File: BraceMatching\CSharpBraceMatcherTests.cs
Web Access
Project: src\src\EditorFeatures\CSharpTest\Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Editor.UnitTests.BraceMatching;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.BraceMatching;
 
[Trait(Traits.Feature, Traits.Features.BraceMatching)]
public sealed class CSharpBraceMatcherTests : AbstractBraceMatcherTests
{
    protected override EditorTestWorkspace CreateWorkspaceFromCode(string code, ParseOptions options)
        => EditorTestWorkspace.CreateCSharp(code, options);
 
    [Fact]
    public Task TestEmptyFile()
        => TestAsync(@"$$", @"");
 
    [Fact]
    public Task TestAtFirstPositionInFile()
        => TestAsync(@"$$public class C { }", @"public class C { }");
 
    [Fact]
    public Task TestAtLastPositionInFile()
        => TestAsync(@"public class C { }$$", @"public class C [|{|] }");
 
    [Fact]
    public Task TestCurlyBrace1()
        => TestAsync(@"public class C $${ }", @"public class C { [|}|]");
 
    [Fact]
    public Task TestCurlyBrace2()
        => TestAsync(@"public class C {$$ }", @"public class C { [|}|]");
 
    [Fact]
    public Task TestCurlyBrace3()
        => TestAsync(@"public class C { $$}", @"public class C [|{|] }");
 
    [Fact]
    public Task TestCurlyBrace4()
        => TestAsync(@"public class C { }$$", @"public class C [|{|] }");
 
    [Fact]
    public Task TestParen1()
        => TestAsync(@"public class C { void Goo$$() { } }", @"public class C { void Goo([|)|] { } }");
 
    [Fact]
    public Task TestParen2()
        => TestAsync(@"public class C { void Goo($$) { } }", @"public class C { void Goo([|)|] { } }");
 
    [Fact]
    public Task TestParen3()
        => TestAsync(@"public class C { void Goo($$ ) { } }", @"public class C { void Goo( [|)|] { } }");
 
    [Fact]
    public Task TestParen4()
        => TestAsync(@"public class C { void Goo( $$) { } }", @"public class C { void Goo[|(|] ) { } }");
 
    [Fact]
    public Task TestParen5()
        => TestAsync(@"public class C { void Goo( )$$ { } }", @"public class C { void Goo[|(|] ) { } }");
 
    [Fact]
    public Task TestParen6()
        => TestAsync(@"public class C { void Goo()$$ { } }", @"public class C { void Goo[|(|]) { } }");
 
    [Fact]
    public Task TestSquareBracket1()
        => TestAsync(@"public class C { int$$[] i; }", @"public class C { int[[|]|] i; }");
 
    [Fact]
    public Task TestSquareBracket2()
        => TestAsync(@"public class C { int[$$] i; }", @"public class C { int[[|]|] i; }");
 
    [Fact]
    public Task TestSquareBracket3()
        => TestAsync(@"public class C { int[$$ ] i; }", @"public class C { int[ [|]|] i; }");
 
    [Fact]
    public Task TestSquareBracket4()
        => TestAsync(@"public class C { int[ $$] i; }", @"public class C { int[|[|] ] i; }");
 
    [Fact]
    public Task TestSquareBracket5()
        => TestAsync(@"public class C { int[ ]$$ i; }", @"public class C { int[|[|] ] i; }");
 
    [Fact]
    public Task TestSquareBracket6()
        => TestAsync(@"public class C { int[]$$ i; }", @"public class C { int[|[|]] i; }");
 
    [Fact]
    public Task TestAngleBracket1()
        => TestAsync(@"public class C { Goo$$<int> f; }", @"public class C { Goo<int[|>|] f; }");
 
    [Fact]
    public Task TestAngleBracket2()
        => TestAsync(@"public class C { Goo<$$int> f; }", @"public class C { Goo<int[|>|] f; }");
 
    [Fact]
    public Task TestAngleBracket3()
        => TestAsync(@"public class C { Goo<int$$> f; }", @"public class C { Goo[|<|]int> f; }");
 
    [Fact]
    public Task TestAngleBracket4()
        => TestAsync(@"public class C { Goo<int>$$ f; }", @"public class C { Goo[|<|]int> f; }");
 
    [Fact]
    public Task TestNestedAngleBracket1()
        => TestAsync(@"public class C { Func$$<Func<int,int>> f; }", @"public class C { Func<Func<int,int>[|>|] f; }");
 
    [Fact]
    public Task TestNestedAngleBracket2()
        => TestAsync(@"public class C { Func<$$Func<int,int>> f; }", @"public class C { Func<Func<int,int>[|>|] f; }");
 
    [Fact]
    public Task TestNestedAngleBracket3()
        => TestAsync(@"public class C { Func<Func$$<int,int>> f; }", @"public class C { Func<Func<int,int[|>|]> f; }");
 
    [Fact]
    public Task TestNestedAngleBracket4()
        => TestAsync(@"public class C { Func<Func<$$int,int>> f; }", @"public class C { Func<Func<int,int[|>|]> f; }");
 
    [Fact]
    public Task TestNestedAngleBracket5()
        => TestAsync(@"public class C { Func<Func<int,int$$>> f; }", @"public class C { Func<Func[|<|]int,int>> f; }");
 
    [Fact]
    public Task TestNestedAngleBracket6()
        => TestAsync(@"public class C { Func<Func<int,int>$$> f; }", @"public class C { Func<Func[|<|]int,int>> f; }");
 
    [Fact]
    public Task TestNestedAngleBracket7()
        => TestAsync(@"public class C { Func<Func<int,int> $$> f; }", @"public class C { Func[|<|]Func<int,int> > f; }");
 
    [Fact]
    public Task TestNestedAngleBracket8()
        => TestAsync(@"public class C { Func<Func<int,int>>$$ f; }", @"public class C { Func[|<|]Func<int,int>> f; }");
 
    [Fact]
    public Task TestString1()
        => TestAsync(@"public class C { string s = $$""Goo""; }", @"public class C { string s = ""Goo[|""|]; }");
 
    [Fact]
    public Task TestString2()
        => TestAsync(@"public class C { string s = ""$$Goo""; }", @"public class C { string s = ""Goo[|""|]; }");
 
    [Fact]
    public Task TestString3()
        => TestAsync(@"public class C { string s = ""Goo$$""; }", @"public class C { string s = [|""|]Goo""; }");
 
    [Fact]
    public Task TestString4()
        => TestAsync(@"public class C { string s = ""Goo""$$; }", @"public class C { string s = [|""|]Goo""; }");
 
    [Fact]
    public Task TestString5()
        => TestAsync(@"public class C { string s = ""Goo$$ ", @"public class C { string s = ""Goo ");
 
    [Fact]
    public Task TestVerbatimString1()
        => TestAsync(@"public class C { string s = $$@""Goo""; }", @"public class C { string s = @""Goo[|""|]; }");
 
    [Fact]
    public Task TestVerbatimString2()
        => TestAsync(@"public class C { string s = @$$""Goo""; }", @"public class C { string s = @""Goo[|""|]; }");
 
    [Fact]
    public Task TestVerbatimString3()
        => TestAsync(@"public class C { string s = @""$$Goo""; }", @"public class C { string s = @""Goo[|""|]; }");
 
    [Fact]
    public Task TestVerbatimString4()
        => TestAsync(@"public class C { string s = @""Goo$$""; }", @"public class C { string s = [|@""|]Goo""; }");
 
    [Fact]
    public Task TestVerbatimString5()
        => TestAsync(@"public class C { string s = @""Goo""$$; }", @"public class C { string s = [|@""|]Goo""; }");
 
    [Fact]
    public Task TestInterpolatedString1()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""$${x}, {y}""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x[|}|], {y}""; }");
 
    [Fact]
    public Task TestInterpolatedString2()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{$$x}, {y}""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x[|}|], {y}""; }");
 
    [Fact]
    public Task TestInterpolatedString3()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x$$}, {y}""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""[|{|]x}, {y}""; }");
 
    [Fact]
    public Task TestInterpolatedString4()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x}$$, {y}""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""[|{|]x}, {y}""; }");
 
    [Fact]
    public Task TestInterpolatedString5()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x}, $${y}""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x}, {y[|}|]""; }");
 
    [Fact]
    public Task TestInterpolatedString6()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x}, {$$y}""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x}, {y[|}|]""; }");
 
    [Fact]
    public Task TestInterpolatedString7()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x}, {y$$}""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x}, [|{|]y}""; }");
 
    [Fact]
    public Task TestInterpolatedString8()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x}, {y}$$""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x}, [|{|]y}""; }");
 
    [Fact]
    public Task TestInterpolatedString9()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $$[||]$""{x}, {y}""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x}, {y}[|""|]; }");
 
    [Fact]
    public Task TestInterpolatedString10()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $[||]$$""{x}, {y}""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $""{x}, {y}[|""|]; }");
 
    [Fact]
    public Task TestInterpolatedString11()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $$[||]$@""{x}, {y}""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $@""{x}, {y}[|""|]; }");
 
    [Fact]
    public Task TestInterpolatedString12()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $[||]$$@""{x}, {y}""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $@""{x}, {y}[|""|]; }");
 
    [Fact]
    public Task TestInterpolatedString13()
        => TestAsync(@"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $@$$""{x}, {y}""; }", @"public class C { void M() { var x = ""Hello""; var y = ""World""; var s = $@""{x}, {y}[|""|]; }");
 
    [Fact]
    public Task TestUtf8String1()
        => TestAsync(@"public class C { string s = $$""Goo""u8; }", @"public class C { string s = ""Goo[|""u8|]; }");
 
    [Fact]
    public Task TestUtf8String2()
        => TestAsync(@"public class C { string s = ""$$Goo""u8; }", @"public class C { string s = ""Goo[|""u8|]; }");
 
    [Fact]
    public Task TestUtf8String3()
        => TestAsync(@"public class C { string s = ""Goo$$""u8; }", @"public class C { string s = [|""|]Goo""u8; }");
 
    [Fact]
    public Task TestUtf8String4()
        => TestAsync(@"public class C { string s = ""Goo""$$u8; }", @"public class C { string s = [|""|]Goo""u8; }");
 
    [Fact]
    public Task TestUtf8String5()
        => TestAsync(@"public class C { string s = ""Goo""u$$8; }", @"public class C { string s = [|""|]Goo""u8; }");
 
    [Fact]
    public Task TestUtf8String6()
        => TestAsync(@"public class C { string s = ""Goo""u8$$; }", @"public class C { string s = [|""|]Goo""u8; }");
 
    [Fact]
    public Task TestVerbatimUtf8String1()
        => TestAsync(@"public class C { string s = $$@""Goo""u8; }", @"public class C { string s = @""Goo[|""u8|]; }");
 
    [Fact]
    public Task TestVerbatimUtf8String2()
        => TestAsync(@"public class C { string s = @$$""Goo""u8; }", @"public class C { string s = @""Goo[|""u8|]; }");
 
    [Fact]
    public Task TestVerbatimUtf8String3()
        => TestAsync(@"public class C { string s = @""$$Goo""u8; }", @"public class C { string s = @""Goo[|""u8|]; }");
 
    [Fact]
    public Task TestVerbatimUtf8String4()
        => TestAsync(@"public class C { string s = @""Goo$$""u8; }", @"public class C { string s = [|@""|]Goo""u8; }");
 
    [Fact]
    public Task TestVerbatimUtf8String5()
        => TestAsync(@"public class C { string s = @""Goo""$$u8; }", @"public class C { string s = [|@""|]Goo""u8; }");
 
    [Fact]
    public Task TestVerbatimUtf8String6()
        => TestAsync(@"public class C { string s = @""Goo""u$$8; }", @"public class C { string s = [|@""|]Goo""u8; }");
 
    [Fact]
    public Task TestVerbatimUtf8String7()
        => TestAsync(@"public class C { string s = @""Goo""u8$$; }", @"public class C { string s = [|@""|]Goo""u8; }");
 
    [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")]
    public Task TestConditionalDirectiveWithSingleMatchingDirective()
        => TestAsync("""
            public class C 
            {
            #if$$ CHK 
            #endif
            }
            """, """
            public class C 
            {
            #if$$ CHK 
            [|#endif|]
            }
            """);
 
    [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")]
    public Task TestConditionalDirectiveWithTwoMatchingDirectives()
        => TestAsync("""
            public class C 
            {
            #if$$ CHK 
            #else
            #endif
            }
            """, """
            public class C 
            {
            #if$$ CHK 
            [|#else|]
            #endif
            }
            """);
 
    [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")]
    public Task TestConditionalDirectiveWithAllMatchingDirectives()
        => TestAsync("""
            public class C 
            {
            #if CHK 
            #elif RET
            #else
            #endif$$
            }
            """, """
            public class C 
            {
            [|#if|] CHK 
            #elif RET
            #else
            #endif
            }
            """);
 
    [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")]
    public Task TestRegionDirective()
        => TestAsync("""
            public class C 
            {
            $$#region test
            #endregion
            }
            """, """
            public class C 
            {
            #region test
            [|#endregion|]
            }
            """);
 
    [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")]
    public Task TestInterleavedDirectivesInner()
        => TestAsync("""
            #define CHK
            public class C 
            {
                void Test()
                {
            #if CHK
            $$#region test
                var x = 5;
            #endregion
            #else
                var y = 6;
            #endif
                }
            }
            """, """
            #define CHK
            public class C 
            {
                void Test()
                {
            #if CHK
            #region test
                var x = 5;
            [|#endregion|]
            #else
                var y = 6;
            #endif
                }
            }
            """);
 
    [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")]
    public Task TestInterleavedDirectivesOuter()
        => TestAsync("""
            #define CHK
            public class C 
            {
                void Test()
                {
            #if$$ CHK
            #region test
                var x = 5;
            #endregion
            #else
                var y = 6;
            #endif
                }
            }
            """, """
            #define CHK
            public class C 
            {
                void Test()
                {
            #if CHK
            #region test
                var x = 5;
            #endregion
            [|#else|]
                var y = 6;
            #endif
                }
            }
            """);
 
    [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")]
    public Task TestUnmatchedDirective1()
        => TestAsync("""
            public class C 
            {
            $$#region test
            }
            """, """
            public class C 
            {
            #region test
            }
            """);
 
    [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7120")]
    public Task TestUnmatchedDirective2()
        => TestAsync("""
            #d$$efine CHK
            public class C 
            {
            }
            """, """
            #define CHK
            public class C 
            {
            }
            """);
 
    [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7534")]
    public Task TestUnmatchedConditionalDirective()
        => TestAsync("""
            class Program
            {
                static void Main(string[] args)
                {#if$$
 
                }
            }
            """, """
            class Program
            {
                static void Main(string[] args)
                {#if
 
                }
            }
            """);
 
    [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/7534")]
    public Task TestUnmatchedConditionalDirective2()
        => TestAsync("""
            class Program
            {
                static void Main(string[] args)
                {#else$$
 
                }
            }
            """, """
            class Program
            {
                static void Main(string[] args)
                {#else
 
                }
            }
            """);
 
    [Fact]
    public Task StartTupleDeclaration()
        => TestAsync(@"public class C { $$(int, int, int, int, int, int, int, int) x; }", @"public class C { (int, int, int, int, int, int, int, int[|)|] x; }", TestOptions.Regular);
 
    [Fact]
    public Task EndTupleDeclaration()
        => TestAsync(@"public class C { (int, int, int, int, int, int, int, int)$$ x; }", @"public class C { [|(|]int, int, int, int, int, int, int, int) x; }", TestOptions.Regular);
 
    [Fact]
    public Task StartTupleLiteral()
        => TestAsync(@"public class C { var x = $$(1, 2, 3, 4, 5, 6, 7, 8); }", @"public class C { var x = (1, 2, 3, 4, 5, 6, 7, 8[|)|]; }", TestOptions.Regular);
 
    [Fact]
    public Task EndTupleLiteral()
        => TestAsync(@"public class C { var x = (1, 2, 3, 4, 5, 6, 7, 8)$$; }", @"public class C { var x = [|(|]1, 2, 3, 4, 5, 6, 7, 8); }", TestOptions.Regular);
 
    [Fact]
    public Task StartNestedTupleLiteral()
        => TestAsync(@"public class C { var x = $$((1, 1, 1), 2, 3, 4, 5, 6, 7, 8); }", @"public class C { var x = ((1, 1, 1), 2, 3, 4, 5, 6, 7, 8[|)|]; }", TestOptions.Regular);
 
    [Fact]
    public Task StartInnerNestedTupleLiteral()
        => TestAsync(@"public class C { var x = ($$(1, 1, 1), 2, 3, 4, 5, 6, 7, 8); }", @"public class C { var x = ((1, 1, 1[|)|], 2, 3, 4, 5, 6, 7, 8); }", TestOptions.Regular);
 
    [Fact]
    public Task EndNestedTupleLiteral()
        => TestAsync(@"public class C { var x = (1, 2, 3, 4, 5, 6, 7, (8, 8, 8))$$; }", @"public class C { var x = [|(|]1, 2, 3, 4, 5, 6, 7, (8, 8, 8)); }", TestOptions.Regular);
 
    [Fact]
    public Task EndInnerNestedTupleLiteral()
        => TestAsync(@"public class C { var x = ((1, 1, 1)$$, 2, 3, 4, 5, 6, 7, 8); }", @"public class C { var x = ([|(|]1, 1, 1), 2, 3, 4, 5, 6, 7, 8); }", TestOptions.Regular);
 
    [Fact]
    public Task TestFunctionPointer()
        => TestAsync(@"public unsafe class C { delegate*<$$int, int> functionPointer; }", @"public unsafe class C { delegate*<int, int[|>|] functionPointer; }", TestOptions.Regular);
}