File: Completion\CompletionProviders\TypeImportCompletionProviderTests.cs
Web Access
Project: src\src\EditorFeatures\CSharpTest\Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.CSharp.Completion.Providers;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders;
 
[UseExportProvider]
[Trait(Traits.Feature, Traits.Features.Completion)]
public sealed class TypeImportCompletionProviderTests : AbstractCSharpCompletionProviderTests
{
    internal override Type GetCompletionProviderType()
        => typeof(TypeImportCompletionProvider);
 
    public TypeImportCompletionProviderTests()
    {
        ShowImportCompletionItemsOptionValue = true;
        ForceExpandedCompletionIndexCreation = true;
    }
 
    [InlineData(null)]
    [InlineData(true)]
    [InlineData(false)]
    [Theory]
    public async Task OptionSetToTrue(bool? optionValue)
    {
        ShowImportCompletionItemsOptionValue = optionValue;
 
        var markup = """
            class Bar
            {
                 $$
            }
            """;
 
        if (!optionValue.HasValue || optionValue.Value)
        {
            await VerifyAnyItemExistsAsync(markup);
        }
        else
        {
            await VerifyNoItemsExistAsync(markup);
        }
    }
 
    #region "CompletionItem tests"
 
    [InlineData("class", (int)Glyph.ClassPublic)]
    [InlineData("record", (int)Glyph.ClassPublic)]
    [InlineData("struct", (int)Glyph.StructurePublic)]
    [InlineData("enum", (int)Glyph.EnumPublic)]
    [InlineData("interface", (int)Glyph.InterfacePublic)]
    [Theory]
    public Task Show_TopLevel_NoImport_InProject(string typeKind, int glyph)
        => VerifyTypeImportItemExistsAsync(
            CreateMarkupForSingleProject("""
                namespace Baz
                {
                    class Bat
                    {
                         $$
                    }
                }
                """, $$"""
                namespace Foo
                {
                    public {{typeKind}} Bar
                    {}
                }
                """, LanguageNames.CSharp),
            "Bar",
            glyph: glyph,
            inlineDescription: "Foo");
 
    [InlineData("class", (int)Glyph.ClassPublic)]
    [InlineData("record", (int)Glyph.ClassPublic)]
    [InlineData("struct", (int)Glyph.StructurePublic)]
    [InlineData("enum", (int)Glyph.EnumPublic)]
    [InlineData("interface", (int)Glyph.InterfacePublic)]
    [Theory]
    public Task Show_TopLevelStatement_NoImport_InProject(string typeKind, int glyph)
        => VerifyTypeImportItemExistsAsync(
            CreateMarkupForSingleProject("""
                $$
                """, $$"""
                namespace Foo
                {
                    public {{typeKind}} Bar
                    {}
                }
                """, LanguageNames.CSharp),
            "Bar",
            glyph: glyph,
            inlineDescription: "Foo");
 
    [InlineData("class")]
    [InlineData("record")]
    [InlineData("struct")]
    [InlineData("enum")]
    [InlineData("interface")]
    [Theory]
    public Task DoNotShow_TopLevel_SameNamespace_InProject(string typeKind)
        => VerifyTypeImportItemIsAbsentAsync(
            CreateMarkupForSingleProject("""
                namespace Foo
                {
                    class Bat
                    {
                         $$
                    }
                }
                """, $$"""
                namespace Foo
                {
                    public {{typeKind}} Bar
                    {}
                }
                """, LanguageNames.CSharp),
            "Bar",
            inlineDescription: "Foo");
 
    [InlineData("class", (int)Glyph.ClassPublic)]
    [InlineData("record", (int)Glyph.ClassPublic)]
    [InlineData("struct", (int)Glyph.StructurePublic)]
    [InlineData("interface", (int)Glyph.InterfacePublic)]
    [Theory]
    public async Task Show_TopLevel_MutipleOverrides_NoImport_InProject(string typeKind, int glyph)
    {
        var file1 = $$"""
            namespace Foo
            {
                public {{typeKind}} Bar
                {} 
 
                public {{typeKind}} Bar<T>
                {}                   
 
                public {{typeKind}} Bar<T1, T2>
                {}
            }
            """;
 
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyTypeImportItemExistsAsync(markup, "Bar", glyph: glyph, inlineDescription: "Foo");
        await VerifyTypeImportItemExistsAsync(markup, "Bar", displayTextSuffix: "<>", glyph: glyph, inlineDescription: "Foo");
    }
 
    [InlineData("class")]
    [InlineData("record")]
    [InlineData("struct")]
    [InlineData("enum")]
    [InlineData("interface")]
    [Theory]
    public async Task DoNotShow_NestedType_NoImport_InProject(string typeKind)
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {
                    public {{typeKind}} Faz {}
                }
            }
            """;
 
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Faz", inlineDescription: "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Faz", inlineDescription: "Foo.Bar");
    }
 
    [InlineData("class")]
    [InlineData("record")]
    [InlineData("struct")]
    [InlineData("enum")]
    [InlineData("interface")]
    [Theory]
    public async Task DoNotShow_TopLevel_WithImport_InProject(string typeKind)
    {
        var file1 = $$"""
            namespace Foo
            {
                public {{typeKind}} Bar
                {}
            }
            """;
 
        var file2 = """
            namespace Baz
            {
                using Foo;
 
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", inlineDescription: "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task Show_TopLevel_Public_NoImport_InReference(bool isProjectReference)
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {}
 
                public record Bar2
                {}
            }
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = GetMarkupWithReference(file2, file1, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemExistsAsync(markup, "Bar", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo");
        await VerifyTypeImportItemExistsAsync(markup, "Bar2", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task DoNotShow_TopLevel_Public_WithImport_InReference(bool isProjectReference)
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {}
 
                public record Bar2
                {}
            }
            """;
        var file2 = """
            using Foo;
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = GetMarkupWithReference(file2, file1, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", inlineDescription: "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar2", inlineDescription: "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task DoNotShow_TopLevel_Internal_NoImport_InReference(bool isProjectReference)
    {
        var file1 = $$"""
            namespace Foo
            {
                internal class Bar
                {}
 
                internal record Bar2
                {}
            }
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = GetMarkupWithReference(file2, file1, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", inlineDescription: "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar2", inlineDescription: "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task TopLevel_OverloadsWithMixedAccessibility_Internal_NoImport_InReference1(bool isProjectReference)
    {
        var file1 = $$"""
            namespace Foo
            {
                internal class Bar
                {}
 
                public class Bar<T>
                {}
            }
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = GetMarkupWithReference(file2, file1, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", displayTextSuffix: "", inlineDescription: "Foo");
        await VerifyTypeImportItemExistsAsync(markup, "Bar", displayTextSuffix: "<>", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task DoNotShow_TopLevel_OverloadsWithMixedAccessibility_Internal_WithImport_InReference1(bool isProjectReference)
    {
        var file1 = $$"""
            namespace Foo
            {
                internal class Bar
                {}
 
                public class Bar<T>
                {}
            }
            """;
        var file2 = """
            using Foo;
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = GetMarkupWithReference(file2, file1, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", displayTextSuffix: "", inlineDescription: "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", displayTextSuffix: "<>", inlineDescription: "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task TopLevel_OverloadsWithMixedAccessibility_InternalWithIVT_NoImport_InReference1(bool isProjectReference)
    {
        var file1 = $$"""
            [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Project1")]
 
            namespace Foo
            {
                internal class Bar
                {}
 
                public class Bar<T>
                {}
            }
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = GetMarkupWithReference(file2, file1, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemExistsAsync(markup, "Bar", glyph: (int)Glyph.ClassInternal, inlineDescription: "Foo");
        await VerifyTypeImportItemExistsAsync(markup, "Bar", displayTextSuffix: "<>", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task DoNotShow_TopLevel_OverloadsWithMixedAccessibility_InternalWithIVT_WithImport_InReference1(bool isProjectReference)
    {
        var file1 = $$"""
            [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Project1")]
 
            namespace Foo
            {
                internal class Bar
                {}
 
                public class Bar<T>
                {}
            }
            """;
        var file2 = """
            using Foo;
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = GetMarkupWithReference(file2, file1, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", inlineDescription: "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", displayTextSuffix: "<>", inlineDescription: "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task TopLevel_OverloadsWithMixedAccessibility_Internal_NoImport_InReference2(bool isProjectReference)
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {}
 
                public class Bar<T>
                {}    
 
                internal class Bar<T1, T2>
                {}
            }
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = GetMarkupWithReference(file2, file1, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemExistsAsync(markup, "Bar", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo");
        await VerifyTypeImportItemExistsAsync(markup, "Bar", displayTextSuffix: "<>", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task DoNotShow_TopLevel_OverloadsWithMixedAccessibility_Internal_SameNamespace_InReference2(bool isProjectReference)
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {}
 
                public class Bar<T>
                {}    
 
                internal class Bar<T1, T2>
                {}
            }
            """;
        var file2 = """
            namespace Foo.Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = GetMarkupWithReference(file2, file1, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", inlineDescription: "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", displayTextSuffix: "<>", inlineDescription: "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task TopLevel_OverloadsWithMixedAccessibility_InternalWithIVT_NoImport_InReference2(bool isProjectReference)
    {
        var file1 = $$"""
            [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Project1")]
 
            namespace Foo
            {
                internal class Bar
                {}
 
                internal class Bar<T>
                {}    
 
                internal class Bar<T1, T2>
                {}
            }
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = GetMarkupWithReference(file2, file1, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemExistsAsync(markup, "Bar", glyph: (int)Glyph.ClassInternal, inlineDescription: "Foo");
        await VerifyTypeImportItemExistsAsync(markup, "Bar", displayTextSuffix: "<>", glyph: (int)Glyph.ClassInternal, inlineDescription: "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task Show_TopLevel_Internal_WithIVT_NoImport_InReference(bool isProjectReference)
    {
        var file1 = $$"""
            [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Project1")]
 
            namespace Foo
            {
                internal class Bar
                {}
            }
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = GetMarkupWithReference(file2, file1, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemExistsAsync(markup, "Bar", glyph: (int)Glyph.ClassInternal, inlineDescription: "Foo");
    }
 
    [Fact]
    public async Task Show_TopLevel_NoImport_InVBReference()
    {
        var file1 = $"""
            Namespace Bar
                Public Class Barr
                End CLass
            End Namespace
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = CreateMarkupForProjecWithVBProjectReference(file2, file1, sourceLanguage: LanguageNames.CSharp, rootNamespace: "Foo");
        await VerifyTypeImportItemExistsAsync(markup, "Barr", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo.Bar");
    }
 
    [Fact]
    public async Task VB_MixedCapitalization_Test()
    {
        var file1 = $"""
            Namespace Na
                Public Class Foo
                End Class
            End Namespace
 
            Namespace na
                Public Class Bar
                End Class
            End Namespace
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = CreateMarkupForProjecWithVBProjectReference(file2, file1, sourceLanguage: LanguageNames.CSharp, rootNamespace: "");
        await VerifyTypeImportItemExistsAsync(markup, "Bar", glyph: (int)Glyph.ClassPublic, inlineDescription: "Na");
        await VerifyTypeImportItemExistsAsync(markup, "Foo", glyph: (int)Glyph.ClassPublic, inlineDescription: "Na");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", inlineDescription: "na");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Foo", inlineDescription: "na");
    }
 
    [Fact]
    public async Task VB_MixedCapitalization_WithImport_Test()
    {
        var file1 = $"""
            Namespace Na
                Public Class Foo
                End Class
            End Namespace
 
            Namespace na
                Public Class Bar
                End Class
            End Namespace
            """;
        var file2 = """
            using Na;
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = CreateMarkupForProjecWithVBProjectReference(file2, file1, sourceLanguage: LanguageNames.CSharp, rootNamespace: "");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", inlineDescription: "Na");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Foo", inlineDescription: "Na");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", inlineDescription: "na");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Foo", inlineDescription: "na");
    }
 
    [Fact]
    public async Task DoNotShow_TopLevel_Internal_NoImport_InVBReference()
    {
        var file1 = $"""
            Namespace Bar
                Friend Class Barr
                End CLass
            End Namespace
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = CreateMarkupForProjecWithVBProjectReference(file2, file1, sourceLanguage: LanguageNames.CSharp, rootNamespace: "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Barr", inlineDescription: "Foo.Bar");
    }
 
    [Fact]
    public async Task DoNotShow_TopLevel_WithImport_InVBReference()
    {
        var file1 = $"""
            Namespace Bar
                Public Class Barr
                End CLass
            End Namespace
            """;
        var file2 = """
            using Foo.Bar;
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = CreateMarkupForProjecWithVBProjectReference(file2, file1, sourceLanguage: LanguageNames.CSharp, rootNamespace: "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Barr", inlineDescription: "Foo.Bar");
    }
 
    [Theory, CombinatorialData]
    public async Task TypesWithIdenticalNameButDifferentNamespaces(bool isProjectReference)
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {}
 
                public class Bar<T>
                {}
            }
            namespace Baz
            {
                public class Bar<T>
                {} 
 
                public class Bar
                {}
            }
            """;
        var file2 = """
            namespace NS
            {
                class C
                {
                     $$
                }
            }
            """;
        var markup = GetMarkupWithReference(file2, file1, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemExistsAsync(markup, "Bar", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo");
        await VerifyTypeImportItemExistsAsync(markup, "Bar", displayTextSuffix: "<>", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo");
        await VerifyTypeImportItemExistsAsync(markup, "Bar", glyph: (int)Glyph.ClassPublic, inlineDescription: "Baz");
        await VerifyTypeImportItemExistsAsync(markup, "Bar", displayTextSuffix: "<>", glyph: (int)Glyph.ClassPublic, inlineDescription: "Baz");
    }
 
    [Theory, CombinatorialData]
    public async Task TestNoCompletionItemWhenThereIsAlias(bool isProjectReference)
    {
        var file1 = """
            using AliasFoo1 = Foo1.Foo2.Foo3.Foo4;
            using AliasFoo2 = Foo1.Foo2.Foo3.Foo4.Foo6;
 
            namespace Bar
            {
                using AliasFoo3 = Foo1.Foo2.Foo3.Foo5;
                using AliasFoo4 = Foo1.Foo2.Foo3.Foo5.Foo7;
                public class CC
                {
                    public static void Main()
                    {    
                        F$$
                    }
                }
            }
            """;
        var file2 = """
            namespace Foo1
            {
                namespace Foo2
                {
                    namespace Foo3
                    {
                        public class Foo4
                        {
                            public class Foo6
                            {
                            }
                        }
 
                        public class Foo5
                        {
                            public class Foo7
                            {
                            }
                        }
                    }
                }
            }
            """;
 
        var markup = GetMarkupWithReference(file1, file2, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Foo4", "Foo1.Foo2.Foo3");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Foo6", "Foo1.Foo2.Foo3");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Foo5", "Foo1.Foo2.Foo3");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Foo7", "Foo1.Foo2.Foo3");
    }
 
    [Theory, CombinatorialData]
    public async Task TestAttributesAlias(bool isProjectReference)
    {
        var file1 = """
            using myAlias = Foo.BarAttribute;
            using myAlia2 = Foo.BarAttributeDifferentEnding;
 
            namespace Foo2
            {
                public class Main
                {
                    $$
                }
            }
            """;
 
        var file2 = """
            namespace Foo
            {
                public class BarAttribute: System.Attribute
                {
                }
 
                public class BarAttributeDifferentEnding: System.Attribute
                {
                }
            }
            """;
 
        var markup = GetMarkupWithReference(file1, file2, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "BarAttribute", "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "BarAttributeDifferentEnding", "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task TestGenericsAliasHasNoEffect(bool isProjectReference)
    {
        var file1 = """
            using AliasFoo1 = Foo1.Foo2.Foo3.Foo4<int>;
 
            namespace Bar
            {
                using AliasFoo2 = Foo1.Foo2.Foo3.Foo5<string>;
                public class CC
                {
                    public static void Main()
                    {    
                        F$$
                    }
                }
            }
            """;
        var file2 = """
            namespace Foo1
            {
                namespace Foo2
                {
                    namespace Foo3
                    {
                        public class Foo4<T>
                        {
                        }
 
                        public class Foo5<U>
                        {
                        }
                    }
                }
            }
            """;
 
        var markup = GetMarkupWithReference(file1, file2, LanguageNames.CSharp, LanguageNames.CSharp, isProjectReference);
        await VerifyTypeImportItemExistsAsync(markup, "Foo4", (int)Glyph.ClassPublic, "Foo1.Foo2.Foo3", displayTextSuffix: "<>");
        await VerifyTypeImportItemExistsAsync(markup, "Foo5", (int)Glyph.ClassPublic, "Foo1.Foo2.Foo3", displayTextSuffix: "<>");
    }
 
    #endregion
 
    #region "Commit Change Tests"
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    public async Task Commit_NoImport_InProject(SourceCodeKind kind)
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {
                }
            }
            """;
 
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                    $$
                }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyCustomCommitProviderAsync(markup, "Bar", """
            using Foo;
 
            namespace Baz
            {
                class Bat
                {
                    Bar$$
                }
            }
            """, sourceCodeKind: kind);
    }
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    public async Task Commit_TopLevelStatement_NoImport_InProject(SourceCodeKind kind)
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {
                }
            }
            """;
 
        var file2 = """
            $$
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyCustomCommitProviderAsync(markup, "Bar", """
            using Foo;
 
            Bar$$
            """, sourceCodeKind: kind);
    }
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    public async Task Commit_TopLevelStatement_UnrelatedImport_InProject(SourceCodeKind kind)
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {
                }
            }
            """;
 
        var file2 = """
            using System;
 
            $$
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyCustomCommitProviderAsync(markup, "Bar", """
            using System;
            using Foo;
 
            Bar$$
            """, sourceCodeKind: kind);
    }
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    public async Task Commit_NoImport_InVBReference(SourceCodeKind kind)
    {
        var file1 = $"""
            Namespace Bar
                Public Class Barr
                End CLass
            End Namespace
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                    $$
                }
            }
            """;
        var markup = CreateMarkupForProjecWithVBProjectReference(file2, file1, sourceLanguage: LanguageNames.CSharp, rootNamespace: "Foo");
        await VerifyCustomCommitProviderAsync(markup, "Barr", """
            using Foo.Bar;
 
            namespace Baz
            {
                class Bat
                {
                    Barr$$
                }
            }
            """, sourceCodeKind: kind);
    }
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    public Task Commit_NoImport_InPEReference(SourceCodeKind kind)
        => VerifyCustomCommitProviderAsync($$"""
            <Workspace>
                <Project Language="{{LanguageNames.CSharp}}" CommonReferences="true">
                    <Document FilePath="CSharpDocument">class Bar
            {
                 $$
            }</Document>
                </Project>    
            </Workspace>
            """, "Console", """
            using System;
 
            class Bar
            {
                 Console$$
            }
            """, sourceCodeKind: kind);
 
    #endregion
 
    [Fact]
    public async Task DoNotShow_TopLevel_Public_NoImport_InNonGlobalAliasedMetadataReference()
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {}
            }
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = CreateMarkupForProjectWithAliasedMetadataReference(file2, "alias1", file1, LanguageNames.CSharp, LanguageNames.CSharp, hasGlobalAlias: false);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", inlineDescription: "Foo");
    }
 
    [Fact]
    public async Task Show_TopLevel_Public_NoImport_InGlobalAliasedMetadataReference()
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {}
            }
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = CreateMarkupForProjectWithAliasedMetadataReference(file2, "alias1", file1, LanguageNames.CSharp, LanguageNames.CSharp, hasGlobalAlias: true);
        await VerifyTypeImportItemExistsAsync(markup, "Bar", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo");
    }
 
    [Fact]
    public async Task DoNotShow_TopLevel_Public_NoImport_InNonGlobalAliasedProjectReference()
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {}
            }
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = CreateMarkupForProjectWithAliasedProjectReference(file2, "alias1", file1, LanguageNames.CSharp, LanguageNames.CSharp);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", inlineDescription: "Foo");
    }
 
    [Fact]
    public async Task ShorterTypeNameShouldShowBeforeLongerTypeName()
    {
        var file1 = $$"""
            namespace Foo
            {
                public class SomeType
                {} 
                public class SomeTypeWithLongerName
                {}
            }
            """;
        var file2 = """
            namespace Baz
            {
                class Bat
                {
                     $$
                }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        var completionList = await GetCompletionListAsync(markup).ConfigureAwait(false);
        AssertRelativeOrder(["SomeType", "SomeTypeWithLongerName"], [.. completionList.ItemsList]);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35540")]
    public async Task AttributeTypeInAttributeNameContext()
    {
        var file1 = """
            namespace Foo
            {
                public class MyAttribute : System.Attribute { }
                public class MyAttributeWithoutSuffix : System.Attribute { }
                public class MyClass { }
            }
            """;
 
        var file2 = """
            namespace Test
            {
                [$$
                class Program { }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
 
        await VerifyTypeImportItemExistsAsync(markup, "My", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo", expectedDescriptionOrNull: "class Foo.MyAttribute", flags: CompletionItemFlags.Expanded);
        await VerifyTypeImportItemIsAbsentAsync(markup, "MyAttributeWithoutSuffix", inlineDescription: "Foo");  // We intentionally ignore attribute types without proper suffix for perf reason
        await VerifyTypeImportItemIsAbsentAsync(markup, "MyAttribute", inlineDescription: "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "MyClass", inlineDescription: "Foo");
    }
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    [WorkItem("https://github.com/dotnet/roslyn/issues/35540")]
    public async Task CommitAttributeTypeInAttributeNameContext(SourceCodeKind kind)
    {
        var file1 = """
            namespace Foo
            {
                public class MyAttribute : System.Attribute { }
            }
            """;
 
        var file2 = """
            namespace Test
            {
                [$$
                class Program { }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyCustomCommitProviderAsync(markup, "My", """
            using Foo;
 
            namespace Test
            {
                [My$$
                class Program { }
            }
            """, sourceCodeKind: kind);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35540")]
    public async Task AttributeTypeInNonAttributeNameContext()
    {
        var file1 = """
            namespace Foo
            {
                public class MyAttribute : System.Attribute { }
                public class MyAttributeWithoutSuffix : System.Attribute { }
                public class MyClass { }
            }
            """;
 
        var file2 = """
            namespace Test
            {
                class Program 
                {
                    $$
                }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
 
        await VerifyTypeImportItemExistsAsync(markup, "MyAttribute", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo", expectedDescriptionOrNull: "class Foo.MyAttribute", flags: CompletionItemFlags.CachedAndExpanded);
        await VerifyTypeImportItemExistsAsync(markup, "MyAttributeWithoutSuffix", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo", expectedDescriptionOrNull: "class Foo.MyAttributeWithoutSuffix", flags: CompletionItemFlags.CachedAndExpanded);
        await VerifyTypeImportItemIsAbsentAsync(markup, "My", inlineDescription: "Foo");
        await VerifyTypeImportItemExistsAsync(markup, "MyClass", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo", expectedDescriptionOrNull: "class Foo.MyClass", flags: CompletionItemFlags.CachedAndExpanded);
    }
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    [WorkItem("https://github.com/dotnet/roslyn/issues/35540")]
    public async Task CommitAttributeTypeInNonAttributeNameContext(SourceCodeKind kind)
    {
        var file1 = """
            namespace Foo
            {
                public class MyAttribute : System.Attribute { }
            }
            """;
 
        var file2 = """
            namespace Test
            {
                class Program 
                {
                    $$
                }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyCustomCommitProviderAsync(markup, "MyAttribute", """
            using Foo;
 
            namespace Test
            {
                class Program 
                {
                    MyAttribute$$
                }
            }
            """, sourceCodeKind: kind);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35540")]
    public async Task AttributeTypeWithoutSuffixInAttributeNameContext()
    {
        // attribute suffix isn't capitalized
        var file1 = """
            namespace Foo
            {
                public class Myattribute : System.Attribute { }
                public class MyClass { }
            }
            """;
 
        var file2 = """
            namespace Test
            {
                [$$
                class Program { }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
 
        await VerifyTypeImportItemExistsAsync(markup, "Myattribute", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo", expectedDescriptionOrNull: "class Foo.Myattribute", flags: CompletionItemFlags.CachedAndExpanded);
        await VerifyTypeImportItemIsAbsentAsync(markup, "My", inlineDescription: "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "MyClass", inlineDescription: "Foo");
    }
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    [WorkItem("https://github.com/dotnet/roslyn/issues/35540")]
    public async Task CommitAttributeTypeWithoutSuffixInAttributeNameContext(SourceCodeKind kind)
    {
        // attribute suffix isn't capitalized
        var file1 = """
            namespace Foo
            {
                public class Myattribute : System.Attribute { }
            }
            """;
 
        var file2 = """
            namespace Test
            {
                [$$
                class Program { }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyCustomCommitProviderAsync(markup, "Myattribute", """
            using Foo;
 
            namespace Test
            {
                [Myattribute$$
                class Program { }
            }
            """, sourceCodeKind: kind);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35540")]
    public async Task AttributeTypeWithoutSuffixInNonAttributeNameContext()
    {
        // attribute suffix isn't capitalized
        var file1 = """
            namespace Foo
            {
                public class Myattribute : System.Attribute { }
                public class MyClass { }
            }
            """;
 
        var file2 = """
            namespace Test
            {
                class Program 
                {
                    $$
                }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
 
        await VerifyTypeImportItemExistsAsync(markup, "Myattribute", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo", expectedDescriptionOrNull: "class Foo.Myattribute", flags: CompletionItemFlags.Expanded);
        await VerifyTypeImportItemIsAbsentAsync(markup, "My", inlineDescription: "Foo");
        await VerifyTypeImportItemExistsAsync(markup, "MyClass", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo", expectedDescriptionOrNull: "class Foo.MyClass", flags: CompletionItemFlags.CachedAndExpanded);
    }
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    [WorkItem("https://github.com/dotnet/roslyn/issues/35540")]
    public async Task CommitAttributeTypeWithoutSuffixInNonAttributeNameContext(SourceCodeKind kind)
    {
        // attribute suffix isn't capitalized
        var file1 = """
            namespace Foo
            {
                public class Myattribute : System.Attribute { }
            }
            """;
 
        var file2 = """
            namespace Test
            {
                class Program 
                {
                    $$
                }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyCustomCommitProviderAsync(markup, "Myattribute", """
            using Foo;
 
            namespace Test
            {
                class Program 
                {
                    Myattribute$$
                }
            }
            """, sourceCodeKind: kind);
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/35540")]
    public async Task VBAttributeTypeWithoutSuffixInAttributeNameContext()
    {
        var file1 = """
            Namespace Foo
                Public Class Myattribute
                    Inherits System.Attribute
                End Class
                Public Class MyVBClass
                End Class
            End Namespace
            """;
 
        var file2 = """
            namespace Test
            {
                [$$
                class Program 
                {
                }
            }
            """;
 
        var markup = CreateMarkupForProjectWithProjectReference(file2, file1, LanguageNames.CSharp, LanguageNames.VisualBasic);
 
        await VerifyTypeImportItemExistsAsync(markup, "Myattribute", glyph: (int)Glyph.ClassPublic, inlineDescription: "Foo", expectedDescriptionOrNull: "class Foo.Myattribute", flags: CompletionItemFlags.Expanded);
        await VerifyTypeImportItemIsAbsentAsync(markup, "My", inlineDescription: "Foo");
        await VerifyTypeImportItemIsAbsentAsync(markup, "MyVBClass", inlineDescription: "Foo");
    }
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    [WorkItem("https://github.com/dotnet/roslyn/issues/37038")]
    public async Task CommitTypeInUsingStaticContextShouldUseFullyQualifiedName(SourceCodeKind kind)
    {
        var file1 = """
            namespace Foo
            {
                public class MyClass { }
            }
            """;
 
        var file2 = """
            using static $$
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyCustomCommitProviderAsync(markup, "MyClass", """
            using static Foo.MyClass$$
            """, sourceCodeKind: kind);
    }
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    [WorkItem("https://github.com/dotnet/roslyn/issues/37038")]
    public async Task CommitGenericTypeParameterInUsingAliasContextShouldUseFullyQualifiedName(SourceCodeKind kind)
    {
        var file1 = """
            namespace Foo
            {
                public class MyClass { }
            }
            """;
 
        var file2 = """
            using CollectionOfStringBuilders = System.Collections.Generic.List<$$>
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyCustomCommitProviderAsync(markup, "MyClass", """
            using CollectionOfStringBuilders = System.Collections.Generic.List<Foo.MyClass$$>
            """, sourceCodeKind: kind);
    }
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    [WorkItem("https://github.com/dotnet/roslyn/issues/37038")]
    public async Task CommitGenericTypeParameterInUsingAliasContextShouldUseFullyQualifiedName2(SourceCodeKind kind)
    {
        var file1 = """
            namespace Foo.Bar
            {
                public class MyClass { }
            }
            """;
 
        var file2 = """
            namespace Foo
            {
                using CollectionOfStringBuilders = System.Collections.Generic.List<$$>
            }
            """;
 
        // Completion is not fully qualified
 
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyCustomCommitProviderAsync(markup, "MyClass", """
            namespace Foo
            {
                using CollectionOfStringBuilders = System.Collections.Generic.List<Foo.Bar.MyClass$$>
            }
            """, sourceCodeKind: kind);
    }
 
    [Fact]
    [Trait(Traits.Feature, Traits.Features.Interactive)]
    [WorkItem("https://github.com/dotnet/roslyn/issues/39027")]
    public async Task TriggerCompletionInSubsequentSubmission()
    {
        var markup = """
            <Workspace>
                <Submission Language="C#" CommonReferences="true">  
                    var x = "10";
                </Submission>
                <Submission Language="C#" CommonReferences="true">  
                    var y = $$
                </Submission>
            </Workspace>
            """;
 
        var completionList = await GetCompletionListAsync(markup, workspaceKind: WorkspaceKind.Interactive).ConfigureAwait(false);
        Assert.NotEmpty(completionList.ItemsList);
    }
 
    [Fact]
    public async Task ShouldNotTriggerInsideTrivia()
    {
        var file1 = $$"""
            namespace Foo
            {
                public class Bar
                {} 
            }
            """;
 
        var file2 = """
            namespace Baz
            {
                /// <summary>
                /// <see cref="B$$"/>
                /// </summary>
                class Bat
                {
                }
            }
            """;
        var markup = CreateMarkupForSingleProject(file2, file1, LanguageNames.CSharp);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Bar", inlineDescription: "Foo");
    }
    private static void AssertRelativeOrder(List<string> expectedTypesInRelativeOrder, ImmutableArray<CompletionItem> allCompletionItems)
    {
        var hashset = new HashSet<string>(expectedTypesInRelativeOrder);
        var actualTypesInRelativeOrder = allCompletionItems.SelectAsArray(item => hashset.Contains(item.DisplayText), item => item.DisplayText);
 
        Assert.Equal(expectedTypesInRelativeOrder.Count, actualTypesInRelativeOrder.Length);
        for (var i = 0; i < expectedTypesInRelativeOrder.Count; ++i)
        {
            Assert.Equal(expectedTypesInRelativeOrder[i], actualTypesInRelativeOrder[i]);
        }
    }
 
    [Theory, CombinatorialData]
    public async Task TestBrowsableAwaysFromReferences(bool isProjectReference)
    {
        var srcDoc = """
            class Program
            {
                void M()
                {
                    $$
                }
            }
            """;
 
        var refDoc = """
            namespace Foo
            {
                [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Always)]
                public class Goo
                {
                }
            }
            """;
 
        var markup = isProjectReference switch
        {
            true => CreateMarkupForProjectWithProjectReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp),
            false => CreateMarkupForProjectWithMetadataReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp)
        };
 
        await VerifyTypeImportItemExistsAsync(
                markup,
                "Goo",
                glyph: (int)Glyph.ClassPublic,
                inlineDescription: "Foo");
    }
 
    [Theory, CombinatorialData]
    public async Task TestBrowsableNeverFromReferences(bool isProjectReference)
    {
        var srcDoc = """
            class Program
            {
                void M()
                {
                    $$
                }
            }
            """;
 
        var refDoc = """
            namespace Foo
            {
                [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
                public class Goo
                {
                }
            }
            """;
 
        var (markup, shouldContainItem) = isProjectReference switch
        {
            true => (CreateMarkupForProjectWithProjectReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp), true),
            false => (CreateMarkupForProjectWithMetadataReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp), false),
        };
 
        if (shouldContainItem)
        {
            await VerifyTypeImportItemExistsAsync(
                    markup,
                    "Goo",
                    glyph: (int)Glyph.ClassPublic,
                    inlineDescription: "Foo");
        }
        else
        {
            await VerifyTypeImportItemIsAbsentAsync(
                    markup,
                    "Goo",
                    inlineDescription: "Foo");
        }
    }
 
    [InlineData(true, true)]
    [InlineData(true, false)]
    [InlineData(false, true)]
    [InlineData(false, false)]
    [Theory]
    public async Task TestBrowsableAdvancedFromReferences(bool isProjectReference, bool hideAdvancedMembers)
    {
        HideAdvancedMembers = hideAdvancedMembers;
 
        var srcDoc = """
            class Program
            {
                void M()
                {
                    $$
                }
            }
            """;
 
        var refDoc = """
            namespace Foo
            {
                [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
                public class Goo
                {
                }
            }
            """;
 
        var (markup, shouldContainItem) = isProjectReference switch
        {
            true => (CreateMarkupForProjectWithProjectReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp), true),
            false => (CreateMarkupForProjectWithMetadataReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp), !hideAdvancedMembers),
        };
 
        if (shouldContainItem)
        {
            await VerifyTypeImportItemExistsAsync(
                    markup,
                    "Goo",
                    glyph: (int)Glyph.ClassPublic,
                    inlineDescription: "Foo");
        }
        else
        {
            await VerifyTypeImportItemIsAbsentAsync(
                    markup,
                    "Goo",
                    inlineDescription: "Foo");
        }
    }
 
    [Theory]
    [InlineData('.')]
    [InlineData(';')]
    public Task TestCommitWithCustomizedCommitCharForParameterlessConstructor(char commitChar)
        => VerifyProviderCommitAsync("""
            namespace AA
            {
                public class C
                {
                }
            }
 
            namespace BB
            {
                public class B
                {
                    public void M()
                    {
                        var c = new $$
                    }
                }
            }
            """, "C", $$"""
            using AA;
 
            namespace AA
            {
                public class C
                {
                }
            }
 
            namespace BB
            {
                public class B
                {
                    public void M()
                    {
                        var c = new C(){{commitChar}}
                    }
                }
            }
            """, commitChar: commitChar, sourceCodeKind: SourceCodeKind.Regular);
 
    [Theory]
    [InlineData('.')]
    [InlineData(';')]
    public Task TestCommitWithCustomizedCommitCharUnderNonObjectCreationContext(char commitChar)
        => VerifyProviderCommitAsync("""
            namespace AA
            {
                public class C
                {
                }
            }
            namespace BB
            {
                public class B
                {
                    public void M()
                    {
                        $$
                    }
                }
            }
            """, "C", $$"""
            using AA;
 
            namespace AA
            {
                public class C
                {
                }
            }
            namespace BB
            {
                public class B
                {
                    public void M()
                    {
                        C{{commitChar}}
                    }
                }
            }
            """, commitChar: commitChar, sourceCodeKind: SourceCodeKind.Regular);
 
    [InlineData(SourceCodeKind.Regular)]
    [InlineData(SourceCodeKind.Script)]
    [WpfTheory]
    [WorkItem("https://github.com/dotnet/roslyn/issues/54493")]
    public Task CommitInLocalFunctionContext(SourceCodeKind kind)
        => VerifyProviderCommitAsync("""
            namespace Foo
            {
                public class MyClass { }
            }
 
            namespace Test
            {
                class Program
                {
                    public static void Main()
                    {
                        static $$
                    }
                }
            }
            """, "MyClass", """
            using Foo;
 
            namespace Foo
            {
                public class MyClass { }
            }
 
            namespace Test
            {
                class Program
                {
                    public static void Main()
                    {
                        static MyClass
                    }
                }
            }
            """, commitChar: null, sourceCodeKind: kind);
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58473")]
    public async Task TestGlobalUsingsInSdkAutoGeneratedFile()
    {
        var source = """
            using System;
            $$
            """;
 
        var globalUsings = """
            global using global::System;
            global using global::System.Collections.Generic;
            global using global::System.IO;
            global using global::System.Linq;
            global using global::System.Net.Http;
            global using global::System.Threading;
            global using global::System.Threading.Tasks;
            """;
 
        var markup = CreateMarkupForSingleProject(source, globalUsings, LanguageNames.CSharp, referencedFileName: "ProjectName.GlobalUsings.g.cs");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Task", inlineDescription: "System.Threading.Tasks");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Console", inlineDescription: "System");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58473")]
    public async Task TestGlobalUsingsInSameFile()
    {
        var source = """
            global using global::System;
            global using global::System.Threading.Tasks;
 
            $$
            """;
 
        var markup = CreateMarkupForSingleProject(source, "", LanguageNames.CSharp);
        await VerifyTypeImportItemIsAbsentAsync(markup, "Console", inlineDescription: "System");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Task", inlineDescription: "System.Threading.Tasks");
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/58473")]
    public async Task TestGlobalUsingsInUserDocument()
    {
        var source = """
            $$
            """;
 
        var globalUsings = """
            global using global::System;
            global using global::System.Collections.Generic;
            global using global::System.IO;
            global using global::System.Linq;
            global using global::System.Net.Http;
            global using global::System.Threading;
            global using global::System.Threading.Tasks;
            """;
 
        var markup = CreateMarkupForSingleProject(source, globalUsings, LanguageNames.CSharp, referencedFileName: "GlobalUsings.cs");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Task", inlineDescription: "System.Threading.Tasks");
        await VerifyTypeImportItemIsAbsentAsync(markup, "Console", inlineDescription: "System");
    }
 
    [Theory]
    [InlineData(null)]
    [InlineData(true)]
    [InlineData(false)]
    [WorkItem("https://github.com/dotnet/roslyn/issues/65339")]
    public async Task TestFileScopedType(bool? isProjectReference)
    {
        var srcDoc = """
            class Program
            {
                void M()
                {
                    $$goo
                }
            }
            """;
 
        var refDoc = """
            namespace Foo
            {
                file class Goo
                {
                }
            }
            """;
 
        string markup;
        if (isProjectReference.HasValue)
        {
            markup = isProjectReference switch
            {
                true => CreateMarkupForProjectWithProjectReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp),
                false => CreateMarkupForProjectWithMetadataReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp)
            };
        }
        else
        {
            markup = CreateMarkupForSingleProject(srcDoc, refDoc, LanguageNames.CSharp);
        }
        await VerifyTypeImportItemIsAbsentAsync(
                markup,
                "Goo",
                inlineDescription: "Foo");
    }
 
    [Fact]
    public async Task TestEnumBaseList1()
    {
        var source = """
            enum E : $$
            """;
 
        await VerifyTypeImportItemExistsAsync(source, "Byte", glyph: (int)Glyph.StructurePublic, inlineDescription: "System");
        await VerifyTypeImportItemExistsAsync(source, "SByte", glyph: (int)Glyph.StructurePublic, inlineDescription: "System");
        await VerifyTypeImportItemExistsAsync(source, "Int16", glyph: (int)Glyph.StructurePublic, inlineDescription: "System");
        await VerifyTypeImportItemExistsAsync(source, "UInt16", glyph: (int)Glyph.StructurePublic, inlineDescription: "System");
        await VerifyTypeImportItemExistsAsync(source, "Int32", glyph: (int)Glyph.StructurePublic, inlineDescription: "System");
        await VerifyTypeImportItemExistsAsync(source, "UInt32", glyph: (int)Glyph.StructurePublic, inlineDescription: "System");
        await VerifyTypeImportItemExistsAsync(source, "Int64", glyph: (int)Glyph.StructurePublic, inlineDescription: "System");
        await VerifyTypeImportItemExistsAsync(source, "UInt64", glyph: (int)Glyph.StructurePublic, inlineDescription: "System");
 
        // Verify that other things from `System` namespace are not present
        await VerifyTypeImportItemIsAbsentAsync(source, "Console", inlineDescription: "System");
        await VerifyTypeImportItemIsAbsentAsync(source, "Action", inlineDescription: "System");
        await VerifyTypeImportItemIsAbsentAsync(source, "DateTime", inlineDescription: "System");
 
        // Verify that things from other namespaces are not present
        await VerifyTypeImportItemIsAbsentAsync(source, "IEnumerable", inlineDescription: "System.Collections");
        await VerifyTypeImportItemIsAbsentAsync(source, "Task", inlineDescription: "System.Threading.Tasks");
        await VerifyTypeImportItemIsAbsentAsync(source, "AssemblyName", inlineDescription: "System.Reflection");
    }
 
    [Fact]
    public Task TestEnumBaseList2()
        => VerifyNoItemsExistAsync("""
            using System;
 
            enum E : $$
            """);
 
    private Task VerifyTypeImportItemExistsAsync(string markup, string expectedItem, int glyph, string inlineDescription, string displayTextSuffix = null, string expectedDescriptionOrNull = null, CompletionItemFlags? flags = null)
        => VerifyItemExistsAsync(markup, expectedItem, displayTextSuffix: displayTextSuffix, glyph: (Glyph)glyph, inlineDescription: inlineDescription, expectedDescriptionOrNull: expectedDescriptionOrNull, isComplexTextEdit: true, flags: flags);
 
    private Task VerifyTypeImportItemIsAbsentAsync(string markup, string expectedItem, string inlineDescription, string displayTextSuffix = null)
        => VerifyItemIsAbsentAsync(markup, expectedItem, displayTextSuffix: displayTextSuffix, inlineDescription: inlineDescription);
}