File: IntroduceParameter\IntroduceParameterTests.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;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.IntroduceParameter;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.IntroduceParameter;
 
[Trait(Traits.Feature, Traits.Features.CodeActionsIntroduceParameter)]
public sealed class IntroduceParameterTests : AbstractCSharpCodeActionTest_NoEditor
{
    protected override CodeRefactoringProvider CreateCodeRefactoringProvider(TestWorkspace workspace, TestParameters parameters)
        => new CSharpIntroduceParameterCodeRefactoringProvider();
 
    protected override ImmutableArray<CodeAction> MassageActions(ImmutableArray<CodeAction> actions)
        => FlattenActions(actions);
 
    private OptionsCollection UseExpressionBody
        => Option(CSharpCodeStyleOptions.PreferExpressionBodiedMethods, CSharpCodeStyleOptions.WhenPossibleWithSuggestionEnforcement);
 
    [Fact]
    public Task TestExpressionWithNoMethodCallsCase()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z) 
                {
                    int m = [|x * y * z;|]
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(int x, int y, int z, int m) 
                {
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestExpressionCaseWithLocal()
        => TestMissingInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z) 
                {
                    int l = 5;
                    int m = [|l * y * z;|]
                }
            }
            """);
 
    [Fact]
    public Task TestBasicComplexExpressionCase()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(string x, int y, int z) 
                {
                    int m = [|x.Length * y * z|];
                }
 
                void M1(string y)
                {
                    M(y, 5, 2);
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(string x, int y, int z, int m) 
                {
                }
 
                void M1(string y)
                {
                    M(y, 5, 2, y.Length * 5 * 2);
                }
            }
            """, 0);
 
    [Fact]
    public Task TestExpressionCaseWithSingleMethodCall()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = [|x * z * z|];
                }
 
                void M1(int x, int y, int z) 
                {
                    M(z, x, z);
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(int x, int y, int z, int m)
                {
                }
 
                void M1(int x, int y, int z) 
                {
                    M(z, x, z, z * z * z);
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestLocalDeclarationMultipleDeclarators()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = [|x * z * z|], y = 0;
                }
 
                void M1(int x, int y, int z) 
                {
                    M(z, x, z);
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(int x, int y, int z, int v)
                {
                    int m = {|Rename:v|}, y = 0;
                }
 
                void M1(int x, int y, int z) 
                {
                    M(z, x, z, z * z * z);
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestDeclarationInForLoop()
        => TestMissingAsync("""
            using System;
            class TestClass
            {
                void M(int a, int b)
                {
                    var v = () =>
                    {
                        for (var y = [|a * b|]; ;) { }
                    };
                }
            }
            """);
 
    [Fact]
    public Task TestExpressionCaseWithSingleMethodCallInLocalFunction()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = M2(x, z);
 
                    int M2(int x, int y)
                    {
                        int val = [|x * y|];
                        return val;
                    }
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = M2(x, z, x * z);
 
                    int M2(int x, int y, int val)
                    {
                        return val;
                    }
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestExpressionCaseWithSingleMethodCallInStaticLocalFunction()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = M2(x, z);
 
                    static int M2(int x, int y)
                    {
                        int val = [|x * y|];
                        return val;
                    }
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = M2(x, z, x * z);
 
                    static int M2(int x, int y, int val)
                    {
                        return val;
                    }
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestHighlightIncompleteExpressionCaseWithSingleMethodCall()
        => TestMissingInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = 5 * [|x * y * z|];
                }
 
                void M1(int x, int y, int z) 
                {
                    M(z, y, x);
                }
            }
            """);
 
    [Fact]
    public Task TestExpressionCaseWithMultipleMethodCall()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = [|x * y * z|];
                }
 
                void M1(int x, int y, int z) 
                {
                    M(a + b, 5, x);
                    M(z, y, x);
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(int x, int y, int z, int m)
                {
                }
 
                void M1(int x, int y, int z) 
                {
                    M(a + b, 5, x, (a + b) * 5 * x);
                    M(z, y, x, z * y * x);
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestExpressionAllOccurrences()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = x * y * z;
                    int f = [|x * y * z|];
                }
 
                void M1(int x, int y, int z) 
                {
                    M(a + b, 5, x);
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(int x, int y, int z, int f)
                {
                    int m = f;
                }
 
                void M1(int x, int y, int z) 
                {
                    M(a + b, 5, x, (a + b) * 5 * x);
                }
            }
            """, index: 3);
 
    [Fact]
    public Task TestxpressionWithNoMethodCallTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z) 
                {
                    int m = [|x * y * z;|]
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int GetM(int x, int y, int z)
                {
                    return x * y * z;
                }
 
                void M(int x, int y, int z, int m) 
                {
                }
            }
            """, index: 1, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionWithSingleMethodCallTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = [|y * x|];
                }
 
                void M1(int x, int y, int z) 
                {
                    M(z, y, x);
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int GetM(int x, int y)
                {
                    return y * x;
                }
 
                void M(int x, int y, int z, int m)
                {
                }
 
                void M1(int x, int y, int z) 
                {
                    M(z, y, x, GetM(z, y));
                }
            }
            """, index: 1, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionWithSingleMethodCallAndAccessorsTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = [|y * x|];
                }
 
                void M1(int x, int y, int z) 
                {
                    this.M(z, y, x);
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int GetM(int x, int y)
                {
                    return y * x;
                }
 
                void M(int x, int y, int z, int m)
                {
                }
 
                void M1(int x, int y, int z) 
                {
                    this.M(z, y, x, GetM(z, y));
                }
            }
            """, index: 1, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionWithSingleMethodCallAndAccessorsConditionalTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = [|y * x|];
                }
 
                void M1(int x, int y, int z) 
                {
                    this?.M(z, y, x);
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int GetM(int x, int y)
                {
                    return y * x;
                }
 
                void M(int x, int y, int z, int m)
                {
                }
 
                void M1(int x, int y, int z) 
                {
                    this?.M(z, y, x, this?.GetM(z, y));
                }
            }
            """, index: 1, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionWithSingleMethodCallMultipleAccessorsTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z) 
                {
                    A a = new A();
                    var age = a.Prop.ComputeAge(x, y);
                }
            }
 
            class A
            {
                public B Prop { get; set; }
            }
            class B
            {
                public int ComputeAge(int x, int y)
                {
                    var age = [|x + y|];
                    return age;
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(int x, int y, int z) 
                {
                    A a = new A();
                    var age = a.Prop.ComputeAge(x, y, a.Prop.GetAge(x, y));
                }
            }
 
            class A
            {
                public B Prop { get; set; }
            }
            class B
            {
                public int GetAge(int x, int y)
                {
                    return x + y;
                }
 
                public int ComputeAge(int x, int y, int age)
                {
                    return age;
                }
            }
            """, index: 1, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionWithSingleMethodCallMultipleAccessorsConditionalTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z) 
                {
                    A a = new A();
                    var age = a?.Prop?.ComputeAge(x, y);
                }
            }
 
            class A
            {
                public B Prop { get; set; }
            }
            class B
            {
                public int ComputeAge(int x, int y)
                {
                    var age = [|x + y|];
                    return age;
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(int x, int y, int z) 
                {
                    A a = new A();
                    var age = a?.Prop?.ComputeAge(x, y, a?.Prop?.GetAge(x, y));
                }
            }
 
            class A
            {
                public B Prop { get; set; }
            }
            class B
            {
                public int GetAge(int x, int y)
                {
                    return x + y;
                }
 
                public int ComputeAge(int x, int y, int age)
                {
                    return age;
                }
            }
            """, index: 1, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionWithSingleMethodCallAccessorsMixedConditionalTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z) 
                {
                    A a = new A();
                    var age = a.Prop?.ComputeAge(x, y);
                }
            }
 
            class A
            {
                public B Prop { get; set; }
            }
            class B
            {
                public int ComputeAge(int x, int y)
                {
                    var age = [|x + y|];
                    return age;
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(int x, int y, int z) 
                {
                    A a = new A();
                    var age = a.Prop?.ComputeAge(x, y, a.Prop?.GetAge(x, y));
                }
            }
 
            class A
            {
                public B Prop { get; set; }
            }
            class B
            {
                public int GetAge(int x, int y)
                {
                    return x + y;
                }
 
                public int ComputeAge(int x, int y, int age)
                {
                    return age;
                }
            }
            """, index: 1, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionWithSingleMethodCallTrampolineAllOccurrences()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = [|x * y * z|];
                    int l = x * y * z;
                }
 
                void M1(int x, int y, int z) 
                {
                    M(z, y, x);
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int GetM(int x, int y, int z)
                {
                    return x * y * z;
                }
 
                void M(int x, int y, int z, int m)
                {
                    int l = m;
                }
 
                void M1(int x, int y, int z) 
                {
                    M(z, y, x, GetM(z, y, x));
                }
            }
            """, index: 4, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionWithNoMethodCallOverload()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z) 
                {
                    int m = [|x * y * z;|]
                }
            }
            """, """
            using System;
            class TestClass
            {
                private void M(int x, int y, int z)
                {
                    M(x, y, z, x * y * z);
                }
 
                void M(int x, int y, int z, int m) 
                {
                }
            }
            """, index: 2, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionWithSingleMethodCallOverload()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(int x, int y, int z)
                {
                    int m = [|x * y * z|];
                }
 
                void M1(int x, int y, int z) 
                {
                    M(z, y, x);
                }
            }
            """, """
            using System;
            class TestClass
            {
                private void M(int x, int y, int z)
                {
                    M(x, y, z, x * y * z);
                }
 
                void M(int x, int y, int z, int m)
                {
                }
 
                void M1(int x, int y, int z) 
                {
                    M(z, y, x);
                }
            }
            """, index: 2, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionBodiedMemberOverload()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y, int z) => [|x * y * z|];
 
                void M1(int x, int y, int z)
                {
                    int prod = M(z, y, x);
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int M(int x, int y, int z) => M(x, y, z, x * y * z);
                int M(int x, int y, int z, int v) => {|Rename:v|};
 
                void M1(int x, int y, int z)
                {
                    int prod = M(z, y, x);
                }
            }
            """, index: 2, new(options: UseExpressionBody, parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionBodiedMemberTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y, int z) => [|x * y * z|];
 
                void M1(int x, int y, int z)
                {
                    int prod = M(z, y, x);
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int GetV(int x, int y, int z)
                {
                    return x * y * z;
                }
 
                int M(int x, int y, int z, int v) => {|Rename:v|};
 
                void M1(int x, int y, int z)
                {
                    int prod = M(z, y, x, GetV(z, y, x));
                }
            }
            """, index: 1, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionCaseWithRecursiveCall()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y, int z)
                {
                    int m = [|x * y * z|];
                    return M(x, x, z);
                }
            }
            """, """
            using System;
            class TestClass
            {
                int M(int x, int y, int z, int m)
                {
                    return M(x, x, z, x * x * z);
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestExpressionCaseWithNestedRecursiveCall()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y, int z)
                {
                    int m = [|x * y * z|];
                    return M(x, x, M(x, y, z));
                }
            }
            """, """
            using System;
            class TestClass
            {
                int M(int x, int y, int z, int m)
                {
                    return M(x, x, M(x, y, z, x * y * z), x * x * M(x, y, z, x * y * z));
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestExpressionCaseWithParamsArg()
        => TestMissingInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(params int[] args)
                {
                    int m = [|args[0] + args[1]|];
                    return m;
                }
 
                void M1()
                {
                    M(5, 6, 7);
                }
            }
            """);
 
    [Fact]
    public Task TestExpressionCaseWithOptionalParameters()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y = 5)
                {
                    int m = [|x * y|];
                    return m;
                }
 
                void M1()
                {
                    M(5, 3);
                }
            }
            """, """
            using System;
            class TestClass
            {
                int M(int x, int m, int y = 5)
                {
                    return m;
                }
 
                void M1()
                {
                    M(5, 5 * 3, 3);
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestExpressionCaseWithOptionalParametersUsed()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y = 5)
                {
                    int m = [|x * y|];
                    return m;
                }
 
                void M1()
                {
                    M(7);
                }
            }
            """, """
            using System;
            class TestClass
            {
                int M(int x, int m, int y = 5)
                {
                    return m;
                }
 
                void M1()
                {
                    M(7, 7 * 5);
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestExpressionCaseWithOptionalParametersUsedOverload()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y = 5)
                {
                    int m = [|x * y|];
                    return m;
                }
 
                void M1()
                {
                    M(7);
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int M(int x, int y = 5)
                {
                    return M(x, x * y, y);
                }
 
                int M(int x, int m, int y = 5)
                {
                    return m;
                }
 
                void M1()
                {
                    M(7);
                }
            }
            """, index: 2);
 
    [Fact]
    public Task TestExpressionCaseWithOptionalParametersUsedTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y = 5)
                {
                    int m = [|x * y|];
                    return m;
                }
 
                void M1()
                {
                    M(7);
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int GetM(int x, int y = 5)
                {
                    return x * y;
                }
 
                int M(int x, int m, int y = 5)
                {
                    return m;
                }
 
                void M1()
                {
                    M(7, GetM(7));
                }
            }
            """, index: 1);
 
    [Fact]
    public Task TestExpressionCaseWithOptionalParametersUnusedTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y = 5)
                {
                    int m = [|x * y|];
                    return m;
                }
 
                void M1()
                {
                    M(7, 2);
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int GetM(int x, int y = 5)
                {
                    return x * y;
                }
 
                int M(int x, int m, int y = 5)
                {
                    return m;
                }
 
                void M1()
                {
                    M(7, GetM(7, 2), 2);
                }
            }
            """, index: 1);
 
    [Fact]
    public Task TestExpressionCaseWithCancellationToken()
        => TestInRegularAndScriptAsync("""
            using System;
            using System.Threading;
            class TestClass
            {
                int M(int x, CancellationToken cancellationToken)
                {
                    int m = [|x * x|];
                    return m;
                }
 
                void M1(CancellationToken cancellationToken)
                {
                    M(7, cancellationToken);
                }
            }
            """, """
            using System;
            using System.Threading;
            class TestClass
            {
                int M(int x, int m, CancellationToken cancellationToken)
                {
                    return m;
                }
 
                void M1(CancellationToken cancellationToken)
                {
                    M(7, 7 * 7, cancellationToken);
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestExpressionCaseWithRecursiveCallTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y, int z)
                {
                    int m = [|x * y * z|];
                    return M(x, x, z);
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int GetM(int x, int y, int z)
                {
                    return x * y * z;
                }
 
                int M(int x, int y, int z, int m)
                {
                    return M(x, x, z, GetM(x, x, z));
                }
            }
            """, index: 1, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionCaseWithNestedRecursiveCallTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y, int z)
                {
                    int m = [|x * y * z|];
                    return M(x, x, M(x, y, x));
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int GetM(int x, int y, int z)
                {
                    return x * y * z;
                }
 
                int M(int x, int y, int z, int m)
                {
                    return M(x, x, M(x, y, x, GetM(x, y, x)), GetM(x, x, M(x, y, x, GetM(x, y, x))));
                }
            }
            """, index: 1, new(options: new OptionsCollection(GetLanguage()), parseOptions: CSharpParseOptions.Default));
 
    [Fact]
    public Task TestExpressionCaseInConstructor()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                public TestClass(int x, int y)
                {
                    Math.Max([|x + y|], x * y);
                }
 
                void TestMethod()
                {
                    var test = new TestClass(5, 6);
                }
            }
            """, """
            using System;
            class TestClass
            {
                public TestClass(int x, int y, int val1)
                {
                    Math.Max({|Rename:val1|}, x * y);
                }
 
                void TestMethod()
                {
                    var test = new TestClass(5, 6, 5 + 6);
                }
            }
            """, 0);
 
    [Fact]
    public Task TestLambdaCaseNormal()
        => TestMissingInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                Func<int, int, int> mult = (x, y) => [|x * y|];
            }
            """);
 
    [Fact]
    public Task TestLambdaCaseTrampoline()
        => TestMissingInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                Func<int, int, int> mult = (x, y) => [|x * y|];
            }
            """);
 
    [Fact]
    public Task TestLambdaCaseOverload()
        => TestMissingInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                Func<int, int, int> mult = (x, y) => [|x * y|];
            }
            """);
 
    [Fact]
    public Task TestTopLevelStatements()
        => TestMissingInRegularAndScriptAsync("""
            using System;
            Math.Max(5 + 5, [|6 + 7|]);
            """);
 
    [Fact]
    public Task TestFieldInitializer()
        => TestMissingInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int a = [|5 + 3|];
            }
            """);
 
    [Fact]
    public Task TestIndexer()
        => TestMissingInRegularAndScriptAsync("""
            using System;
            class SampleCollection<T>
            {
                private T[] arr = new T[100];
 
                public T this[int i] => arr[[|i + 5|]];
            }
            """);
 
    [Fact]
    public Task TestPropertyGetter()
        => TestMissingInRegularAndScriptAsync("""
            using System;
 
            class TimePeriod
            {
               private double _seconds;
 
               public double Hours
               {
                   get { return [|_seconds / 3600|]; }
               }
            }
            """);
 
    [Fact]
    public Task TestPropertySetter()
        => TestMissingInRegularAndScriptAsync("""
            using System;
 
            class TimePeriod
            {
               private double _seconds;
 
               public double Hours
               {
                   set {
                      _seconds = [|value * 3600|];
                    }
                }
            }
            """);
 
    [Fact]
    public Task TestDestructor()
        => TestMissingInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                public ~TestClass()
                {
                    Math.Max([|5 + 5|], 5 * 5);
                }
            }
            """);
 
    [Fact]
    public Task TestExpressionInParameter()
        => TestMissingInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                public void M(int x = [|5 * 5|])
                {
                }
            }
            """);
 
    [Fact]
    public Task TestCrossLanguageInvocations()
        => TestInRegularAndScriptAsync("""
            <Workspace>
                <Project Language= "C#" AssemblyName="Assembly1" CommonReferences="true">
                    <Document>
            public class Program
            {
                public Program() {}
 
                public int M(int x, int y)
                {
                    int m = [|x * y|];
                    return m;
                }
 
                void M1()
                {
                    M(7, 2);
                }
            }
                    </Document>
                </Project>
 
            <Project Language= "Visual Basic" AssemblyName="Assembly2" CommonReferences="true">
                    <ProjectReference>Assembly1</ProjectReference>
                    <Document>
            Class ProgramVB
                Sub M2()
                    Dim programC = New Program()
                    programC.M(7, 2)
                End Sub
            End Class
                    </Document>
                </Project>
            </Workspace>
            """, """
            <Workspace>
                <Project Language= "C#" AssemblyName="Assembly1" CommonReferences="true">
                    <Document>
            public class Program
            {
                public Program() {}
 
                public int M(int x, int y, int m)
                {
                    return m;
                }
 
                void M1()
                {
                    M(7, 2, 7 * 2);
                }
            }
                    </Document>
                </Project>
 
            <Project Language= "Visual Basic" AssemblyName="Assembly2" CommonReferences="true">
                    <ProjectReference>Assembly1</ProjectReference>
                    <Document>
            Class ProgramVB
                Sub M2()
                    Dim programC = New Program()
                    programC.M(7, 2)
                End Sub
            End Class
                    </Document>
                </Project>
            </Workspace>
            """, 0);
 
    [Fact]
    public Task TestConvertedTypeInExpression()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(double x, double y) 
                {
                    int m = [|(int)(x * y);|]
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(double x, double y, int m) 
                {
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestConvertedTypeInExpressionTrampoline()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M(double x, double y) 
                {
                    int m = [|(int)(x * y);|]
                }
            }
            """, """
            using System;
            class TestClass
            {
                private int GetM(double x, double y)
                {
                    return (int)(x * y);
                }
 
                void M(double x, double y, int m) 
                {
                }
            }
            """, index: 1);
 
    [Fact]
    public Task TestThisKeywordInExpression()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                public int M1()
                {
                    return 5;
                }
 
                public int M(int x, int y)
                {
                    int m = [|x * this.M1();|]
                    return m;
                }
            }
            """, """
            using System;
            class TestClass
            {
                public int M1()
                {
                    return 5;
                }
 
                public int GetM(int x)
                {
                    return x * this.M1();
                }
 
                public int M(int x, int y, int m)
                {
                    return m;
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestThisImplicitInExpression()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                public int M1()
                {
                    return 5;
                }
 
                public int M(int x, int y)
                {
                    int m = [|x * M1();|]
                    return m;
                }
            }
            """, """
            using System;
            class TestClass
            {
                public int M1()
                {
                    return 5;
                }
 
                public int GetM(int x)
                {
                    return x * M1();
                }
 
                public int M(int x, int y, int m)
                {
                    return m;
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestStaticMethodCallInExpression()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                public static int M1()
                {
                    return 5;
                }
 
                public int M(int x, int y)
                {
                    int m = [|x * M1();|]
                    return m;
                }
            }
            """, """
            using System;
            class TestClass
            {
                public static int M1()
                {
                    return 5;
                }
 
                public int M(int x, int y, int m)
                {
                    return m;
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestBaseKeywordInExpression()
        => TestInRegularAndScriptAsync("""
            using System;
            class Net
            {
                public int _value = 6;
            }
 
            class Perl : Net
            {
                public new int _value = 7;
 
                public void Write()
                {
                    int x = [|base._value + 1;|]
                }
            }
            """, """
            using System;
            class Net
            {
                public int _value = 6;
            }
 
            class Perl : Net
            {
                public new int _value = 7;
 
                public int GetX()
                {
                    return base._value + 1;
                }
 
                public void Write(int x)
                {
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestFieldReferenceInOptionalParameter()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y = int.MaxValue)
                {
                    int m = [|x * y|];
                    return m;
                }
 
                void M1()
                {
                    M(7);
                }
            }
            """, """
            using System;
            class TestClass
            {
                int M(int x, int m, int y = int.MaxValue)
                {
                    return m;
                }
 
                void M1()
                {
                    M(7, 7 * int.MaxValue);
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestNamedParameterNecessary()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                int M(int x, int y = 5, int z = 3)
                {
                    int m = [|z * y|];
                    return m;
                }
 
                void M1()
                {
                    M(z: 0, y: 2);
                }
            }
            """, """
            using System;
            class TestClass
            {
                int M(int x, int m, int y = 5, int z = 3)
                {
                    return m;
                }
 
                void M1()
                {
                    M(z: 0, m: 0 * 2, y: 2);
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestHighlightReturnType()
        => TestMissingInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                [|int|] M(int x)
                {
                    return x;
                }
 
                void M1()
                {
                    M(5);
                }
            }
            """);
 
    [Fact]
    public Task TestTypeOfOnString()
        => TestInRegularAndScriptAsync("""
            using System;
            class TestClass
            {
                void M()
                {
                    var x = [|typeof(string);|]
                }
            }
            """, """
            using System;
            class TestClass
            {
                void M(Type x)
                {
                }
            }
            """, index: 0);
 
    [Fact]
    public Task TestClassObject()
        => TestMissingInRegularAndScriptAsync("""
            class F
            {
                public int x;
                public int y;
 
                public F(int x, int y)
                {
                    this.x = x;
                    this.y = y;
                }
            }
 
            class TestClass
            {
                int N(F f)
                {
                    return f.[|x|];
                }
 
                void M()
                {
                    N(new F(1, 2));
                }
            }
            """);
 
    [Fact]
    public Task TestReferenceInDifferentDocumentWithUsings()
        => TestInRegularAndScriptAsync("""
            <Workspace>
                <Project Language= "C#" AssemblyName="Assembly1" CommonReferences="true">
                    <Document>
            using System;
            using System.Linq;
 
            namespace Foo
            {
                public class Bar
                {
                    public Bar()
                    {
                        [|var x = 2|];
                    }
                }
            }
                    </Document>
 
                    <Document>
            namespace Refactorings
            {
                using Foo;
                class Program
                {
                    public Program(int x)
                    {
                        var bar = new Bar();
 
                    }
                }
            }
                    </Document>
                </Project>
            </Workspace>
            """, """
            <Workspace>
                <Project Language= "C#" AssemblyName="Assembly1" CommonReferences="true">
                    <Document>
            using System;
            using System.Linq;
 
            namespace Foo
            {
                public class Bar
                {
                    public Bar(int x)
                    {
                    }
                }
            }
                    </Document>
 
                    <Document>
            namespace Refactorings
            {
                using Foo;
                class Program
                {
                    public Program(int x)
                    {
                        var bar = new Bar(2);
 
                    }
                }
            }
                    </Document>
                </Project>
            </Workspace>
            """, 0);
 
    [Fact]
    public Task TestIntroduceParameterOnParameter()
        => TestMissingInRegularAndScriptAsync("""
            using System;
 
            class Program
            {
                public static void Main(string[] args)
                {
                    Console.WriteLine([|args|]);
                }
            }
            """);
 
    [Fact]
    public Task TestIntroduceParameterOnExpressionContainingParameter()
        => TestInRegularAndScriptAsync("""
            public class C
            {
                public void M(string s)
                {
                    localFunction();
 
                    void localFunction()
                    {
                        _ = [|s|].ToString();
                    }
                }
            }
            """, """
            public class C
            {
                public void M(string s)
                {
                    localFunction(s);
 
                    void localFunction(string s)
                    {
                        _ = {|Rename:s|}.ToString();
                    }
                }
            }
            """, 0);
 
    [Fact]
    public Task TestIntroduceParameterOnOverload()
        => TestInRegularAndScriptAsync("""
            M();
            int M(int _) => M([|1234|]);
            """, """
            M();
            int M(int _, int v) => M({|Rename:v|}, 1234);
            """, 0);
 
    [Fact]
    public Task TestIntroduceParameterOnAttributeArgument()
        => TestMissingInRegularAndScriptAsync("""
            public class C
            {
                [Theory]
                [InlineData([|"A"|])]
                public void Test(string s)
                {
                }
            }
            """);
 
    [Fact]
    public Task TestNotOnNamedType1()
        => TestMissingInRegularAndScriptAsync(
            """
            using System;
 
            class C
            {
                void M()
                {
                    [||]Console.WriteLine();
                }
            }
            """);
}