File: ConvertAnonymousType\ConvertAnonymousTypeToTupleTests.cs
Web Access
Project: src\src\Features\CSharpTest\Microsoft.CodeAnalysis.CSharp.Features.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Features.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.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.ConvertAnonymousType;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ConvertAnonymousType;
 
[Trait(Traits.Feature, Traits.Features.CodeActionsConvertAnonymousTypeToTuple)]
public sealed class ConvertAnonymousTypeToTupleTests : AbstractCSharpCodeActionTest_NoEditor
{
    protected override CodeRefactoringProvider CreateCodeRefactoringProvider(TestWorkspace workspace, TestParameters parameters)
        => new CSharpConvertAnonymousTypeToTupleCodeRefactoringProvider();
 
    protected override ImmutableArray<CodeAction> MassageActions(ImmutableArray<CodeAction> actions)
        => FlattenActions(actions);
 
    [Fact]
    public async Task ConvertSingleAnonymousType()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = [||]new { a = 1, b = 2 };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = (a: 1, b: 2);
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task NotOnEmptyAnonymousType()
    {
        await TestMissingInRegularAndScriptAsync("""
            class Test
            {
                void Method()
                {
                    var t1 = [||]new { };
                }
            }
            """);
    }
 
    [Fact]
    public async Task NotOnSingleFieldAnonymousType()
    {
        await TestMissingInRegularAndScriptAsync("""
            class Test
            {
                void Method()
                {
                    var t1 = [||]new { a = 1 };
                }
            }
            """);
    }
 
    [Fact]
    public async Task ConvertSingleAnonymousTypeWithInferredName()
    {
        var text = """
            class Test
            {
                void Method(int b)
                {
                    var t1 = [||]new { a = 1, b };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method(int b)
                {
                    var t1 = (a: 1, b);
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task ConvertMultipleInstancesInSameMethod()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = [||]new { a = 1, b = 2 };
                    var t2 = new { a = 3, b = 4 };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = (a: 1, b: 2);
                    var t2 = (a: 3, b: 4);
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task ConvertMultipleInstancesAcrossMethods()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = [||]new { a = 1, b = 2 };
                    var t2 = new { a = 3, b = 4 };
                }
 
                void Method2()
                {
                    var t1 = new { a = 1, b = 2 };
                    var t2 = new { a = 3, b = 4 };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = (a: 1, b: 2);
                    var t2 = (a: 3, b: 4);
                }
 
                void Method2()
                {
                    var t1 = new { a = 1, b = 2 };
                    var t2 = new { a = 3, b = 4 };
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task OnlyConvertMatchingTypesInSameMethod()
    {
        var text = """
            class Test
            {
                void Method(int b)
                {
                    var t1 = [||]new { a = 1, b = 2 };
                    var t2 = new { a = 3, b };
                    var t3 = new { a = 4 };
                    var t4 = new { b = 5, a = 6 };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method(int b)
                {
                    var t1 = (a: 1, b: 2);
                    var t2 = (a: 3, b);
                    var t3 = new { a = 4 };
                    var t4 = new { b = 5, a = 6 };
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task TestFixAllInSingleMethod()
    {
        var text = """
            class Test
            {
                void Method(int b)
                {
                    var t1 = [||]new { a = 1, b = 2 };
                    var t2 = new { a = 3, b };
                    var t3 = new { a = 4 };
                    var t4 = new { b = 5, a = 6 };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method(int b)
                {
                    var t1 = (a: 1, b: 2);
                    var t2 = (a: 3, b);
                    var t3 = new { a = 4 };
                    var t4 = (b: 5, a: 6);
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected, index: 1);
    }
 
    [Fact]
    public async Task TestFixNotAcrossMethods()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = [||]new { a = 1, b = 2 };
                    var t2 = new { a = 3, b = 4 };
                }
 
                void Method2()
                {
                    var t1 = new { a = 1, b = 2 };
                    var t2 = new { a = 3, b = 4 };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = (a: 1, b: 2);
                    var t2 = (a: 3, b: 4);
                }
 
                void Method2()
                {
                    var t1 = new { a = 1, b = 2 };
                    var t2 = new { a = 3, b = 4 };
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task TestTrivia()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = /*1*/ [||]new /*2*/ { /*3*/ a /*4*/ = /*5*/ 1 /*7*/ , /*8*/ b /*9*/ = /*10*/ 2 /*11*/ } /*12*/ ;
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = /*1*/ ( /*3*/ a /*4*/ : /*5*/ 1 /*7*/ , /*8*/ b /*9*/ : /*10*/ 2 /*11*/ ) /*12*/ ;
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task TestFixAllNestedTypes()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = [||]new { a = 1, b = new { c = 1, d = 2 } };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = (a: 1, b: (c: 1, d: 2));
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected, index: 1);
    }
 
    [Fact]
    public async Task ConvertMultipleNestedInstancesInSameMethod()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = [||]new { a = 1, b = (object)new { a = 1, b = default(object) } };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = (a: 1, b: (object)(a: 1, b: default(object)));
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task ConvertWithLambda1()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = [||]new { a = 1, b = 2 };
                    Action a = () =>
                    {
                        var t2 = new { a = 3, b = 4 };
                    };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = (a: 1, b: 2);
                    Action a = () =>
                    {
                        var t2 = (a: 3, b: 4);
                    };
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task ConvertWithLambda2()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = new { a = 1, b = 2 };
                    Action a = () =>
                    {
                        var t2 = [||]new { a = 3, b = 4 };
                    };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = (a: 1, b: 2);
                    Action a = () =>
                    {
                        var t2 = (a: 3, b: 4);
                    };
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task ConvertWithLocalFunction1()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = [||]new { a = 1, b = 2 };
                    void func()
                    {
                        var t2 = new { a = 3, b = 4 };
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = (a: 1, b: 2);
                    void func()
                    {
                        var t2 = (a: 3, b: 4);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task ConvertWithLocalFunction2()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = new { a = 1, b = 2 };
                    void func()
                    {
                        var t2 = [||]new { a = 3, b = 4 };
                    }
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = (a: 1, b: 2);
                    void func()
                    {
                        var t2 = (a: 3, b: 4);
                    }
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact]
    public async Task TestIncompleteAnonymousType()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = [||]new { a = , b = };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = (a: , b: );
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/34749")]
    public async Task NotInExpressionTree()
    {
        await TestMissingInRegularAndScriptAsync("""
            using System.Linq.Expressions;
 
            class C
            {
                static void Main(string[] args)
                {
                    Expression<Func<string, string, dynamic>> test =
                        (par1, par2) => [||]new { Parameter1 = par1, Parameter2 = par2 };
                }
            }
            """);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75950")]
    public async Task RemoveTrailingComma()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = [||]new { a = 1, b = 2, };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = (a: 1, b: 2);
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/50470")]
    public async Task TestMultiLine1()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = var items = new[]
                    {
                        [||]new
                        {
                            x = 1,
                            y = 2,
                        },
                    };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = var items = new[]
                    {
                        (
                            x: 1,
                            y: 2
                        ),
                    };
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/50470")]
    public async Task TestMultiLine2()
    {
        var text = """
            class Test
            {
                void Method()
                {
                    var t1 = var items = new[]
                    {
                        [||]new
                        {
                            x = 1,
                            y = 2
                        },
                    };
                }
            }
            """;
        var expected = """
            class Test
            {
                void Method()
                {
                    var t1 = var items = new[]
                    {
                        (
                            x: 1,
                            y: 2
                        ),
                    };
                }
            }
            """;
        await TestInRegularAndScriptAsync(text, expected);
    }
}