File: Debugging\ProximityExpressionsGetterTests.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.
 
#nullable disable
 
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Debugging;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Debugging;
 
[UseExportProvider]
[Trait(Traits.Feature, Traits.Features.DebuggingProximityExpressions)]
public sealed partial class ProximityExpressionsGetterTests
{
    private static string s_lazyTestFileContent;
 
    private static string GetTestFileContent()
    {
        if (s_lazyTestFileContent == null)
        {
            using var stream = typeof(ProximityExpressionsGetterTests).Assembly.GetManifestResourceStream("Debugging/ProximityExpressionsGetterTestFile.cs");
            using var reader = new StreamReader(stream, Encoding.UTF8);
            s_lazyTestFileContent = reader.ReadToEnd();
        }
 
        return s_lazyTestFileContent;
    }
 
    private static SyntaxTree GetTree()
        => SyntaxFactory.ParseSyntaxTree(GetTestFileContent());
 
    private static SyntaxTree GetTreeFromCode(string code)
        => SyntaxFactory.ParseSyntaxTree(code);
 
    [Fact]
    public void TestWithinStatement_1()
    {
        var tree = GetTreeFromCode("""
            using System;
            using System.Collections.Generic;
 
            namespace ConsoleApplication1
            {
                class Program
                {
                    static void Main(string[] args)
                    {
                        var xx = true;
                        var yy = new List<bool>();
                        yy.Add(xx?true:false);
                    }
                }
            }
            """);
        var terms = CSharpProximityExpressionsService.GetProximityExpressions(tree, 245, cancellationToken: default);
        Assert.NotNull(terms);
        AssertEx.Equal((string[])["yy", "xx"], terms);
    }
 
    private static async Task TestProximityExpressionGetterAsync(
        string markup,
        Func<CSharpProximityExpressionsService, Document, int, Task> continuation)
    {
        using var workspace = EditorTestWorkspace.CreateCSharp(markup);
        var testDocument = workspace.Documents.Single();
        var caretPosition = testDocument.CursorPosition.Value;
        var snapshot = testDocument.GetTextBuffer().CurrentSnapshot;
        var languageDebugInfo = new CSharpLanguageDebugInfoService();
        var document = workspace.CurrentSolution.GetDocument(testDocument.Id);
 
        var proximityExpressionsGetter = new CSharpProximityExpressionsService();
 
        await continuation(proximityExpressionsGetter, document, caretPosition);
    }
 
    private static async Task TestTryDoInMainAsync(string body, bool topLevelStatement, params string[] expectedTerms)
    {
        string input;
        if (topLevelStatement)
        {
            input = body;
        }
        else
        {
            input = $$"""
                class Program
                {
                    static void Main(string[] args)
                    {
                {{string.Join(Environment.NewLine, body.ReplaceLineEndings("\n").Split('\n').Select(line => line == "" ? line : $"        {line}"))}}
                    }
                }
                """;
        }
 
        await TestTryDoAsync(input, expectedTerms);
    }
 
    private static Task TestTryDoAsync(string input, params string[] expectedTerms)
        => TestProximityExpressionGetterAsync(input, async (getter, document, position) =>
        {
            var actualTerms = await getter.GetProximityExpressionsAsync(document, position, CancellationToken.None);
            Assert.True(actualTerms is null or { Count: > 0 });
            AssertEx.Equal(expectedTerms, actualTerms ?? Array.Empty<string>());
        });
 
    private static Task TestIsValidAsync(string input, string expression, bool expectedValid)
        => TestProximityExpressionGetterAsync(input, async (getter, semanticSnapshot, position) =>
        {
            var actualValid = await getter.IsValidAsync(semanticSnapshot, position, expression, CancellationToken.None);
            Assert.Equal(expectedValid, actualValid);
        });
 
    [Fact]
    public async Task TestTryDo1()
        => await TestTryDoAsync("class Class { void Method() { string local;$$ } }", "local", "this");
 
    [Fact]
    public async Task TestNoParentToken()
        => await TestTryDoAsync("$$");
 
    [Fact]
    public async Task TestIsValid1()
        => await TestIsValidAsync("class Class { void Method() { string local;$$ } }", "local", true);
 
    [Fact]
    public Task TestIsValidWithDiagnostics()
        => TestIsValidAsync("class Class { void Method() { string local; } $$}", "local", false);
 
    [Fact]
    public async Task TestIsValidReferencingLocalBeforeDeclaration()
        => await TestIsValidAsync("class Class { void Method() { $$int i; int j; } }", "j", false);
 
    [Fact]
    public async Task TestIsValidReferencingUndefinedVariable()
        => await TestIsValidAsync("class Class { void Method() { $$int i; int j; } }", "k", false);
 
    [Fact]
    public async Task TestIsValidNoTypeSymbol()
        => await TestIsValidAsync("namespace Namespace$$ { }", "goo", false);
 
    [Fact]
    public async Task TestIsValidLocalAfterPosition()
        => await TestIsValidAsync("class Class { void Method() { $$ int i; string local; } }", "local", false);
 
    [Fact]
    public Task TestThis()
        => TestTryDoAsync("""
            class Class 
            {
                public Class() : this(true) 
                {
                    base.ToString();
                    this.ToString()$$;
                }
            }
            """, "this");
 
    [Theory, CombinatorialData]
    public async Task TestArrayCreationExpression(bool topLevelStatement)
    {
        if (!topLevelStatement)
        {
            await TestTryDoAsync("""
                class Class 
                {
                    void Method()
                    {
                        int[] i = new int[] { 3 }$$;
                    }
                }
                """, "i", "this");
        }
 
        await TestTryDoInMainAsync("""
            int[] i = new int[] { 3 }$$;
            """, topLevelStatement, "i", "args");
    }
 
    [Theory, CombinatorialData]
    public async Task TestPostfixUnaryExpressionSyntax(bool topLevelStatement)
    {
        if (!topLevelStatement)
        {
            await TestTryDoAsync("""
                class Class 
                {
                    void Method()
                    {
                        int i = 3;
                        i++$$;
                    }
                }
                """, "i", "this");
        }
 
        await TestTryDoInMainAsync("""
            int i = 3;
            i++$$;
            """, topLevelStatement, "i");
    }
 
    [Theory, CombinatorialData]
    public async Task TestLabeledStatement(bool topLevelStatement)
    {
        if (!topLevelStatement)
        {
            await TestTryDoAsync("""
                class Class 
                {
                    void Method()
                    {
                        label: int i = 3;
                        label2$$: i++;
                    }
                }
                """, "i", "this");
        }
 
        await TestTryDoInMainAsync("""
            label: int i = 3;
            label2$$: i++;
            """, topLevelStatement, "i");
    }
 
    [Theory, CombinatorialData]
    public Task TestThrowStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            e = new Exception();
            thr$$ow e;
            """, topLevelStatement, "e");
 
    [Theory, CombinatorialData]
    public Task TestDoStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            do$$ { } while (true);
            """, topLevelStatement, "args");
 
    [Theory, CombinatorialData]
    public Task TestLockStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            lock(typeof(Cl$$ass)) { };
            """, topLevelStatement, "args");
 
    [Theory, CombinatorialData]
    public Task TestWhileStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            while(DateTime.Now <$$ DateTime.Now) { };
            """, topLevelStatement, "DateTime", "DateTime.Now", "args");
 
    [Theory, CombinatorialData]
    public Task TestForStatementWithDeclarators(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            for(int i = 0; i < 10; i$$++) { }
            """, topLevelStatement, "i", "args");
 
    [Theory, CombinatorialData]
    public Task TestForStatementWithInitializers(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int i = 0;
            for(i = 1; i < 10; i$$++) { }
            """, topLevelStatement, "i");
 
    [Theory, CombinatorialData]
    public async Task TestUsingStatement(bool topLevelStatement)
    {
        if (!topLevelStatement)
        {
            await TestTryDoAsync("""
                class Class 
                {
                    void Method()
                    {
                        using (FileStream fs = new FileStream($$)) { }
                    }
                }
                """, "this");
        }
 
        await TestTryDoInMainAsync("""
            using (FileStream fs = new FileStream($$)) { }
            """, topLevelStatement, "args");
    }
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538879")]
    public Task TestValueInPropertySetter()
        => TestTryDoAsync("""
            class Class 
            {
                string Name
                {
                    get { return ""; }
                    set { $$ }
                }
            }
            """, "this", "value");
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/48504")]
    public Task TestValueInPropertyInit()
        => TestTryDoAsync("""
            class Class
            {
                string Name
                {
                    get { return ""; }
                    init { $$ }
                }
            }
            """, "this", "value");
 
    [Fact]
    public Task TestValueInEventAdd()
        => TestTryDoAsync("""
            class Class 
            {
                event Action Event
                {
                    add { $$ }
                    set { }
                }
            }
            """, "this", "value");
 
    [Fact]
    public Task TestValueInEventRemove()
        => TestTryDoAsync("""
            class Class 
            {
                event Action Event
                {
                    add { }
                    remove { $$ }
                }
            }
            """, "this", "value");
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538880")]
    public Task TestValueInIndexerSetter()
        => TestTryDoAsync("""
            class Class 
            {
                string this[int index]
                {
                    get { return ""; }
                    set { $$ }
                }
            }
            """, "index", "this", "value");
 
    [Theory, CombinatorialData]
    [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538881")]
    public async Task TestCatchBlock(bool topLevelStatement)
    {
        if (!topLevelStatement)
        {
            await TestTryDoAsync("""
                class Class 
                {
                    void Method()
                    {
                        try { }
                        catch(Exception ex) { int $$ }
                    }
                }
                """, "ex", "this");
        }
 
        await TestTryDoInMainAsync("""
            try { }
            catch(Exception ex) { int $$ }
            """, topLevelStatement, "ex");
    }
 
    [Theory, CombinatorialData]
    [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538881")]
    public async Task TestCatchBlockEmpty_OpenBrace(bool topLevelStatement)
    {
        if (!topLevelStatement)
        {
            await TestTryDoAsync("""
                class Class 
                {
                    void Method()
                    {
                        try { }
                        catch(Exception ex) { $$ }
                    }
                }
                """, "ex", "this");
        }
 
        await TestTryDoInMainAsync("""
            try { }
            catch(Exception ex) { $$ }
            """, topLevelStatement, "ex");
    }
 
    [Theory, CombinatorialData]
    public async Task TestCatchBlockEmpty_CloseBrace(bool topLevelStatement)
    {
        if (!topLevelStatement)
        {
            await TestTryDoAsync("""
                class Class 
                {
                    void Method()
                    {
                        try { }
                        catch(Exception ex) { } $$ 
                    }
                }
                """, "this");
        }
 
        await TestTryDoInMainAsync("""
            try { }
            catch(Exception ex) { } $$
            """, topLevelStatement);
    }
 
    [Theory, CombinatorialData]
    [WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538874")]
    public async Task TestObjectCreation(bool topLevelStatement)
    {
        if (!topLevelStatement)
        {
            await TestTryDoAsync("""
                class Class 
                {
                    void Method()
                    {
                        $$Goo(new Bar(a).Baz);
                    }
                }
                """, "a", "new Bar(a).Baz", "Goo", "this");
        }
 
        await TestTryDoInMainAsync("""
            $$Goo(new Bar(a).Baz);
            """, topLevelStatement, "a", "new Bar(a).Baz", "Goo", "args");
    }
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538874")]
    public Task Test2()
        => TestIsValidAsync("""
            class D
            {
               private static int x;
            }
 
            class Class 
            {
                void Method()
                {
                    $$Goo(D.x);
                }
            }
            """, "D.x", false);
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538890")]
    public Task TestArrayCreation()
        => TestTryDoAsync("""
            class Class 
            {
                int a;
                void Method()
                {
                    $$new int[] { a };
                }
            }
            """, "this");
 
    [Fact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/751141")]
    public Task Bug751141()
        => TestTryDoAsync("""
            class Program
            {
                double m_double = 1.1;
                static void Main(string[] args)
                {
                    new Program().M();
                }
                void M()
                {
                    int local_int = (int)m_double;
                    $$System.Diagnostics.Debugger.Break();
                }
            }
            """, "System.Diagnostics.Debugger", "local_int", "m_double", "(int)m_double", "this");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ForLoopExpressionsInFirstStatementOfLoop1(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            for(int i = 0; i < 5; i++)
            {
                $$var x = 8;
            }
            """, topLevelStatement, "i", "x");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ForLoopExpressionsInFirstStatementOfLoop2(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int i = 0, j = 0, k = 0, m = 0, n = 0;
 
            for(i = 0; j < 5; k++)
            {
                $$m = 8;
                n = 7;
            }
            """, topLevelStatement, "m", "i", "j", "k");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ForLoopExpressionsInFirstStatementOfLoop3(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int i = 0, j = 0, k = 0, m = 0;
 
            for(i = 0; j < 5; k++)
            {
                var m = 8;
                $$var n = 7;
            }
            """, topLevelStatement, "m", "n");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ForLoopExpressionsInFirstStatementOfLoop4(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int i = 0, j = 0, k = 0, m = 0;
 
            for(i = 0; j < 5; k++)
                $$m = 8;
            """, topLevelStatement, "m", "i", "j", "k");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ForEachLoopExpressionsInFirstStatementOfLoop1(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            foreach (var x in new int[] { 1, 2, 3 })
            {
                $$var z = 0;
            }
            """, topLevelStatement, "x", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ForEachLoopExpressionsInFirstStatementOfLoop2(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            foreach (var x in new int[] { 1, 2, 3 })
                $$var z = 0;
            """, topLevelStatement, "x", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterForLoop1(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0;
 
            for (a = 5; b < 1; b++)
            {
                c = 8;
                d = 9; // included
            }
 
            $$var z = 0;
            """, topLevelStatement, "a", "b", "d", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterForLoop2(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0;
 
            for (a = 5; b < 1; b++)
            {
                c = 8;
                int d = 9; // not included
            }
 
            $$var z = 0;
            """, topLevelStatement, "a", "b", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterForEachLoop(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0;
 
            foreach (var q in new int[] {1, 2, 3})
            {
                c = 8;
                d = 9; // included
            }
 
            $$var z = 0;
            """, topLevelStatement, "q", "d", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterNestedForLoop(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
 
            for (a = 5; b < 1; b++)
            {
                c = 8;
                d = 9;
                for (a = 7; b < 9; b--)
                {
                    e = 8;
                    f = 10; // included
                }
            }
 
            $$var z = 0;
            """, topLevelStatement, "a", "b", "f", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterCheckedStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
 
            checked
            {
                a = 7;
                b = 0; // included
            }
 
            $$var z = 0;
            """, topLevelStatement, "b", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterUncheckedStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
 
            unchecked
            {
                a = 7;
                b = 0; // included
            }
 
            $$var z = 0;
            """, topLevelStatement, "b", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterIfStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
 
            if (a == 0)
            {
                c = 8; 
                d = 9; // included
            }
 
            $$var z = 0;
            """, topLevelStatement, "a", "d", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterIfStatementWithElse(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
 
            if (a == 0)
            {
                c = 8; 
                d = 9; // included
            }
            else
            {
                e = 1;
                f = 2; // included
            }
 
            $$var z = 0;
            """, topLevelStatement, "a", "d", "f", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterLockStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0;
 
            lock (new object())
            {
                a = 2;
                b = 3; // included
            }
 
            $$var z = 0;
            """, topLevelStatement, "b", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterSwitchStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0;
 
            switch(a)
            {
                case 1:
                    b = 7;
                    c = 8; // included
                    break;
                case 2:
                    d = 9;
                    e = 10; // included
                    break;
                default:
                    f = 1;
                    g = 2; // included
                    break;
            }
 
            $$var z = 0;
            """, topLevelStatement, "a", "c", "e", "g", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterTryStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0;
 
            try
            {
                a = 2;
                b = 3; // included
            }
            catch (System.DivideByZeroException)
            {
                c = 2;
                d = 5; // included
            }
            catch (System.EntryPointNotFoundException)
            {
                e = 8;
                f = 9; // included
            }
 
            $$var z = 0;
            """, topLevelStatement, "b", "d", "f", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterTryStatementWithFinally(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0;
 
            try
            {
                a = 2;
                b = 3;
            }
            catch (System.DivideByZeroException)
            {
                c = 2;
                d = 5;
            }
            catch (System.EntryPointNotFoundException)
            {
                e = 8;
                f = 9;
            }
            finally
            {
                g = 2; // included
            }
 
            $$var z = 0;
            """, topLevelStatement, "g", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterUsingStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0;
 
            using (null as System.IDisposable)
            {
                a = 4;
                b = 8; // Included
            }
 
            $$var z = 0;
            """, topLevelStatement, "b", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/775161"), CombinatorialData]
    public Task ExpressionsAfterWhileStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 0, b = 0, c = 0, d = 0, e = 0, f = 0, g = 0;
 
            while (a < 5)
            {
                a++;
                b = 8; // Included
            }
 
            $$var z = 0;
            """, topLevelStatement, "a", "b", "z");
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/778215"), CombinatorialData]
    public Task ExpressionsInParenthesizedExpressions(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int i = 0, j = 0, k = 0, m = 0;
            int flags = 7;
 
            if((flags & i) == k)
            {
                $$ m = 8;
            }
            """, topLevelStatement, "m", "flags", "i", "k");
 
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/58337"), CombinatorialData]
    public Task ExpressionsInTopLevelStatement(bool topLevelStatement)
        => TestTryDoInMainAsync("""
            int a = 1;
            int b = 2;
            $$ Console.WriteLine("Hello, World!");
            """, topLevelStatement, "Console", "b");
}