File: RefactoringHelpers\RefactoringHelpersTests.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.Syntax;
using Microsoft.CodeAnalysis.Editor.UnitTests.RefactoringHelpers;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RefactoringHelpers;
 
public sealed partial class RefactoringHelpersTests : RefactoringHelpersTestBase<CSharpTestWorkspaceFixture>
{
    #region Locations
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestInTokenDirectlyUnderNode()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    {|result:C Local[||]Function(C c)
                    {
                        return null;
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestBeforeTokenDirectlyUnderNode()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    {|result:C [||]LocalFunction(C c)
                    {
                        return null;
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestAfterTokenDirectlyUnderNode()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    {|result:C [||]LocalFunction(C c)
                    {
                        return null;
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingInTokenUnderDifferentNode()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    C LocalFunction(C c)
                    {
                        [||]return null;
                    }
 
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestClimbRightEdge()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    {|result:C LocalFunction(C c)
                    {
                        return null;
                    }[||]|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestClimbLeftEdge()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    {|result:[||]C LocalFunction(C c)
                    {
                        return null;
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestClimbLeftEdgeComments()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    /// <summary>
                    /// Comment1
                    /// </summary>
                    {|result:[||]C LocalFunction(C c)
                    {
                        return null;
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingInAnotherChildNode()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    C LocalFunction(C c)
                    {
                        [||]return null;
                    }
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingInTooFarBeforeInWhitespace()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    [||]
 
                    C LocalFunction(C c)
                    {
                        return null;
                    }
 
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingInWhiteSpaceOnLineWithDifferentStatement()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
 
                    var a = null; [||]
                    C LocalFunction(C c)
                    {
                        return null;
                    }
 
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestNotBeforePrecedingComment()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    [||]//Test comment
                    C LocalFunction(C c)
                    {
                        return null;
                    }
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestBeforeInWhitespace1_OnSameLine()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
            [||]    {|result:C LocalFunction(C c)
                    {
                        return null;
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestBeforeInWhitespace1_OnPreviousLine()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    [||]
                    {|result:C LocalFunction(C c)
                    {
                        return null;
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestBeforeInWhitespace1_NotOnMultipleLinesPrior()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    [||]
 
                    C LocalFunction(C c)
                    {
                        return null;
                    }
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestBeforeInWhitespace2()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                        var a = null;
            [||]        {|result:C LocalFunction(C c)
                    {
                        return null;
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingInNextTokensLeadingTrivia()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
 
                    C LocalFunction(C c)
                    {
                        return null;
                    }
                    [||]
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestInEmptySyntaxNode_AllowEmptyNodesTrue1()
        => TestAsync<ArgumentSyntax>("""
            class C
            {
                void M()
                {
                    N(0, [||]{|result:|}); 
                }
 
                int N(int a, int b, int c)
                {
                }
            }
            """, allowEmptyNodes: true);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestInEmptySyntaxNode_AllowEmptyNodesTrue2()
        => TestAsync<ArgumentSyntax>("""
            class C
            {
                void M()
                {
                    N(0, N(0, [||]{|result:|}, 0)); 
                }
 
                int N(int a, int b, int c)
                {
                }
            }
            """, allowEmptyNodes: true);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestInEmptySyntaxNode_AllowEmptyNodesFalse1()
        => TestMissingAsync<ArgumentSyntax>("""
            class C
            {
                void M()
                {
                    N(0, [||], 0)); 
                }
 
                int N(int a, int b, int c)
                {
                }
            }
            """, allowEmptyNodes: false);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestInEmptySyntaxNode_AllowEmptyNodesFalse2()
        => TestAsync<ArgumentSyntax>("""
            class C
            {
                void M()
                {
                    N(0, {|result:N(0, [||], 0)|}); 
                }
 
                int N(int a, int b, int c)
                {
                }
            }
            """, allowEmptyNodes: false);
 
    #endregion
 
    #region Selections
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestSelectedTokenDirectlyUnderNode()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    {|result:C [|LocalFunction|](C c)
                    {
                        return null;
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestPartiallySelectedTokenDirectlyUnderNode()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    {|result:C Lo[|calFunct|]ion(C c)
                    {
                        return null;
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestSelectedMultipleTokensUnderNode()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    {|result:[|C LocalFunction(C c)|]
                    {
                        return null;
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingSelectedMultipleTokensWithLowerCommonAncestor()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    C LocalFunction(C c)
                    [|{
                        return null;
                    }|]
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingSelectedLowerNode()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    [|C|] LocalFunction(C c)
                    {
                        return null;
                    }
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingSelectedWhitespace()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    C[| |]LocalFunction(C c)
                    {
                        return null;
                    }
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingSelectedWhitespace2()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                   [| |]C LocalFunction(C c)
                    {
                        return null;
                    }
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestCompleteSelection()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    {|result:[|C LocalFunction(C c)
                    {
                        return null;
                    }|]|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestOverSelection()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    [|
 
                    {|result:C LocalFunction(C c)
                    {
                        return null;
                    }|}
 
                    |]var a = new object();
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestOverSelectionComments()
        => TestAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
 
                    // Co[|mment1
                    {|result:C LocalFunction(C c)
                    {
                        return null;
                    }|}|]
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingOverSelection()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
                    [|
                    C LocalFunction(C c)
                    {
                        return null;
                    }
                    v|]ar a = new object();
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingSelectionBefore()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            class C
            {
                void M()
                {
 
             [|       |]C LocalFunction(C c)
                    {
                        return null;
                    }
                    var a = new object();
                }
            }
            """);
 
    #endregion
 
    #region IsUnderselected
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38708")]
    public Task TestUnderselectionOnSemicolon()
        => TestNotUnderselectedAsync<ExpressionSyntax>("""
            class Program
            {
                static void Main()
                {
                    {|result:Main()|}[|;|]
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38708")]
    public Task TestUnderselectionBug1()
        => TestNotUnderselectedAsync<ExpressionSyntax>("""
            class Program
            {
                public static void Method()
                {
                    //[|>
                    var str = {|result:" <|] aaa"|};
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38708")]
    public Task TestUnderselectionBug2()
        => TestNotUnderselectedAsync<ExpressionSyntax>("""
            class C {
                public void M()
                {
                    Console.WriteLine("Hello world");[|
                    {|result:Console.WriteLine(new |]C())|};
                    }
                }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38708")]
    public Task TestUnderselection()
        => TestNotUnderselectedAsync<BinaryExpressionSyntax>("""
            class C {
                public void M()
                {
                    bool a = {|result:[|true || false || true|]|};
                }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38708")]
    public Task TestUnderselection2()
        => TestUnderselectedAsync<BinaryExpressionSyntax>("""
            class C {
                public void M()
                {
                    bool a = true || [|false || true|] || true;
                }
            """);
    #endregion
 
    #region Attributes
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37584")]
    public Task TestMissingEmptyMember()
        => TestMissingAsync<MethodDeclarationSyntax>("""
            using System;
            public class Class1
            {
                [][||]
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38502")]
    public Task TestIncompleteAttribute()
        => TestAsync<MethodDeclarationSyntax>("""
            using System;
            public class Class1
            {
                {|result:void foo([[||]bar) {}|}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/38502")]
    public Task TestIncompleteAttribute2()
        => TestAsync<MethodDeclarationSyntax>("""
            using System;
            public class Class1
            {
                {|result:void foo([[||]Class1 arg1) {}|}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37837")]
    public Task TestEmptyParameter()
        => TestAsync<ParameterSyntax>("""
            using System;
            public class TestAttribute : Attribute { }
            public class Class1
            {
                static void foo({|result:[Test][||]
            |}    {
 
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37584")]
    public Task TestMissingEmptyMember2()
        => TestMissingAsync<MethodDeclarationSyntax>("""
            using System;
            public class Class1
            {
                [||]// Comment 
                []
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/37584")]
    public Task TestEmptyAttributeList()
        => TestAsync<MethodDeclarationSyntax>("""
            using System;
            public class Class1
            {
                {|result:[]
                [||]void a() {}|}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestClimbLeftEdgeBeforeAttribute()
        => TestAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
 
                // Comment1
                [||]{|result:[Test]
                void M()
                {
                }|}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestClimbLeftEdgeAfterAttribute()
        => TestAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
 
                {|result:[Test]
                [||]void M()
                {
                }|}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestClimbLeftEdgeAfterAttributeComments()
        => TestAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
 
                // Comment1
                {|result:[Test]
                // Comment2
                [||]void M()
                {
                }|}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestClimbLeftEdgeAfterAttributes()
        => TestAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                class Test2Attribute : Attribute { }
 
                // Comment1
                {|result:[Test]
                [Test2]
                // Comment2
                [||]void M()
                {
                }|}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingBetweenAttributes()
        => TestMissingAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                class Test2Attribute : Attribute { }
 
                [Test]
                [||][Test2]
                void M()
                {
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingBetweenInAttributes()
        => TestMissingAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
 
                [[||]Test]
                void M()
                {
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingSelectedAttributes()
        => TestMissingAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                class Test2Attribute : Attribute { }
 
                [|[Test]
                [Test2]|]
                void M()
                {
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingSelectedAttribute()
        => TestMissingAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
 
                [|[Test]|]
                void M()
                {
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestSelectedWholeNodeAndAttributes()
        => TestAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                class Test2Attribute : Attribute { }
 
                // Comment1
                [|{|result:[Test]
                [Test2]
                // Comment2
                void M()
                {
                }|}|]
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestSelectedWholeNodeWithoutAttributes()
        => TestAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                class Test2Attribute : Attribute { }
 
                // Comment1
                {|result:[Test]
                [Test2]
                // Comment2
                [|void M()
                {
                }|]|}
            }
            """);
    #endregion
 
    #region Extractions general
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestExtractionsClimbing()
        => TestAsync<ObjectCreationExpressionSyntax>("""
            using System;
            class C
            {
                void M()
                {
                    var a = {|result:new object()|};[||]
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingExtractHeaderForSelection()
        => TestMissingAsync<PropertyDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                [Test] public [|int|] a { get; set; }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public async Task TestMultipleExtractions()
    {
        await TestAsync<LocalDeclarationStatementSyntax>(GetTestText("{|result:string name = \"\", b[||]b = null;|}"));
        await TestAsync<VariableDeclaratorSyntax>(GetTestText("string name = \"\", {|result:bb[||] = null|};"));
 
        static string GetTestText(string data)
        {
            return """
                class C
                {
                    void M()
                    {
                        C LocalFunction(C c)
                        {
                """ + data + """
                return null;
                        }
                        var a = new object();
                    }
                }
                """;
 
        }
    }
    #endregion
 
    #region Extractions
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestExtractFromDeclaration()
        => TestAsync<ObjectCreationExpressionSyntax>("""
            using System;
            class C
            {
                void M()
                {
                    [|var a = {|result:new object()|};|]
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestExtractFromDeclaration2()
        => TestAsync<ObjectCreationExpressionSyntax>("""
            using System;
            class C
            {
                void M()
                {
                    var a = [|{|result:new object()|};|]
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestExtractFromAssignment()
        => TestAsync<ObjectCreationExpressionSyntax>("""
            using System;
            class C
            {
                void M()
                {
                    object a;
                    a = [|{|result:new object()|};|]
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestExtractFromDeclarator()
        => TestAsync<ObjectCreationExpressionSyntax>("""
            using System;
            class C
            {
                void M()
                {
                    var [|a = {|result:new object()|}|];
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestExtractFromDeclarator2()
        => TestAsync<LocalDeclarationStatementSyntax>("""
            using System;
            class C
            {
                void M()
                {
                    {|result:var [|a = new object()|];|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestExtractInHeaderOfProperty()
        => TestAsync<PropertyDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                {|result:[Test] public i[||]nt a { get; set; }|}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingExtractNotInHeaderOfProperty()
        => TestMissingAsync<PropertyDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                [Test] public int a { [||]get; set; }
            }
            """);
 
    #endregion
 
    #region Headers & holes
    [Theory]
    [InlineData("var aa = nul[||]l;")]
    [InlineData("var aa = n[||]ull;")]
    [InlineData("string aa = null, bb = n[||]ull;")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public async Task TestMissingInHeaderHole(string data)
    {
        var testText = """
            class C
            {
                void M()
                {
                    C LocalFunction(C c)
                    {
            """ + data + """
            return null;
                    }
                    var a = new object();
                }
            }
            """;
        await TestMissingAsync<LocalDeclarationStatementSyntax>(testText);
    }
 
    [Theory]
    [InlineData("{|result:[||]var aa = null;|}")]
    [InlineData("{|result:var aa = [||]null;|}")]
    [InlineData("{|result:var aa = null[||];|}")]
    [InlineData("{|result:string aa = null, b[||]b = null;|}")]
    [InlineData("{|result:string aa = null, bb = [||]null;|}")]
    [InlineData("{|result:string aa = null, bb = null[||];|}")]
    [InlineData("{|result:string aa = null, bb = null;[||]|}")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public async Task TestInHeader(string data)
    {
        var testText = """
            class C
            {
                void M()
                {
                    C LocalFunction(C c)
                    {
            """ + data + """
            return null;
                    }
                    var a = new object();
                }
            }
            """;
        await TestAsync<LocalDeclarationStatementSyntax>(testText);
    }
    #endregion
 
    #region TestHidden
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestNextToHidden()
        => TestAsync<LocalFunctionStatementSyntax>("""
            #line default
            class C
            {
                void M()
                {
            #line hidden
                    var a = b;
            #line default
                    {|result:C [||]LocalFunction(C c)
                    {
                        return null;
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestNextToHidden2()
        => TestAsync<LocalFunctionStatementSyntax>("""
            #line default
            class C
            {
                void M()
                {
            #line hidden
                    var a = b;
            #line default
                    {|result:C [||]LocalFunction(C c)
                    {
                        return null;
                    }|}
            #line hidden
                    var a = b;
            #line default
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingHidden()
        => TestMissingAsync<LocalFunctionStatementSyntax>("""
            #line default
            class C
            {
                void M()
                {
            #line hidden
                    C LocalFunction(C c)
            #line default
                    {
                        return null;
                    }[||]
                }
            }
            """);
    #endregion
 
    #region Test predicate
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingPredicate()
        => TestMissingAsync<ArgumentSyntax>("""
            class C
            {
                void M()
                {
                    N([||]2+3);
                }
 
                void N(int a)
                {
                }
            }
            """, n => n.Parent is TupleExpressionSyntax);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestArgument()
        => TestAsync<ArgumentSyntax>("""
            class C
            {
                void M()
                {
                    N({|result:[||]2+3|});
                }
 
                void N(int a)
                {
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestPredicate()
        => TestAsync<ArgumentSyntax>("""
            class C
            {
                void M()
                {
                    var a = ({|result:[||]2 + 3|}, 2 + 3);
                }
            }
            """, n => n.Parent is TupleExpressionSyntax);
    #endregion
 
    #region Test arguments
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestArgumentsExtractionsInInitializer()
        => TestAsync<ParameterSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public C({|result:[Test]int a = [||]42|}, int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingArgumentsExtractionsSelectInitializer()
        => TestMissingAsync<ParameterSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public C([Test]int a = [|42|], int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingArgumentsExtractionsSelectComma()
        => TestMissingAsync<ParameterSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public C([Test]int a = 42[|,|] int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingArgumentsExtractionsInAttributes()
        => TestMissingAsync<ParameterSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public C([[||]Test]int a = 42, int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingArgumentsExtractionsSelectType1()
        => TestMissingAsync<ParameterSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public C([Test][|int|] a = 42, int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingArgumentsExtractionsSelectType2()
        => TestMissingAsync<ParameterSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public C([Test][|C|] a = null, int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestArgumentsExtractionsAtTheEnd()
        => TestAsync<ParameterSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public C({|result:[Test]int a = 42[||]|}, int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestArgumentsExtractionsBefore()
        => TestAsync<ParameterSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public C([||]{|result:[Test]int a = 42|}, int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestArgumentsExtractionsSelectParamName()
        => TestAsync<ParameterSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public C({|result:[Test]int [|a|] = 42|}, int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestArgumentsExtractionsSelectParam1()
        => TestAsync<ParameterSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public C({|result:[Test][|int a|] = 42|}, int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestArgumentsExtractionsSelectParam2()
        => TestAsync<ParameterSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public C([|{|result:[Test]int a = 42|}|], int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestArgumentsExtractionsSelectParam3()
        => TestAsync<ParameterSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public C({|result:[Test][|int a = 42|]|}, int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestArgumentsExtractionsInHeader()
        => TestAsync<ParameterSyntax>("""
            using System;
            class CC
            {
                class TestAttribute : Attribute { }
                public CC({|result:[Test]C[||]C a = 42|}, int b = 41) {}
            }
            """);
 
    #endregion
 
    #region Test methods
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingMethodExplicitInterfaceSelection()
        => TestMissingAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                public void [|I|].A([Test]int a = 42, int b = 41) {}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMethodCaretBeforeInterfaceSelection()
        => TestAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                {|result:public void [||]I.A([Test]int a = 42, int b = 41) {}|}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMethodNameAndExplicitInterfaceSelection()
        => TestAsync<MethodDeclarationSyntax>("""
            using System;
            class C
            {
                class TestAttribute : Attribute { }
                {|result:public void [|I.A|]([Test]int a = 42, int b = 41) {}|}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMethodInHeader()
        => TestAsync<MethodDeclarationSyntax>("""
            using System;
            class CC
            {
                class TestAttribute : Attribute { }
                {|result:public C[||]C I.A([Test]int a = 42, int b = 41) { return null; }|}
            }
            """);
 
    #endregion
 
    #region TestLocalDeclaration
    [Theory]
    [InlineData("{|result:v[||]ar name = \"\";|}")]
    [InlineData("{|result:string name = \"\", b[||]b = null;|}")]
    [InlineData("{|result:var[||] name = \"\";|}")]
    [InlineData("{|result:var [||]name = \"\";|}")]
    [InlineData("{|result:var na[||]me = \"\";|}")]
    [InlineData("{|result:var name[||] = \"\";|}")]
    [InlineData("{|result:var name [||]= \"\";|}")]
    [InlineData("{|result:var name =[||] \"\";|}")]
    [InlineData("{|result:var name = [||]\"\";|}")]
    [InlineData("{|result:[|var name = \"\";|]|}")]
    [InlineData("{|result:var name = \"\"[||];|}")]
    [InlineData("{|result:var name = \"\";[||]|}")]
    [InlineData("{|result:var name = \"\"[||]|}")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public async Task TestLocalDeclarationInHeader(string data)
    {
        var testText = """
            class C
            {
                void M()
                {
 
                    C LocalFunction(C c)
                    {
            """ + data + """
            return null;
                    }
                    var a = new object();
                }
            }
            """;
        await TestAsync<LocalDeclarationStatementSyntax>(testText);
    }
 
    [Theory]
    [InlineData("var name = \"[||]\";")]
    [InlineData("var name=[|\"\"|];")]
    [InlineData("string name = \"\", bb = n[||]ull;")]
    [WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public async Task TestMissingLocalDeclarationCaretInHeader(string data)
    {
        var testText = """
            class C
            {
                void M()
                {
 
                    C LocalFunction(C c)
                    {
            """ + data + """
            return null;
                    }
                    var a = new object();
                }
            }
            """;
        await TestMissingAsync<LocalDeclarationStatementSyntax>(testText);
    }
    #endregion
 
    #region Test Ifs
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMultiline_IfElseIfElseSelection1()
        => TestAsync<IfStatementSyntax>(
            """
            class A
            {
                void Goo()
                {
                    {|result:[|if (a)
                    {
                        a();
                    }|]
                    else if (b)
                    {
                        b();
                    }
                    else
                    {
                        c();
                    }|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMultiline_IfElseIfElseSelection2()
        => TestAsync<IfStatementSyntax>(
            """
            class A
            {
                void Goo()
                {
                    {|result:[|if (a)
                    {
                        a();
                    }
                    else if (b)
                    {
                        b();
                    }
                    else
                    {
                        c();
                    }|]|}
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingMultiline_IfElseIfElseSelection()
        => TestMissingAsync<IfStatementSyntax>(
            """
            class A
            {
                void Goo()
                {
                    if (a)
                    {
                        a();
                    }
                    [|else if (b)
                    {
                        b();
                    }
                    else
                    {
                        c();
                    }|]
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/78749")]
    public Task TestMalformedIfBlock1()
        => TestAsync<IfStatementSyntax>(
            """
            {
                {|result:[||]if (devsBad)
                    [crash]
                else return;|}
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/78749")]
    public Task TestMalformedIfBlock2()
        => TestAsync<IfStatementSyntax>(
            """
            {
                if (devsBad)
                    {|result:[|[crash]
                else return;|]|}
            }
            """);
 
    #endregion
 
    #region Test Deep in expression
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestDeepIn()
        => TestAsync<ArgumentSyntax>("""
            class C
            {
                void M()
                {
                    N({|result:2+[||]3+4|});
                }
 
                void N(int a)
                {
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestMissingDeepInSecondRow()
        => TestMissingAsync<ArgumentSyntax>("""
            class C
            {
                void M()
                {
                    N(2
                        +[||]3+4);
                }
 
                void N(int a)
                {
                }
            }
            """);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35525")]
    public Task TestDeepInExpression()
        => TestAsync<ArgumentSyntax>("""
            class C
            {
                void M()
                {
                    var b = ({|result:N(2[||])|}, 0);
                }
 
                int N(int a)
                {
                    return a;
                }
            }
            """, predicate: n => n.Parent is TupleExpressionSyntax);
    #endregion
}