File: AddImport\AddImportCodeRefactoringTests.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.AddImport;
using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions;
using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.AddImport;
 
using VerifyCS = CSharpCodeRefactoringVerifier<CSharpAddImportCodeRefactoringProvider>;
 
[UseExportProvider]
[Trait(Traits.Feature, Traits.Features.CodeActionsAddImport)]
public sealed class AddImportCodeRefactoringTests
{
    [Fact]
    public Task TestSimpleQualifiedTypeName()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                [||]System.Threading.Tasks.Task M() => null;
            }
            """,
            """
            using System.Threading.Tasks;
 
            class C
            {
                Task M() => null;
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InReturnType()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                System.Threading.Tasks.[||]Task M() => null;
            }
            """,
            """
            using System.Threading.Tasks;
 
            class C
            {
                Task M() => null;
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_GenericType()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                [||]System.Collections.Generic.List<int> M() => null;
            }
            """,
            """
            using System.Collections.Generic;
 
            class C
            {
                List<int> M() => null;
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InParameter()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                void M([||]System.Threading.Tasks.Task t) { }
            }
            """,
            """
            using System.Threading.Tasks;
 
            class C
            {
                void M(Task t) { }
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InField()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                private [||]System.Threading.Tasks.Task _task;
            }
            """,
            """
            using System.Threading.Tasks;
 
            class C
            {
                private Task _task;
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InLocalVariable()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                void M()
                {
                    [||]System.Threading.Tasks.Task task = null;
                }
            }
            """,
            """
            using System.Threading.Tasks;
 
            class C
            {
                void M()
                {
                    Task task = null;
                }
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InNewExpression()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                void M()
                {
                    var list = new [||]System.Collections.Generic.List<int>();
                }
            }
            """,
            """
            using System.Collections.Generic;
 
            class C
            {
                void M()
                {
                    var list = new List<int>();
                }
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InTypeof()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                void M()
                {
                    var type = typeof([||]System.Threading.Tasks.Task);
                }
            }
            """,
            """
            using System.Threading.Tasks;
 
            class C
            {
                void M()
                {
                    var type = typeof(Task);
                }
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InBaseType()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C : [||]System.Exception
            {
            }
            """,
            """
            using System;
 
            class C : Exception
            {
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InInterface()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C : [||]System.IDisposable
            {
                public void Dispose() { }
            }
            """,
            """
            using System;
 
            class C : IDisposable
            {
                public void Dispose() { }
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InGenericConstraint()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C<T> where T : [||]System.IDisposable
            {
            }
            """,
            """
            using System;
 
            class C<T> where T : IDisposable
            {
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InCastExpression()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                void M(object o)
                {
                    var e = ([||]System.Exception)o;
                }
            }
            """,
            """
            using System;
 
            class C
            {
                void M(object o)
                {
                    var e = (Exception)o;
                }
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InIsExpression()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                void M(object o)
                {
                    var b = o is [||]System.Exception;
                }
            }
            """,
            """
            using System;
 
            class C
            {
                void M(object o)
                {
                    var b = o is Exception;
                }
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InAsExpression()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                void M(object o)
                {
                    var e = o as [||]System.Exception;
                }
            }
            """,
            """
            using System;
 
            class C
            {
                void M(object o)
                {
                    var e = o as Exception;
                }
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_NestedNamespace()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                [||]System.Threading.Tasks.Task<int> M() => null;
            }
            """,
            """
            using System.Threading.Tasks;
 
            class C
            {
                Task<int> M() => null;
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_InAttribute()
        => VerifyCS.VerifyRefactoringAsync(
            """
            [[||]System.Obsolete]
            class C
            {
            }
            """,
            """
            using System;
 
            [Obsolete]
            class C
            {
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_NotOfferedWhenUsingAlreadyExists()
        => VerifyCS.VerifyRefactoringAsync(
            """
            using System.Threading.Tasks;
 
            class C
            {
                [||]System.Threading.Tasks.Task M() => null;
            }
            """);
 
    [Fact]
    public Task TestQualifiedTypeName_NotOfferedOnNamespace()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                void M()
                {
                    var x = nameof([||]System.Threading);
                }
            }
            """);
 
    [Fact]
    public Task TestStaticMemberAccess()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                void M()
                {
                    [||]System.Console.WriteLine();
                }
            }
            """,
            """
            using System;
 
            class C
            {
                void M()
                {
                    Console.WriteLine();
                }
            }
            """);
 
    [Fact]
    public Task TestStaticMemberAccess_InMiddle()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                void M()
                {
                    System.[||]Console.WriteLine();
                }
            }
            """,
            """
            using System;
 
            class C
            {
                void M()
                {
                    Console.WriteLine();
                }
            }
            """);
 
    [Fact]
    public Task TestStaticMemberAccess_WithExistingUsing()
        => VerifyCS.VerifyRefactoringAsync(
            """
            using System;
 
            class C
            {
                void M()
                {
                    [||]System.Console.WriteLine();
                }
            }
            """);
 
    [Fact]
    public Task TestGlobalQualifiedName()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                [||]global::System.Threading.Tasks.Task M() => null;
            }
            """,
            """
            using System.Threading.Tasks;
 
            class C
            {
                Task M() => null;
            }
            """);
 
    [Fact]
    public Task TestAmbiguity_TypeWithSameNameInScope1()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class Task { }
 
            class C
            {
                [||]System.Threading.Tasks.Task M() => null;
            }
            """,
            """
            using System.Threading.Tasks;
 
            class Task { }
 
            class C
            {
                System.Threading.Tasks.Task M() => null;
            }
            """);
 
    [Fact]
    public Task TestAmbiguity_TypeWithSameNameInScope2()
        => VerifyCS.VerifyRefactoringAsync(
            """
            using N;
 
            namespace N
            {
                class Task { }
            }
 
            class C
            {
                [||]System.Threading.Tasks.Task M() => null;
            }
 
            class D
            {
                Task M() => null;
            }
            """,
            """
            using System.Threading.Tasks;
            using N;
 
            namespace N
            {
                class Task { }
            }
 
            class C
            {
                System.Threading.Tasks.Task M() => null;
            }
            
            class D
            {
                N.Task M() => null;
            }
            """);
 
    [Fact]
    public Task TestSimplifyAllOccurrences_MultipleUsages()
    {
        return new VerifyCS.Test
        {
            TestCode = """
                class C
                {
                    [||]System.Threading.Tasks.Task M1() => null;
                    System.Threading.Tasks.Task M2() => null;
                    System.Threading.Tasks.Task<int> M3() => null;
                }
                """,
            FixedCode = """
                using System.Threading.Tasks;
 
                class C
                {
                    Task M1() => null;
                    Task M2() => null;
                    Task<int> M3() => null;
                }
                """,
            CodeActionIndex = 1,
        }.RunAsync();
    }
 
    [Fact]
    public Task TestSimplifyAllOccurrences_MixedUsages()
    {
        return new VerifyCS.Test
        {
            TestCode = """
                class C
                {
                    [||]System.Threading.Tasks.Task M1() => null;
                    void M2(System.Threading.Tasks.Task t) { }
                    System.Threading.Tasks.Task<string> _field;
                }
                """,
            FixedCode = """
                using System.Threading.Tasks;
 
                class C
                {
                    Task M1() => null;
                    void M2(Task t) { }
                    Task<string> _field;
                }
                """,
            CodeActionIndex = 1,
        }.RunAsync();
    }
 
    [Fact]
    public Task TestSimplifyAllOccurrences_WithOtherNamespaces()
    {
        return new VerifyCS.Test
        {
            TestCode = """
                class C
                {
                    [||]System.Threading.Tasks.Task M1() => null;
                    System.Collections.Generic.List<int> M2() => null;
                }
                """,
            FixedCode = """
                using System.Threading.Tasks;
 
                class C
                {
                    Task M1() => null;
                    System.Collections.Generic.List<int> M2() => null;
                }
                """,
            CodeActionIndex = 1,
        }.RunAsync();
    }
 
    [Fact]
    public Task TestSimplifyOnlyCurrentOccurrence()
    {
        return new VerifyCS.Test
        {
            TestCode = """
                class C
                {
                    [||]System.Threading.Tasks.Task M1() => null;
                    System.Threading.Tasks.Task M2() => null;
                }
                """,
            FixedCode = """
                using System.Threading.Tasks;
 
                class C
                {
                    Task M1() => null;
                    System.Threading.Tasks.Task M2() => null;
                }
                """,
        }.RunAsync();
    }
 
    [Fact]
    public Task TestNotOfferedOnBuiltInType()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                [||]int M() => 0;
            }
            """);
 
    [Fact]
    public Task TestNotOfferedOnGlobalAloneType()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class TopLevel { }
            
            class C
            {
                [||]global::TopLevel M() => null;
            }
            """);
 
    [Fact]
    public Task TestGlobalQualifiedName_OnGlobal()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                [||]global::System.DateTime M() => default;
            }
            """,
            """
            using System;
 
            class C
            {
                DateTime M() => default;
            }
            """);
 
    [Fact]
    public Task TestGlobalQualifiedName_OnSystem()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                global::[||]System.DateTime M() => default;
            }
            """,
            """
            using System;
 
            class C
            {
                DateTime M() => default;
            }
            """);
 
    [Fact]
    public Task TestGlobalQualifiedName_OnTypeName()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                global::System.[||]DateTime M() => default;
            }
            """,
            """
            using System;
 
            class C
            {
                DateTime M() => default;
            }
            """);
 
    [Fact]
    public Task TestNotOfferedOnMethod_GlobalQualified()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                void M()
                {
                    global::System.Console.[||]WriteLine();
                }
            }
            """);
 
    [Fact]
    public Task TestNotOfferedOnMethod_Qualified()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                void M()
                {
                    System.Console.[||]WriteLine();
                }
            }
            """);
 
    [Fact]
    public Task TestNotOfferedOnMethod_Simple()
        => VerifyCS.VerifyRefactoringAsync(
            """
            using System;
 
            class C
            {
                void M()
                {
                    Console.[||]WriteLine();
                }
            }
            """);
 
    [Fact]
    public Task TestNotOfferedOnSimpleConsole()
        => VerifyCS.VerifyRefactoringAsync(
            """
            using System;
 
            class C
            {
                void M()
                {
                    [||]Console.WriteLine();
                }
            }
            """);
 
    [Fact]
    public Task TestNotOfferedInUsingAliasDirective()
        => VerifyCS.VerifyRefactoringAsync(
            """
            using X = [||]System.Console;
 
            class C
            {
                void M() { X.WriteLine(); }
            }
            """);
 
    [Fact]
    public Task TestNestedType_OfferOnOuterType()
        => VerifyCS.VerifyRefactoringAsync(
            """
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
            }
 
            class C
            {
                [||]NS1.NS2.T1.T2 M() => null;
            }
            """,
            """
            using NS1.NS2;
 
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
            }
 
            class C
            {
                T1.T2 M() => null;
            }
            """);
 
    [Fact]
    public Task TestNestedType_OfferOnOuterType2()
        => VerifyCS.VerifyRefactoringAsync(
            """
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
            
                class C
                {
                    [||]T1.T2 M() => null;
                }
            }
            """,
            """
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
 
                class C
                {
                    T1.T2 M() => null;
                }
            }
            """);
 
    [Fact]
    public Task TestNestedType_OfferOnOuterType3()
        => VerifyCS.VerifyRefactoringAsync(
            """
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
            
                class C
                {
                    T1.[||]T2 M() => null;
                }
            }
            """,
            """
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
 
                class C
                {
                    T1.T2 M() => null;
                }
            }
            """);
 
    [Fact]
    public Task TestNestedType_OfferOnNS1()
        => VerifyCS.VerifyRefactoringAsync(
            """
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
            }
 
            class C
            {
                [||]NS1.NS2.T1.T2 M() => null;
            }
            """,
            """
            using NS1.NS2;
 
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
            }
 
            class C
            {
                T1.T2 M() => null;
            }
            """);
 
    [Fact]
    public Task TestNestedType_OfferOnNS2()
        => VerifyCS.VerifyRefactoringAsync(
            """
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
            }
 
            class C
            {
                NS1.[||]NS2.T1.T2 M() => null;
            }
            """,
            """
            using NS1.NS2;
 
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
            }
 
            class C
            {
                T1.T2 M() => null;
            }
            """);
 
    [Fact]
    public Task TestNestedType_OfferOnT1()
        => VerifyCS.VerifyRefactoringAsync(
            """
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
            }
 
            class C
            {
                NS1.NS2.[||]T1.T2 M() => null;
            }
            """,
            """
            using NS1.NS2;
 
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
            }
 
            class C
            {
                T1.T2 M() => null;
            }
            """);
 
    [Fact]
    public Task TestNestedType_NotOfferedOnT2()
        => VerifyCS.VerifyRefactoringAsync(
            """
            namespace NS1.NS2
            {
                class T1
                {
                    public class T2 { }
                }
            }
 
            class C
            {
                NS1.NS2.T1.[||]T2 M() => null;
            }
            """);
 
    [Fact]
    public Task TestNestedGeneric_OuterName_SimplifiesBoth()
        => VerifyCS.VerifyRefactoringAsync(
            """
            class C
            {
                [||]System.Collections.Generic.List<System.Collections.Generic.List<int>> M() => null;
            }
            """,
            """
            using System.Collections.Generic;
 
            class C
            {
                List<List<int>> M() => null;
            }
            """);
 
    [Fact]
    public Task TestNestedGeneric_InnerName_SimplifiesOnlyInner()
        => new VerifyCS.Test
        {
            TestCode = """
                class C
                {
                    System.Collections.Generic.List<[||]System.Collections.Generic.List<int>> M() => null;
                }
                """,
            FixedCode = """
                using System.Collections.Generic;
 
                class C
                {
                    System.Collections.Generic.List<List<int>> M() => null;
                }
                """,
            CodeActionIndex = 0,
        }.RunAsync();
 
    [Fact]
    public Task TestNestedGeneric_InnerName_SimplifyAll_SimplifiesBoth()
        => new VerifyCS.Test
        {
            TestCode = """
                class C
                {
                    System.Collections.Generic.List<[||]System.Collections.Generic.List<int>> M() => null;
                }
                """,
            FixedCode = """
                using System.Collections.Generic;
 
                class C
                {
                    List<List<int>> M() => null;
                }
                """,
            CodeActionIndex = 1,
        }.RunAsync();
 
    [Fact]
    public Task TestNotOnAliasQualifiedName()
        => new VerifyCS.Test
        {
            TestCode = """
                using SysTasks = System.Threading.Tasks;
 
                class C
                {
                    [||]SysTasks.Task M() => null;
                }
                """,
            FixedCode = """
                using SysTasks = System.Threading.Tasks;
                
                class C
                {
                    SysTasks.Task M() => null;
                }
                """,
        }.RunAsync();
 
    [Fact]
    public Task TestOnGenericWithAliasNameInTypeArgument()
        => new VerifyCS.Test
        {
            TestCode = """
                using SysTasks = System.Threading.Tasks;
 
                class C
                {
                    [||]System.Collections.Generic.List<SysTasks.Task> M() => null;
                }
                """,
            FixedCode = """
                using System.Collections.Generic;
                using SysTasks = System.Threading.Tasks;
                
                class C
                {
                    List<SysTasks.Task> M() => null;
                }
                """,
        }.RunAsync();
 
    [Fact]
    public Task TestNotWithGlobalAliasInSameFile()
        => new VerifyCS.Test
        {
            TestCode =
                """
                global using System.Threading.Tasks;
 
                class C
                {
                    [||]System.Threading.Tasks.Task M() => null;
                }
                """,
            FixedCode =
                """
                global using System.Threading.Tasks;
 
                class C
                {
                    System.Threading.Tasks.Task M() => null;
                }
                """,
            LanguageVersion = LanguageVersion.CSharp10,
        }.RunAsync();
 
    [Fact]
    public Task TestNotWithGlobalAliasInDifferentFile()
        => new VerifyCS.Test
        {
            TestState =
            {
                Sources =
                {
                    """
                    global using System.Threading.Tasks;
                    """,
                    """
                    class C
                    {
                        [||]System.Threading.Tasks.Task M() => null;
                    }
                    """,
                }
            },
            FixedState =
            {
                Sources =
                {
                    """
                    global using System.Threading.Tasks;
                    """,
                    """
                    class C
                    {
                        [||]System.Threading.Tasks.Task M() => null;
                    }
                    """,
                }
            },
            LanguageVersion = LanguageVersion.CSharp10,
        }.RunAsync();
}