File: src\Analyzers\CSharp\Tests\MakeAnonymousFunctionStatic\MakeAnonymousFunctionStaticTests.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.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeStyle;
using Microsoft.CodeAnalysis.CSharp.MakeAnonymousFunctionStatic;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.MakeAnonymousFunctionStatic;
 
using VerifyCS = CSharpCodeFixVerifier<MakeAnonymousFunctionStaticDiagnosticAnalyzer, CSharpMakeAnonymousFunctionStaticCodeFixProvider>;
 
[Trait(Traits.Feature, Traits.Features.CodeActionsMakeAnonymousFunctionStatic)]
public class MakeAnonymousFunctionStaticTests
{
    private static async Task TestWithCSharp9Async(string code, string fixedCode)
    {
        await new VerifyCS.Test
        {
            TestCode = code,
            FixedCode = fixedCode,
            LanguageVersion = LanguageVersion.CSharp9
        }.RunAsync();
    }
 
    [Theory]
    [InlineData("i => { }")]
    [InlineData("(i) => { }")]
    [InlineData("delegate (int i) { }")]
    public async Task TestBelowCSharp9(string anonymousFunctionSyntax)
    {
        var code = $$"""
            using System;
 
            class C
            {
                void M()
                {
                    N({{anonymousFunctionSyntax}});
                }
 
                void N(Action<int> a)
                {
                }
            }
            """;
 
        await new VerifyCS.Test
        {
            TestCode = code,
            FixedCode = code,
            LanguageVersion = LanguageVersion.CSharp8
        }.RunAsync();
    }
 
    [Theory]
    [InlineData("i => { }")]
    [InlineData("(i) => { }")]
    [InlineData("delegate (int i) { }")]
    public async Task TestWithOptionOff(string anonymousFunctionSyntax)
    {
        var code = $$"""
            using System;
 
            class C
            {
                void M()
                {
                    N({{anonymousFunctionSyntax}});
                }
 
                void N(Action<int> a)
                {
                }
            }
            """;
 
        await new VerifyCS.Test
        {
            TestCode = code,
            FixedCode = code,
            LanguageVersion = LanguageVersion.CSharp9,
            Options =
            {
                { CSharpCodeStyleOptions.PreferStaticAnonymousFunction, false }
            }
        }.RunAsync();
    }
 
    [Theory]
    [InlineData("i => { }")]
    [InlineData("(i) => { }")]
    [InlineData("delegate (int i) { }")]
    public async Task TestMissingWhenAlreadyStatic(string anonymousFunctionSyntax)
    {
        var code = $$"""
            using System;
            
            class C
            {
                void M()
                {
                    N(static {{anonymousFunctionSyntax}});
                }
            
                void N(Action<int> a)
                {
                }
            }
            """;
 
        await TestWithCSharp9Async(code, code);
    }
 
    [Theory]
    [InlineData("i => { }")]
    [InlineData("(i) => { }")]
    [InlineData("delegate (int i) { }")]
    public async Task TestNoCaptures(string anonymousFunctionSyntax)
    {
        var code = $$"""
            using System;
            
            class C
            {
                void M()
                {
                    N([|{{anonymousFunctionSyntax}}|]);
                }
            
                void N(Action<int> a)
                {
                }
            }
            """;
 
        var fixedCode = $$"""
            using System;
            
            class C
            {
                void M()
                {
                    N(static {{anonymousFunctionSyntax}});
                }
            
                void N(Action<int> a)
                {
                }
            }
            """;
 
        await TestWithCSharp9Async(code, fixedCode);
    }
 
    [Theory]
    [InlineData("i => _field")]
    [InlineData("(i) => _field")]
    [InlineData("delegate (int i) { return _field; }")]
    public async Task TestCapturesThis(string anonymousFunctionSyntax)
    {
        var code = $$"""
            using System;
            
            class C
            {
                private int _field;
 
                void M()
                {
                    N({{anonymousFunctionSyntax}});
                }
            
                void N(Func<int, int> f)
                {
                }
            }
            """;
 
        await TestWithCSharp9Async(code, code);
    }
 
    [Theory]
    [InlineData("i => GetValueFromStaticMethod()")]
    [InlineData("(i) => GetValueFromStaticMethod()")]
    [InlineData("delegate (int i) { return GetValueFromStaticMethod(); }")]
    public async Task TestNoCaptures_ReferencesStaticMethod(string anonymousFunctionSyntax)
    {
        var code = $$"""
            using System;
            
            class C
            {
                private static int GetValueFromStaticMethod() => 0;
 
                void M()
                {
                    N([|{{anonymousFunctionSyntax}}|]);
                }
            
                void N(Func<int, int> f)
                {
                }
            }
            """;
 
        var fixedCode = $$"""
            using System;
            
            class C
            {
                private static int GetValueFromStaticMethod() => 0;
 
                void M()
                {
                    N(static {{anonymousFunctionSyntax}});
                }
            
                void N(Func<int, int> f)
                {
                }
            }
            """;
 
        await TestWithCSharp9Async(code, fixedCode);
    }
 
    [Theory]
    [InlineData("i => x")]
    [InlineData("(i) => x")]
    [InlineData("delegate (int i) { return x; }")]
    public async Task TestCapturesParameter(string anonymousFunctionSyntax)
    {
        var code = $$"""
            using System;
            
            class C
            {
                void M(int x)
                {
                    N({{anonymousFunctionSyntax}});
                }
            
                void N(Func<int, int> f)
                {
                }
            }
            """;
 
        await TestWithCSharp9Async(code, code);
    }
 
    [Theory]
    [InlineData("i => i")]
    [InlineData("(i) => i")]
    [InlineData("delegate (int i) { return i; }")]
    public async Task TestNoCaptures_SameFunctionParameterNameAsOuterParameterName(string anonymousFunctionSyntax)
    {
        var code = $$"""
            using System;
            
            class C
            {
                void M(int i)
                {
                    N([|{{anonymousFunctionSyntax}}|]);
                }
            
                void N(Func<int, int> f)
                {
                }
            }
            """;
 
        var fixedCode = $$"""
            using System;
            
            class C
            {
                void M(int i)
                {
                    N(static {{anonymousFunctionSyntax}});
                }
            
                void N(Func<int, int> f)
                {
                }
            }
            """;
 
        await TestWithCSharp9Async(code, fixedCode);
    }
 
    [Theory]
    [InlineData("i => x")]
    [InlineData("(i) => x")]
    [InlineData("delegate (int i) { return x; }")]
    public async Task TestCapturesLocal(string anonymousFunctionSyntax)
    {
        var code = $$"""
            using System;
            
            class C
            {
                void M()
                {
                    int x = 0;
                    N({{anonymousFunctionSyntax}});
                }
            
                void N(Func<int, int> f)
                {
                }
            }
            """;
 
        await TestWithCSharp9Async(code, code);
    }
 
    [Theory]
    [InlineData("i => i")]
    [InlineData("(i) => i")]
    [InlineData("delegate (int i) { return i; }")]
    public async Task TestNoCaptures_SameFunctionParameterNameAsOuterLocalName(string anonymousFunctionSyntax)
    {
        var code = $$"""
            using System;
            
            class C
            {
                void M()
                {
                    int i = 0;
                    N([|{{anonymousFunctionSyntax}}|]);
                }
            
                void N(Func<int, int> f)
                {
                }
            }
            """;
 
        var fixedCode = $$"""
            using System;
            
            class C
            {
                void M()
                {
                    int i = 0;
                    N(static {{anonymousFunctionSyntax}});
                }
            
                void N(Func<int, int> f)
                {
                }
            }
            """;
 
        await TestWithCSharp9Async(code, fixedCode);
    }
 
    [Fact]
    public async Task TestNestedLambdasWithNoCaptures()
    {
        var code = """
            using System;
            
            class C
            {
                void M()
                {
                    N([|() =>
                    {
                        Action a = [|() => { }|];
                    }|]);
                }
            
                void N(Action a)
                {
                }
            }
            """;
 
        var fixedCode = """
            using System;
            
            class C
            {
                void M()
                {
                    N(static () =>
                    {
                        Action a = static () => { };
                    });
                }
            
                void N(Action a)
                {
                }
            }
            """;
 
        await TestWithCSharp9Async(code, fixedCode);
    }
 
    [Fact]
    public async Task TestNestedAnonymousMethodsWithNoCaptures()
    {
        var code = """
            using System;
            
            class C
            {
                void M()
                {
                    N([|delegate ()
                    {
                        Action a = [|delegate () { }|];
                    }|]);
                }
            
                void N(Action a)
                {
                }
            }
            """;
 
        var fixedCode = """
            using System;
            
            class C
            {
                void M()
                {
                    N(static delegate ()
                    {
                        Action a = static delegate () { };
                    });
                }
            
                void N(Action a)
                {
                }
            }
            """;
 
        await TestWithCSharp9Async(code, fixedCode);
    }
}