File: Classification\SemanticClassifierTests.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.
 
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Editor.Tagging;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Editor.UnitTests.Classification;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Remote.Testing;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Threading;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
using static Microsoft.CodeAnalysis.Editor.UnitTests.Classification.FormattedClassifications;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Classification;
 
[Trait(Traits.Feature, Traits.Features.Classification)]
public sealed partial class SemanticClassifierTests : AbstractCSharpClassifierTests
{
    protected override async Task<ImmutableArray<ClassifiedSpan>> GetClassificationSpansAsync(string code, ImmutableArray<TextSpan> spans, ParseOptions? options, TestHost testHost)
    {
        using var workspace = CreateWorkspace(code, options, testHost);
        var document = workspace.CurrentSolution.GetRequiredDocument(workspace.Documents.First().Id);
 
        return await GetSemanticClassificationsAsync(document, spans);
    }
 
    private new Task TestAsync(
        [StringSyntax("C#-Test")] string code,
        TestHost testHost,
        params FormattedClassification[] expected)
    {
        return base.TestAsync(code, testHost, expected);
    }
 
    [Theory, CombinatorialData]
    public async Task GenericClassDeclaration(TestHost testHost)
    {
        await TestInMethodAsync(
            className: "Class<T>",
            methodName: "M",
            @"new Class<int>();",
            testHost,
            Class("Class"));
    }
 
    [Theory, CombinatorialData]
    public async Task RefVar(TestHost testHost)
    {
        await TestInMethodAsync(
            @"int i = 0; ref var x = ref i;",
            testHost,
            Classifications(Keyword("var"), Local("i")));
    }
 
    [Theory, CombinatorialData]
    public async Task UsingAlias1(TestHost testHost)
    {
        await TestAsync(
@"using M = System.Math;",
            testHost,
            Class("M"),
            Namespace("System"),
            Class("Math"),
            Static("Math"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsTypeArgument(TestHost testHost)
    {
        await TestInMethodAsync(
            className: "Class<T>",
            methodName: "M",
            @"new Class<dynamic>();",
            testHost,
            Classifications(Class("Class"), Keyword("dynamic")));
    }
 
    [Theory, CombinatorialData]
    public async Task UsingTypeAliases(TestHost testHost)
    {
        var code = """
            using Alias = Test; 
            class Test { void M() { Test a = new Test(); Alias b = new Alias(); } }
            """;
 
        await TestAsync(code,
            code,
            testHost,
            Class("Alias"),
            Class("Test"),
            Class("Test"),
            Class("Test"),
            Class("Alias"),
            Class("Alias"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicTypeAlias(TestHost testHost)
    {
        await TestAsync(
            """
            using dynamic = System.EventArgs;
 
            class C
            {
                dynamic d = new dynamic();
            }
            """,
            testHost,
            Class("dynamic"),
            Namespace("System"),
            Class("EventArgs"),
            Class("dynamic"),
            Class("dynamic"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsDelegateName(TestHost testHost)
    {
        await TestAsync(
            """
            delegate void dynamic();
 
            class C
            {
                void M()
                {
                    dynamic d;
                }
            }
            """,
            testHost,
            Delegate("dynamic"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsInterfaceName(TestHost testHost)
    {
        await TestAsync(
            """
            interface dynamic
            {
            }
 
            class C
            {
                dynamic d;
            }
            """,
            testHost,
            Interface("dynamic"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsEnumName(TestHost testHost)
    {
        await TestAsync(
            """
            enum dynamic
            {
            }
 
            class C
            {
                dynamic d;
            }
            """,
            testHost,
            Enum("dynamic"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsClassName(TestHost testHost)
    {
        await TestAsync(
            """
            class dynamic
            {
            }
 
            class C
            {
                dynamic d;
            }
            """,
            testHost,
            Class("dynamic"));
    }
 
    [Theory, CombinatorialData]
    [WorkItem("https://github.com/dotnet/roslyn/issues/46985")]
    public async Task DynamicAsRecordName(TestHost testHost)
    {
        await TestAsync(
            """
            record dynamic
            {
            }
 
            class C
            {
                dynamic d;
            }
            """,
            testHost,
            RecordClass("dynamic"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsClassNameAndLocalVariableName(TestHost testHost)
    {
        await TestAsync(
            """
            class dynamic
            {
                dynamic()
                {
                    dynamic dynamic;
                }
            }
            """,
            testHost,
            Class("dynamic"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsStructName(TestHost testHost)
    {
        await TestAsync(
            """
            struct dynamic
            {
            }
 
            class C
            {
                dynamic d;
            }
            """,
            testHost,
            Struct("dynamic"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsGenericClassName(TestHost testHost)
    {
        await TestAsync(
            """
            class dynamic<T>
            {
            }
 
            class C
            {
                dynamic<int> d;
            }
            """,
            testHost,
            Class("dynamic"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsGenericClassNameButOtherArity(TestHost testHost)
    {
        await TestAsync(
            """
            class dynamic<T>
            {
            }
 
            class C
            {
                dynamic d;
            }
            """,
            testHost,
            Keyword("dynamic"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsUndefinedGenericType(TestHost testHost)
    {
        await TestAsync(
            """
            class dynamic
            {
            }
 
            class C
            {
                dynamic<int> d;
            }
            """,
            testHost,
            Class("dynamic"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsExternAlias(TestHost testHost)
    {
        await TestAsync(
            """
            extern alias dynamic;
 
            class C
            {
                dynamic::Goo a;
            }
            """,
            testHost,
            Namespace("dynamic"));
    }
 
    [Theory, CombinatorialData]
    public async Task GenericClassNameButOtherArity(TestHost testHost)
    {
        await TestAsync(
            """
            class A<T>
            {
            }
 
            class C
            {
                A d;
            }
            """, testHost,
            Class("A"));
    }
 
    [Theory, CombinatorialData]
    public async Task GenericTypeParameter(TestHost testHost)
    {
        await TestAsync(
            """
            class C<T>
            {
                void M()
                {
                    default(T) }
            }
            """,
            testHost,
            TypeParameter("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task GenericMethodTypeParameter(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                T M<T>(T t)
                {
                    return default(T);
                }
            }
            """,
            testHost,
            TypeParameter("T"),
            TypeParameter("T"),
            TypeParameter("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task GenericMethodTypeParameterInLocalVariableDeclaration(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                void M<T>()
                {
                    T t;
                }
            }
            """,
            testHost,
            TypeParameter("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task ParameterOfLambda1(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                C()
                {
                    Action a = (C p) => {
                    };
                }
            }
            """,
            testHost,
            Class("C"));
    }
 
    [Theory, CombinatorialData]
    public async Task ParameterOfAnonymousMethod(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                C()
                {
                    Action a = delegate (C p) {
                    };
                }
            }
            """,
            testHost,
            Class("C"));
    }
 
    [Theory, CombinatorialData]
    public async Task GenericTypeParameterAfterWhere(TestHost testHost)
    {
        await TestAsync(
            """
            class C<A, B> where A : B
            {
            }
            """,
            testHost,
            TypeParameter("A"),
            TypeParameter("B"));
    }
 
    [Theory, CombinatorialData]
    public async Task BaseClass(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
            }
 
            class C2 : C
            {
            }
            """,
            testHost,
            Class("C"));
    }
 
    [Theory, CombinatorialData]
    public async Task BaseInterfaceOnInterface(TestHost testHost)
    {
        await TestAsync(
            """
            interface T
            {
            }
 
            interface T2 : T
            {
            }
            """,
            testHost,
            Interface("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task BaseInterfaceOnClass(TestHost testHost)
    {
        await TestAsync(
            """
            interface T
            {
            }
 
            class T2 : T
            {
            }
            """,
            testHost,
            Interface("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task InterfaceColorColor(TestHost testHost)
    {
        await TestAsync(
            """
            interface T
            {
            }
 
            class T2 : T
            {
                T T;
            }
            """,
            testHost,
            Interface("T"),
            Interface("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task DelegateColorColor(TestHost testHost)
    {
        await TestAsync(
            """
            delegate void T();
 
            class T2
            {
                T T;
            }
            """,
            testHost,
            Delegate("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task DelegateReturnsItself(TestHost testHost)
    {
        await TestAsync(
            """
            delegate T T();
 
            class C
            {
                T T(T t);
            }
            """,
            testHost,
            Delegate("T"),
            Delegate("T"),
            Delegate("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task StructColorColor(TestHost testHost)
    {
        await TestAsync(
            """
            struct T
            {
                T T;
            }
            """,
            testHost,
            Struct("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task EnumColorColor(TestHost testHost)
    {
        await TestAsync(
            """
            enum T
            {
                T,
                T
            }
 
            class C
            {
                T T;
            }
            """,
            testHost,
            Enum("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsGenericTypeParameter(TestHost testHost)
    {
        await TestAsync(
            """
            class C<dynamic>
            {
                dynamic d;
            }
            """,
            testHost,
            TypeParameter("dynamic"));
    }
 
    [Theory, CombinatorialData]
    public async Task DynamicAsGenericFieldName(TestHost testHost)
    {
        await TestAsync(
            """
            class A<T>
            {
                T dynamic;
            }
            """,
            testHost,
            TypeParameter("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task PropertySameNameAsClass(TestHost testHost)
    {
        await TestAsync(
            """
            class N
            {
                N N { get; set; }
 
                void M()
                {
                    N n = N;
                    N = n;
                    N = N;
                }
            }
            """,
            testHost,
            Class("N"),
            Class("N"),
            Property("N"),
            Property("N"),
            Local("n"),
            Property("N"),
            Property("N"));
    }
 
    [Theory, CombinatorialData]
    public async Task AttributeWithoutAttributeSuffix(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            [Obsolete]
            class C
            {
            }
            """,
            testHost,
            Namespace("System"),
            Class("Obsolete"),
            Obsolete("C"));
    }
 
    [Theory, CombinatorialData]
    public async Task AttributeOnNonExistingMember(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            class A
            {
                [Obsolete]
            }
            """,
            testHost,
            Namespace("System"),
            Class("Obsolete"));
    }
 
    [Theory, CombinatorialData]
    public async Task AttributeWithoutAttributeSuffixOnAssembly(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            [assembly: My]
 
            class MyAttribute : Attribute
            {
            }
            """,
            testHost,
            Namespace("System"),
            Class("My"),
            Class("Attribute"));
    }
 
    [Theory, CombinatorialData]
    public async Task AttributeViaNestedClassOrDerivedClass(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            [Base.My]
            [Derived.My]
            class Base
            {
                public class MyAttribute : Attribute
                {
                }
            }
 
            class Derived : Base
            {
            }
            """,
            testHost,
            Namespace("System"),
            Class("Base"),
            Class("My"),
            Class("Derived"),
            Class("My"),
            Class("Attribute"),
            Class("Base"));
    }
 
    [Theory, CombinatorialData]
    public async Task NamedAndOptional(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                void B(C C = null)
                {
                }
 
                void M()
                {
                    B(C: null);
                }
            }
            """,
            testHost,
            Class("C"),
            Method("B"),
            Parameter("C"));
    }
 
    [Theory, CombinatorialData]
    public async Task PartiallyWrittenGenericName1(TestHost testHost)
    {
        await TestInMethodAsync(
            className: "Class<T>",
            methodName: "M",
            @"Class<int",
            testHost,
            Class("Class"));
    }
 
    [Theory, CombinatorialData]
    public async Task PartiallyWrittenGenericName2(TestHost testHost)
    {
        await TestInMethodAsync(
            className: "Class<T1, T2>",
            methodName: "M",
            @"Class<int, b",
            testHost,
            Class("Class"));
    }
 
    // The "Color Color" problem is the C# IDE folklore for when
    // a property name is the same as a type name
    // and the resulting ambiguities that the spec
    // resolves in favor of properties
    [Theory, CombinatorialData]
    public async Task ColorColor(TestHost testHost)
    {
        await TestAsync(
            """
            class Color
            {
                Color Color;
            }
            """,
            testHost,
            Class("Color"));
    }
 
    [Theory, CombinatorialData]
    public async Task ColorColor2(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                T T = new T();
 
                T()
                {
                    this.T = new T();
                }
            }
            """,
            testHost,
            Class("T"),
            Class("T"),
            Field("T"),
            Class("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task ColorColor3(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                T T = new T();
 
                void M();
 
                T()
                {
                    T.M();
                }
            }
            """,
            testHost,
            Class("T"),
            Class("T"),
            Field("T"),
            Method("M"));
    }
 
    /// <summary>
    /// Instance field should be preferred to type
    /// §7.5.4.1
    /// </summary>
    [Theory, CombinatorialData]
    public async Task ColorColor4(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                T T;
 
                void M()
                {
                    T.T = null;
                }
            }
            """,
            testHost,
            Class("T"),
            Field("T"),
            Field("T"));
    }
 
    /// <summary>
    /// Type should be preferred to a static field
    /// §7.5.4.1
    /// </summary>
    [Theory, CombinatorialData]
    public async Task ColorColor5(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                static T T;
 
                void M()
                {
                    T.T = null;
                }
            }
            """,
            testHost,
            Class("T"),
            Class("T"),
            Field("T"),
            Static("T"));
    }
 
    /// <summary>
    /// Needs to prefer the local
    /// </summary>
    [Theory, CombinatorialData]
    public async Task ColorColor6(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                int field;
 
                void M()
                {
                    T T = new T();
                    T.field = 0;
                }
            }
            """,
            testHost,
            Class("T"),
            Class("T"),
            Local("T"),
            Field("field"));
    }
 
    /// <summary>
    /// Needs to prefer the type
    /// </summary>
    [Theory, CombinatorialData]
    public async Task ColorColor7(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                static int field;
 
                void M()
                {
                    T T = new T();
                    T.field = 0;
                }
            }
            """,
            testHost,
            Class("T"),
            Class("T"),
            Class("T"),
            Field("field"),
            Static("field"));
    }
 
    [Theory, CombinatorialData]
    public async Task ColorColor8(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                void M(T T)
                {
                }
 
                void M2()
                {
                    T T = new T();
                    M(T);
                }
            }
            """,
            testHost,
            Class("T"),
            Class("T"),
            Class("T"),
            Method("M"),
            Local("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task ColorColor9(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                T M(T T)
                {
                    T = new T();
                    return T;
                }
            }
            """,
            testHost,
            Class("T"),
            Class("T"),
            Parameter("T"),
            Class("T"),
            Parameter("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task ColorColor10(TestHost testHost)
    {
        // note: 'var' now binds to the type of the local.
        await TestAsync(
            """
            class T
            {
                void M()
                {
                    var T = new object();
                    T temp = T as T;
                }
            }
            """,
            testHost,
            Keyword("var"),
            Class("T"),
            Local("T"),
            Class("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task ColorColor11(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                void M()
                {
                    var T = new object();
                    bool b = T is T;
                }
            }
            """,
            testHost,
            Keyword("var"),
            Local("T"),
            Class("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task ColorColor12(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                void M()
                {
                    T T = new T();
                    var t = typeof(T);
                }
            }
            """,
            testHost,
            Class("T"),
            Class("T"),
            Keyword("var"),
            Class("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task ColorColor13(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                void M()
                {
                    T T = new T();
                    T t = default(T);
                }
            }
            """,
            testHost,
            Class("T"),
            Class("T"),
            Class("T"),
            Class("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task ColorColor14(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                void M()
                {
                    object T = new T();
                    T t = (T)T;
                }
            }
            """,
            testHost,
            Class("T"),
            Class("T"),
            Class("T"),
            Local("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task NamespaceNameSameAsTypeName1(TestHost testHost)
    {
        await TestAsync(
            """
            namespace T
            {
                class T
                {
                    void M()
                    {
                        T.T T = new T.T();
                    }
                }
            }
            """,
            testHost,
            Namespace("T"),
            Class("T"),
            Class("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task NamespaceNameSameAsTypeNameWithGlobal(TestHost testHost)
    {
        await TestAsync(
            """
            namespace T
            {
                class T
                {
                    void M()
                    {
                        global::T.T T = new global::T.T();
                    }
                }
            }
            """,
            testHost,
            Namespace("T"),
            Namespace("T"),
            Class("T"),
            Namespace("T"),
            Class("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task AmbiguityTypeAsGenericMethodArgumentVsLocal(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                void M<T>()
                {
                    T T;
                    M<T>();
                }
            }
            """,
            testHost,
            TypeParameter("T"),
            Method("M"),
            TypeParameter("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task AmbiguityTypeAsGenericArgumentVsLocal(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                class G<T>
                {
                }
 
                void M()
                {
                    T T;
                    G<T> g = new G<T>();
                }
            }
            """,
            testHost,
            Class("T"),
            Class("G"),
            Class("T"),
            Class("G"),
            Class("T"));
    }
 
    [Theory, CombinatorialData]
    public async Task AmbiguityTypeAsGenericArgumentVsField(TestHost testHost)
    {
        await TestAsync(
            """
            class T
            {
                class H<T>
                {
                    public static int f;
                }
 
                void M()
                {
                    T T;
                    int i = H<T>.f;
                }
            }
            """,
            testHost,
            Class("T"),
            Class("H"),
            Class("T"),
            Field("f"),
            Static("f"));
    }
 
    /// <summary>
    /// §7.5.4.2
    /// </summary>
    [Theory, CombinatorialData]
    public async Task GrammarAmbiguity_7_5_4_2(TestHost testHost)
    {
        await TestAsync(
            """
            class M
            {
                void m()
                {
                    int A = 2;
                    int B = 3;
                    F(G<A, B>(7));
                }
 
                void F(bool b)
                {
                }
 
                bool G<t, f>(int a)
                {
                    return true;
                }
 
                class A
                {
                }
 
                class B
                {
                }
            }
            """,
            testHost,
            Method("F"),
            Method("G"),
            Class("A"),
            Class("B"));
    }
 
    [Theory, CombinatorialData]
    public async Task AnonymousTypePropertyName(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            class C
            {
                void M()
                {
                    var x = new { String = " }; } }
            """,
            testHost,
            Namespace("System"),
            Keyword("var"),
            Property("String"));
    }
 
    [Theory, CombinatorialData]
    public async Task YieldAsATypeName(TestHost testHost)
    {
        await TestAsync(
            """
            using System.Collections.Generic;
 
            class yield
            {
                IEnumerable<yield> M()
                {
                    yield yield = new yield();
                    yield return yield;
                }
            }
            """,
            testHost,
            Namespace("System"),
            Namespace("Collections"),
            Namespace("Generic"),
            Interface("IEnumerable"),
            Class("yield"),
            Class("yield"),
            Class("yield"),
            Local("yield"));
    }
 
    [Theory, CombinatorialData]
    public async Task TypeNameDottedNames(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                class Nested
                {
                }
 
                C.Nested f;
            }
            """,
            testHost,
            Class("C"),
            Class("Nested"));
    }
 
    [Theory, CombinatorialData]
    public async Task BindingTypeNameFromBCLViaGlobalAlias(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            class C
            {
                global::System.String f;
            }
            """,
            testHost,
            Namespace("System"),
            Namespace("System"),
            Class("String"));
    }
 
    [Theory, CombinatorialData]
    public async Task BindingTypeNames(TestHost testHost)
    {
        var code = """
            using System;
            using Str = System.String;
            class C
            {
                class Nested { }
                Str UsingAlias;
                Nested NestedClass;
                String BCL;
                C ClassDeclaration;
                C.Nested FCNested;
                global::C FCN;
                global::System.String FCNBCL;
                global::Str GlobalUsingAlias;
            }
            """;
        await TestAsync(code,
            code,
            testHost,
            Options.Regular,
            Namespace("System"),
            Class("Str"),
            Namespace("System"),
            Class("String"),
            Class("Str"),
            Class("Nested"),
            Class("String"),
            Class("C"),
            Class("C"),
            Class("Nested"),
            Class("C"),
            Namespace("System"),
            Class("String"));
    }
 
    [Theory, CombinatorialData]
    public async Task Constructors(TestHost testHost)
    {
        await TestAsync(
            """
            struct S
            {
                public int i;
 
                public S(int i)
                {
                    this.i = i;
                }
            }
 
            class C
            {
                public C()
                {
                    var s = new S(1);
                    var c = new C();
                }
            }
            """,
            testHost,
            Field("i"),
            Parameter("i"),
            Keyword("var"),
            Struct("S"),
            Keyword("var"),
            Class("C"));
    }
 
    [Theory, CombinatorialData]
    public async Task TypesOfClassMembers(TestHost testHost)
    {
        await TestAsync(
            """
            class Type
            {
                public Type()
                {
                }
 
                static Type()
                {
                }
 
                ~Type()
                {
                }
 
                Type Property { get; set; }
 
                Type Method()
                {
                }
 
                event Type Event;
 
                Type this[Type index] { get; set; }
 
                Type field;
                const Type constant = null;
 
                static operator Type(Type other)
                {
                }
 
                static operator +(Type other)
                {
                }
 
                static operator int(Type other)
                {
                }
 
                static operator Type(int other)
                {
                }
            }
            """,
            testHost,
            Class("Type"),
            Class("Type"),
            Class("Type"),
            Class("Type"),
            Class("Type"),
            Class("Type"),
            Class("Type"),
            Class("Type"),
            Class("Type"),
            Class("Type"),
            Class("Type"),
            Class("Type"));
    }
 
    /// <summary>
    /// NAQ = Namespace Alias Qualifier (?)
    /// </summary>
    [Theory, CombinatorialData]
    public async Task NAQTypeNameCtor(TestHost testHost)
    {
        await TestInMethodAsync(
@"System.IO.BufferedStream b = new global::System.IO.BufferedStream();",
            testHost,
            Namespace("System"),
            Namespace("IO"),
            Class("BufferedStream"),
            Namespace("System"),
            Namespace("IO"),
            Class("BufferedStream"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQEnum(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                void M()
                {
                    global::System.IO.DriveType d;
                }
            }
            """,
            testHost,
            Namespace("System"),
            Namespace("IO"),
            Enum("DriveType"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQDelegate(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                void M()
                {
                    global::System.AssemblyLoadEventHandler d;
                }
            }
            """,
            testHost,
            Namespace("System"),
            Delegate("AssemblyLoadEventHandler"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQTypeNameMethodCall(TestHost testHost)
    {
        await TestInMethodAsync(@"global::System.String.Clone("");",
            testHost,
            Namespace("System"),
            Class("String"),
            Method("Clone"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQEventSubscription(TestHost testHost)
    {
        await TestInMethodAsync(
            """
            global::System.AppDomain.CurrentDomain.AssemblyLoad += 
                        delegate (object sender, System.AssemblyLoadEventArgs args) {};
            """,
            testHost,
            Namespace("System"),
            Class("AppDomain"),
            Property("CurrentDomain"),
            Static("CurrentDomain"),
            Event("AssemblyLoad"),
            Namespace("System"),
            Class("AssemblyLoadEventArgs"));
    }
 
    [Theory, CombinatorialData]
    public async Task AnonymousDelegateParameterType(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                void M()
                {
                    System.Action<System.EventArgs> a = delegate (System.EventArgs e) {
                    };
                }
            }
            """,
            testHost,
            Namespace("System"),
            Delegate("Action"),
            Namespace("System"),
            Class("EventArgs"),
            Namespace("System"),
            Class("EventArgs"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQCtor(TestHost testHost)
    {
        await TestInMethodAsync(
@"global::System.Collections.DictionaryEntry de = new global::System.Collections.DictionaryEntry();",
            testHost,
            Namespace("System"),
            Namespace("Collections"),
            Struct("DictionaryEntry"),
            Namespace("System"),
            Namespace("Collections"),
            Struct("DictionaryEntry"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQSameFileClass(TestHost testHost)
    {
        var code = @"class C { static void M() { global::C.M(); } }";
 
        await TestAsync(code,
            testHost,
            ParseOptions(Options.Regular),
            Class("C"),
            Method("M"),
            Static("M"));
    }
 
    [Theory, CombinatorialData]
    public async Task InteractiveNAQSameFileClass(TestHost testHost)
    {
        var code = @"class C { static void M() { global::Script.C.M(); } }";
 
        await TestAsync(code,
            testHost,
            ParseOptions(Options.Script),
            Class("Script"),
            Class("C"),
            Method("M"),
            Static("M"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQSameFileClassWithNamespace(TestHost testHost)
    {
        await TestAsync(
            """
            using @global = N;
 
            namespace N
            {
                class C
                {
                    static void M()
                    {
                        global::N.C.M();
                    }
                }
            }
            """,
            testHost,
            Namespace("@global"),
            Namespace("N"),
            Namespace("N"),
            Namespace("N"),
            Class("C"),
            Method("M"),
            Static("M"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQSameFileClassWithNamespaceAndEscapedKeyword(TestHost testHost)
    {
        await TestAsync(
            """
            using @global = N;
 
            namespace N
            {
                class C
                {
                    static void M()
                    {
                        @global.C.M();
                    }
                }
            }
            """,
            testHost,
            Namespace("@global"),
            Namespace("N"),
            Namespace("N"),
            Namespace("@global"),
            Class("C"),
            Method("M"),
            Static("M"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQGlobalWarning(TestHost testHost)
    {
        await TestAsync(
            """
            using global = N;
 
            namespace N
            {
                class C
                {
                    static void M()
                    {
                        global.C.M();
                    }
                }
            }
            """,
            testHost,
            Namespace("global"),
            Namespace("N"),
            Namespace("N"),
            Namespace("global"),
            Class("C"),
            Method("M"),
            Static("M"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQUserDefinedNAQNamespace(TestHost testHost)
    {
        await TestAsync(
            """
            using goo = N;
 
            namespace N
            {
                class C
                {
                    static void M()
                    {
                        goo.C.M();
                    }
                }
            }
            """,
            testHost,
            Namespace("goo"),
            Namespace("N"),
            Namespace("N"),
            Namespace("goo"),
            Class("C"),
            Method("M"),
            Static("M"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQUserDefinedNAQNamespaceDoubleColon(TestHost testHost)
    {
        await TestAsync(
            """
            using goo = N;
 
            namespace N
            {
                class C
                {
                    static void M()
                    {
                        goo::C.M();
                    }
                }
            }
            """,
            testHost,
            Namespace("goo"),
            Namespace("N"),
            Namespace("N"),
            Namespace("goo"),
            Class("C"),
            Method("M"),
            Static("M"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQUserDefinedNamespace1(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                void M()
                {
                    A.B.D d;
                }
            }
 
            namespace A
            {
                namespace B
                {
                    class D
                    {
                    }
                }
            }
            """,
            testHost,
            Namespace("A"),
            Namespace("B"),
            Class("D"),
            Namespace("A"),
            Namespace("B"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQUserDefinedNamespaceWithGlobal(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                void M()
                {
                    global::A.B.D d;
                }
            }
 
            namespace A
            {
                namespace B
                {
                    class D
                    {
                    }
                }
            }
            """,
            testHost,
            Namespace("A"),
            Namespace("B"),
            Class("D"),
            Namespace("A"),
            Namespace("B"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQUserDefinedNAQForClass(TestHost testHost)
    {
        await TestAsync(
            """
            using IO = global::System.IO;
 
            class C
            {
                void M()
                {
                    IO::BinaryReader b;
                }
            }
            """,
            testHost,
            Namespace("IO"),
            Namespace("System"),
            Namespace("IO"),
            Namespace("IO"),
            Class("BinaryReader"));
    }
 
    [Theory, CombinatorialData]
    public async Task NAQUserDefinedTypes(TestHost testHost)
    {
        await TestAsync(
            """
            using rabbit = MyNameSpace;
 
            class C
            {
                void M()
                {
                    rabbit::MyClass2.method();
                    new rabbit::MyClass2().myEvent += null;
                    rabbit::MyEnum Enum;
                    rabbit::MyStruct strUct;
                    object o2 = rabbit::MyClass2.MyProp;
                    object o3 = rabbit::MyClass2.myField;
                    rabbit::MyClass2.MyDelegate del = null;
                }
            }
 
            namespace MyNameSpace
            {
                namespace OtherNamespace
                {
                    class A
                    {
                    }
                }
 
                public class MyClass2
                {
                    public static int myField;
 
                    public delegate void MyDelegate();
 
                    public event MyDelegate myEvent;
 
                    public static void method()
                    {
                    }
 
                    public static int MyProp
                    {
                        get
                        {
                            return 0;
                        }
                    }
                }
 
                struct MyStruct
                {
                }
 
                enum MyEnum
                {
                }
            }
            """,
            testHost,
            Namespace("rabbit"),
            Namespace("MyNameSpace"),
            Namespace("rabbit"),
            Class("MyClass2"),
            Method("method"),
            Static("method"),
            Namespace("rabbit"),
            Class("MyClass2"),
            Event("myEvent"),
            Namespace("rabbit"),
            Enum("MyEnum"),
            Namespace("rabbit"),
            Struct("MyStruct"),
            Namespace("rabbit"),
            Class("MyClass2"),
            Property("MyProp"),
            Static("MyProp"),
            Namespace("rabbit"),
            Class("MyClass2"),
            Field("myField"),
            Static("myField"),
            Namespace("rabbit"),
            Class("MyClass2"),
            Delegate("MyDelegate"),
            Namespace("MyNameSpace"),
            Namespace("OtherNamespace"),
            Delegate("MyDelegate"));
    }
 
    [Theory, CombinatorialData]
    public async Task PreferPropertyOverNestedClass(TestHost testHost)
    {
        await TestAsync(
            """
            class Outer
            {
                class A
                {
                    public int B;
                }
 
                class B
                {
                    void M()
                    {
                        A a = new A();
                        a.B = 10;
                    }
                }
            }
            """,
            testHost,
            Class("A"),
            Class("A"),
            Local("a"),
            Field("B"));
    }
 
    [Theory, CombinatorialData]
    public async Task TypeNameInsideNestedClass(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            class Outer
            {
                class C
                {
                    void M()
                    {
                        Console.WriteLine();
                        Console.WriteLine();
                    }
                }
            }
            """,
            testHost,
            Namespace("System"),
            Class("Console"),
            Static("Console"),
            Method("WriteLine"),
            Static("WriteLine"),
            Class("Console"),
            Static("Console"),
            Method("WriteLine"),
            Static("WriteLine"));
    }
 
    [Theory, CombinatorialData]
    public async Task StructEnumTypeNames(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            class C
            {
                enum MyEnum
                {
                }
 
                struct MyStruct
                {
                }
 
                static void Main()
                {
                    ConsoleColor c;
                    Int32 i;
                }
            }
            """,
            testHost,
            Namespace("System"),
            Enum("ConsoleColor"),
            Struct("Int32"));
    }
 
    [Theory, CombinatorialData]
    public async Task PreferFieldOverClassWithSameName(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                public int C;
 
                void M()
                {
                    C = 0;
                }
            }
            """, testHost,
            Field("C"));
    }
 
    [Theory, CombinatorialData]
    public async Task AttributeBinding(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            [Serializable]            // Binds to System.SerializableAttribute; colorized
            class Serializable
            {
            }
 
            [SerializableAttribute]   // Binds to System.SerializableAttribute; colorized
            class Serializable
            {
            }
 
            [NonSerialized]           // Binds to global::NonSerializedAttribute; colorized
            class NonSerializedAttribute
            {
            }
 
            [NonSerializedAttribute]  // Binds to global::NonSerializedAttribute; colorized
            class NonSerializedAttribute
            {
            }
 
            [Obsolete]                // Binds to global::Obsolete; colorized
            class Obsolete : Attribute
            {
            }
 
            [ObsoleteAttribute]       // Binds to global::Obsolete; colorized
            class ObsoleteAttribute : Attribute
            {
            }
            """,
            testHost,
            Namespace("System"),
            Class("Serializable"),
            Class("SerializableAttribute"),
            Class("NonSerialized"),
            Class("NonSerializedAttribute"),
            Class("Obsolete"),
            Class("Attribute"),
            Class("ObsoleteAttribute"),
            Class("Attribute"));
    }
 
    [Theory, CombinatorialData]
    public async Task ShouldNotClassifyNamespacesAsTypes(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            namespace Roslyn.Compilers.Internal
            {
            }
            """,
            testHost,
            Namespace("System"),
            Namespace("Roslyn"),
            Namespace("Compilers"),
            Namespace("Internal"));
    }
 
    [Theory, CombinatorialData]
    public async Task NestedTypeCantHaveSameNameAsParentType(TestHost testHost)
    {
        await TestAsync(
            """
            class Program
            {
                class Program
                {
                }
 
                static void Main(Program p)
                {
                }
 
                Program.Program p2;
            }
            """,
            testHost,
            Class("Program"),
            Class("Program"));
    }
 
    [Theory, CombinatorialData]
    public async Task NestedTypeCantHaveSameNameAsParentTypeWithGlobalNamespaceAlias(TestHost testHost)
    {
        var code = """
            class Program
            {
                class Program { }
                static void Main(Program p) { }
                global::Program.Program p;
            }
            """;
 
        await TestAsync(code,
            testHost,
            ParseOptions(Options.Regular),
            Class("Program"),
            Class("Program"),
            Class("Program"));
    }
 
    [Theory, CombinatorialData]
    public async Task InteractiveNestedTypeCantHaveSameNameAsParentTypeWithGlobalNamespaceAlias(TestHost testHost)
    {
        var code = """
            class Program
            {
                class Program { }
                static void Main(Program p) { }
                global::Script.Program.Program p;
            }
            """;
 
        await TestAsync(code,
            testHost,
            ParseOptions(Options.Script),
            Class("Program"),
            Class("Script"),
            Class("Program"),
            Class("Program"));
    }
 
    [Theory, CombinatorialData]
    public async Task EnumFieldWithSameNameShouldBePreferredToType(TestHost testHost)
    {
        await TestAsync(
            """
            enum E
            {
                E,
                F = E
            }
            """, testHost,
            EnumMember("E"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541150")]
    [CombinatorialData]
    public async Task TestGenericVarClassification(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            static class Program
            {
                static void Main()
                {
                    var x = 1;
                }
            }
 
            class var<T>
            {
            }
            """,
            testHost,
            Namespace("System"),
            Keyword("var"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541154")]
    [CombinatorialData]
    public async Task TestInaccessibleVarClassification(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            class A
            {
                private class var
                {
                }
            }
 
            class B : A
            {
                static void Main()
                {
                    var x = 1;
                }
            }
            """,
            testHost,
            Namespace("System"),
            Class("A"),
            Keyword("var"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/541154")]
    [CombinatorialData]
    public async Task TestVarNamedTypeClassification(TestHost testHost)
    {
        await TestAsync(
            """
            class var
            {
                static void Main()
                {
                    var x;
                }
            }
            """,
            testHost,
            Keyword("var"));
    }
 
    [Theory, WorkItem(9513, "DevDiv_Projects/Roslyn")]
    [CombinatorialData]
    public async Task RegressionFor9513(TestHost testHost)
    {
        await TestAsync(
            """
            enum E
            {
                A,
                B
            }
 
            class C
            {
                void M()
                {
                    switch (new E())
                    {
                        case E.A:
                            goto case E.B;
                        case E.B:
                            goto default;
                        default:
                            goto case E.A;
                    }
                }
            }
            """,
            testHost,
            Enum("E"),
            Enum("E"),
            EnumMember("A"),
            Enum("E"),
            EnumMember("B"),
            Enum("E"),
            EnumMember("B"),
            Enum("E"),
            EnumMember("A"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542368")]
    [CombinatorialData]
    public async Task RegressionFor9572(TestHost testHost)
    {
        await TestAsync(
            """
            class A<T, S> where T : A<T, S>.I, A<T, T>.I
            {
                public interface I
                {
                }
            }
            """,
            testHost,
            TypeParameter("T"),
            Class("A"),
            TypeParameter("T"),
            TypeParameter("S"),
            Interface("I"),
            Class("A"),
            TypeParameter("T"),
            TypeParameter("T"),
            Interface("I"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542368")]
    [CombinatorialData]
    public async Task RegressionFor9831(TestHost testHost)
    {
        await TestAsync(@"F : A",
            """
            public class B<T>
            {
                public class A
                {
                }
            }
 
            public class X : B<X>
            {
                public class F : A
                {
                }
            }
            """,
            testHost,
            Class("A"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542432")]
    [CombinatorialData]
    public async Task TestVar(TestHost testHost)
    {
        await TestAsync(
            """
            class Program
            {
                class var<T>
                {
                }
 
                static var<int> GetVarT()
                {
                    return null;
                }
 
                static void Main()
                {
                    var x = GetVarT();
                    var y = new var<int>();
                }
            }
            """,
            testHost,
            Class("var"),
            Keyword("var"),
            Method("GetVarT"),
            Static("GetVarT"),
            Keyword("var"),
            Class("var"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543123")]
    [CombinatorialData]
    public async Task TestVar2(TestHost testHost)
    {
        await TestAsync(
            """
            class Program
            {
                void Main(string[] args)
                {
                    foreach (var v in args)
                    {
                    }
                }
            }
            """,
            testHost,
            Keyword("var"),
            Parameter("args"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542778")]
    [CombinatorialData]
    public async Task TestDuplicateTypeParamWithConstraint(TestHost testHost)
    {
        await TestAsync(@"where U : IEnumerable<S>",
            """
            using System.Collections.Generic;
 
            class C<T>
            {
                public void Goo<U, U>(U arg)
                    where S : T
                    where U : IEnumerable<S>
                {
                }
            }
            """,
            testHost,
            TypeParameter("U"),
            Interface("IEnumerable"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542685")]
    [CombinatorialData]
    public async Task OptimisticallyColorFromInDeclaration(TestHost testHost)
    {
        await TestInExpressionAsync("from ",
            testHost,
            Keyword("from"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542685")]
    [CombinatorialData]
    public async Task OptimisticallyColorFromInAssignment(TestHost testHost)
    {
        await TestInMethodAsync(
            """
            var q = 3;
 
            q = from
            """,
            testHost,
            Keyword("var"),
            Local("q"),
            Keyword("from"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542685")]
    [CombinatorialData]
    public async Task DoNotColorThingsOtherThanFromInDeclaration(TestHost testHost)
        => await TestInExpressionAsync("fro ", testHost);
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542685")]
    [CombinatorialData]
    public async Task DoNotColorThingsOtherThanFromInAssignment(TestHost testHost)
    {
        await TestInMethodAsync(
            """
            var q = 3;
 
            q = fro
            """,
            testHost,
            Keyword("var"),
            Local("q"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542685")]
    [CombinatorialData]
    public async Task DoNotColorFromWhenBoundInDeclaration(TestHost testHost)
    {
        await TestInMethodAsync(
            """
            var from = 3;
            var q = from
            """,
            testHost,
            Keyword("var"),
            Keyword("var"),
            Local("from"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542685")]
    [CombinatorialData]
    public async Task DoNotColorFromWhenBoundInAssignment(TestHost testHost)
    {
        await TestInMethodAsync(
            """
            var q = 3;
            var from = 3;
 
            q = from
            """,
            testHost,
            Keyword("var"),
            Keyword("var"),
            Local("q"),
            Local("from"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543404")]
    [CombinatorialData]
    public async Task NewOfClassWithOnlyPrivateConstructor(TestHost testHost)
    {
        await TestAsync(
            """
            class X
            {
                private X()
                {
                }
            }
 
            class Program
            {
                static void Main(string[] args)
                {
                    new X();
                }
            }
            """,
            testHost,
            Class("X"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544179")]
    [CombinatorialData]
    public async Task TestNullableVersusConditionalAmbiguity1(TestHost testHost)
    {
        await TestAsync(
            """
            class Program
            {
                static void Main(string[] args)
                {
                    C1 ?
                }
            }
 
            public class C1
            {
            }
            """,
            testHost,
            Class("C1"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544179")]
    [CombinatorialData]
    public async Task TestPointerVersusMultiplyAmbiguity1(TestHost testHost)
    {
        await TestAsync(
            """
            class Program
            {
                static void Main(string[] args)
                {
                    C1 *
                }
            }
 
            public class C1
            {
            }
            """,
            testHost,
            Class("C1"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544302")]
    [CombinatorialData]
    public async Task EnumTypeAssignedToNamedPropertyOfSameNameInAttributeCtor(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
            using System.Runtime.InteropServices;
 
            class C
            {
                [DllImport("abc", CallingConvention = CallingConvention)]
                static extern void M();
            }
            """,
            testHost,
            Namespace("System"),
            Namespace("System"),
            Namespace("Runtime"),
            Namespace("InteropServices"),
            Class("DllImport"),
            Field("CallingConvention"),
            Enum("CallingConvention"));
    }
 
    [Theory, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531119")]
    [CombinatorialData]
    public async Task OnlyClassifyGenericNameOnce(TestHost testHost)
    {
        await TestAsync(
            """
            enum Type
            {
            }
 
            struct Type<T>
            {
                Type<int> f;
            }
            """,
            testHost,
            Struct("Type"));
    }
 
    [Theory, CombinatorialData]
    public async Task NameOf1(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                void goo()
                {
                    var x = nameof
                }
            }
            """,
            testHost,
            Keyword("var"),
            Keyword("nameof"));
    }
 
    [Theory, CombinatorialData]
    public async Task NameOf2(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                void goo()
                {
                    var x = nameof(C);
                }
            }
            """,
            testHost,
            Keyword("var"),
            Keyword("nameof"),
            Class("C"));
    }
 
    [Theory, CombinatorialData]
    public async Task NameOfLocalMethod(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                void goo()
                {
                    var x = nameof(M);
 
                    void M()
                    {
                    }
 
                    void M(int a)
                    {
                    }
 
                    void M(string s)
                    {
                    }
                }
            }
            """,
            testHost,
            Keyword("var"),
            Keyword("nameof"),
            Method("M"));
    }
 
    [Theory, CombinatorialData]
    public async Task MethodCalledNameOfInScope(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                void nameof(int i)
                {
                }
 
                void goo()
                {
                    int y = 3;
                    var x = nameof();
                }
            }
            """,
            testHost,
            Keyword("var"),
            Method("nameof"));
    }
 
    [Theory, CombinatorialData]
    public async Task Tuples(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                (int a, int b) x;
            }
            """,
            testHost,
            ParseOptions(TestOptions.Regular, Options.Script));
    }
 
    [Theory, CombinatorialData]
    [WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/261049")]
    public async Task DevDiv261049RegressionTest(TestHost testHost)
    {
        var source = """
            var (a,b) =  Get(out int x, out int y);
            Console.WriteLine($"({a.first}, {a.second})");
            """;
 
        await TestInMethodAsync(
            source,
            testHost,
            Keyword("var"), Local("a"), Local("a"));
    }
 
    [Theory, CombinatorialData]
    [WorkItem("https://github.com/dotnet/roslyn/issues/633")]
    public async Task InXmlDocCref_WhenTypeOnlyIsSpecified_ItIsClassified(TestHost testHost)
    {
        await TestAsync(
            """
            /// <summary>
            /// <see cref="MyClass"/>
            /// </summary>
            class MyClass
            {
                public MyClass(int x)
                {
                }
            }
            """,
            testHost,
            Class("MyClass"));
    }
 
    [Theory, CombinatorialData]
    [WorkItem("https://github.com/dotnet/roslyn/issues/633")]
    public async Task InXmlDocCref_WhenConstructorOnlyIsSpecified_NothingIsClassified(TestHost testHost)
    {
        await TestAsync(
            """
            /// <summary>
            /// <see cref="MyClass(int)"/>
            /// </summary>
            class MyClass
            {
                public MyClass(int x)
                {
                }
            }
            """, testHost,
            Class("MyClass"));
    }
 
    [Theory, CombinatorialData]
    [WorkItem("https://github.com/dotnet/roslyn/issues/633")]
    public async Task InXmlDocCref_WhenTypeAndConstructorSpecified_OnlyTypeIsClassified(TestHost testHost)
    {
        await TestAsync(
            """
            /// <summary>
            /// <see cref="MyClass.MyClass(int)"/>
            /// </summary>
            class MyClass
            {
                public MyClass(int x)
                {
                }
            }
            """,
            testHost,
            Class("MyClass"),
            Class("MyClass"));
    }
 
    [Theory, CombinatorialData]
    [WorkItem("https://github.com/dotnet/roslyn/issues/13174")]
    public async Task TestMemberBindingThatLooksGeneric(TestHost testHost)
    {
        await TestAsync(
            """
            using System.Diagnostics;
            using System.Threading.Tasks;
 
            namespace ConsoleApplication1
            {
                class Program
                {
                    static void Main(string[] args)
                    {
                        Debug.Assert(args?.Length < 2);
                    }
                }
            }
            """,
            testHost,
            Namespace("System"),
            Namespace("Diagnostics"),
            Namespace("System"),
            Namespace("Threading"),
            Namespace("Tasks"),
            Namespace("ConsoleApplication1"),
            Class("Debug"),
            Static("Debug"),
            Method("Assert"),
            Static("Assert"),
            Parameter("args"),
            Property("Length"));
    }
 
    [Theory, CombinatorialData]
    [WorkItem("https://github.com/dotnet/roslyn/issues/23940")]
    public async Task TestAliasQualifiedClass(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
            using Col = System.Collections.Generic;
 
            namespace AliasTest
            {
                class Program
                {
                    static void Main(string[] args)
                    {
                        var list1 = new Col::List
                    }
                }
            }
            """,
            testHost,
            Namespace("System"),
            Namespace("Col"),
            Namespace("System"),
            Namespace("Collections"),
            Namespace("Generic"),
            Namespace("AliasTest"),
            Keyword("var"),
            Namespace("Col"),
            Class("List"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_InsideMethod(TestHost testHost)
    {
        // Asserts no Keyword("unmanaged") because it is an identifier.
        await TestInMethodAsync("""
            var unmanaged = 0;
            unmanaged++;
            """,
            testHost,
            Keyword("var"),
            Local("unmanaged"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_Type_Keyword(TestHost testHost)
    {
        await TestAsync(
            "class X<T> where T : unmanaged { }",
            testHost,
            TypeParameter("T"),
            Keyword("unmanaged"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_Type_ExistingInterface(TestHost testHost)
    {
        await TestAsync("""
            interface unmanaged {}
            class X<T> where T : unmanaged { }
            """,
            testHost,
            TypeParameter("T"),
            Keyword("unmanaged"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_Type_ExistingInterfaceButOutOfScope(TestHost testHost)
    {
        await TestAsync("""
            namespace OtherScope
            {
                interface unmanaged {}
            }
            class X<T> where T : unmanaged { }
            """,
            testHost,
            Namespace("OtherScope"),
            TypeParameter("T"),
            Keyword("unmanaged"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_Method_Keyword(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void M<T>() where T : unmanaged { }
            }
            """,
            testHost,
            TypeParameter("T"),
            Keyword("unmanaged"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_Method_ExistingInterface(TestHost testHost)
    {
        await TestAsync("""
            interface unmanaged {}
            class X
            {
                void M<T>() where T : unmanaged { }
            }
            """,
            testHost,
            TypeParameter("T"),
            Keyword("unmanaged"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_Method_ExistingInterfaceButOutOfScope(TestHost testHost)
    {
        await TestAsync("""
            namespace OtherScope
            {
                interface unmanaged {}
            }
            class X
            {
                void M<T>() where T : unmanaged { }
            }
            """,
            testHost,
            Namespace("OtherScope"),
            TypeParameter("T"),
            Keyword("unmanaged"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_Delegate_Keyword(TestHost testHost)
    {
        await TestAsync(
            "delegate void D<T>() where T : unmanaged;",
            testHost,
            TypeParameter("T"),
            Keyword("unmanaged"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_Delegate_ExistingInterface(TestHost testHost)
    {
        await TestAsync("""
            interface unmanaged {}
            delegate void D<T>() where T : unmanaged;
            """,
            testHost,
            TypeParameter("T"),
            Keyword("unmanaged"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_Delegate_ExistingInterfaceButOutOfScope(TestHost testHost)
    {
        await TestAsync("""
            namespace OtherScope
            {
                interface unmanaged {}
            }
            delegate void D<T>() where T : unmanaged;
            """,
            testHost,
            Namespace("OtherScope"),
            TypeParameter("T"),
            Keyword("unmanaged"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_LocalFunction_Keyword(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    void M<T>() where T : unmanaged { }
                }
            }
            """,
            testHost,
            TypeParameter("T"),
            Keyword("unmanaged"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_LocalFunction_ExistingInterface(TestHost testHost)
    {
        await TestAsync("""
            interface unmanaged {}
            class X
            {
                void N()
                {
                    void M<T>() where T : unmanaged { }
                }
            }
            """,
            testHost,
            TypeParameter("T"),
            Keyword("unmanaged"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestUnmanagedConstraint_LocalFunction_ExistingInterfaceButOutOfScope(TestHost testHost)
    {
        await TestAsync("""
            namespace OtherScope
            {
                interface unmanaged {}
            }
            class X
            {
                void N()
                {
                    void M<T>() where T : unmanaged { }
                }
            }
            """,
            testHost,
            Namespace("OtherScope"),
            TypeParameter("T"),
            Keyword("unmanaged"));
    }
 
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/29451")]
    [CombinatorialData]
    public async Task TestDirectiveStringLiteral(TestHost testHost)
        => await TestInMethodAsync("""
            #line 1 "a\b"
            """, testHost);
 
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/30378")]
    [CombinatorialData]
    public async Task TestFormatSpecifierInInterpolation(TestHost testHost)
    {
        await TestInMethodAsync(@"var goo = $""goo{{1:0000}}bar"";",
            testHost,
            Keyword("var"),
            Escape(@"{{"),
            Escape(@"}}"));
    }
 
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/29492")]
    [CombinatorialData]
    public async Task TestOverloadedOperator_BinaryExpression(TestHost testHost)
    {
        await TestAsync("""
            class C
            {
                void M()
                {
                    var a = 1 + 1;
                    var b = new True() + new True();
                }
            }
            class True
            {
                public static True operator +(True a, True b)
                {
                     return new True();
                }
            }
            """,
            testHost,
            Keyword("var"),
            Keyword("var"),
            Class("True"),
            OverloadedOperators.Plus,
            Class("True"),
            Class("True"),
            Class("True"),
            Class("True"),
            Class("True"));
    }
 
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/29492")]
    [CombinatorialData]
    public async Task TestOverloadedOperator_PrefixUnaryExpression(TestHost testHost)
    {
        await TestAsync("""
            class C
            {
                void M()
                {
                    var a = !false;
                    var b = !new True();
                }
            }
            class True
            {
                public static bool operator !(True a)
                {
                     return false;
                }
            }
            """,
            testHost,
            Keyword("var"),
            Keyword("var"),
            OverloadedOperators.Exclamation,
            Class("True"),
            Class("True"));
    }
 
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/29492")]
    [CombinatorialData]
    public async Task TestOverloadedOperator_PostfixUnaryExpression(TestHost testHost)
    {
        await TestAsync("""
            class C
            {
                void M()
                {
                    var a = 1;
                    a++;
                    var b = new True();
                    b++;
                }
            }
            class True
            {
                public static True operator ++(True a)
                {
                     return new True();
                }
            }
            """,
            testHost,
            Keyword("var"),
            Local("a"),
            Keyword("var"),
            Class("True"),
            Local("b"),
            OverloadedOperators.PlusPlus,
            Class("True"),
            Class("True"),
            Class("True"));
    }
 
    [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/29492")]
    [CombinatorialData]
    public async Task TestOverloadedOperator_ConditionalExpression(TestHost testHost)
    {
        await TestAsync("""
            class C
            {
                void M()
                {
                    var a = 1 == 1;
                    var b = new True() == new True();
                }
            }
            class True
            {
                public static bool operator ==(True a, True b)
                {
                     return true;
                }
            }
            """,
            testHost,
            Keyword("var"),
            Keyword("var"),
            Class("True"),
            OverloadedOperators.EqualsEquals,
            Class("True"),
            Class("True"),
            Class("True"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestCatchDeclarationVariable(TestHost testHost)
    {
        await TestInMethodAsync("""
            try
            {
            }
            catch (Exception ex)
            {
                throw ex;
            }
            """,
            testHost,
            Local("ex"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_InsideMethod(TestHost testHost)
    {
        // Asserts no Keyword("notnull") because it is an identifier.
        await TestInMethodAsync("""
            var notnull = 0;
            notnull++;
            """,
            testHost,
            Keyword("var"),
            Local("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_Type_Keyword(TestHost testHost)
    {
        await TestAsync(
            "class X<T> where T : notnull { }",
            testHost,
            TypeParameter("T"),
            Keyword("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_Type_ExistingInterface(TestHost testHost)
    {
        await TestAsync("""
            interface notnull {}
            class X<T> where T : notnull { }
            """,
            testHost,
            TypeParameter("T"),
            Keyword("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_Type_ExistingInterfaceButOutOfScope(TestHost testHost)
    {
        await TestAsync("""
            namespace OtherScope
            {
                interface notnull {}
            }
            class X<T> where T : notnull { }
            """,
            testHost,
            Namespace("OtherScope"),
            TypeParameter("T"),
            Keyword("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_Method_Keyword(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void M<T>() where T : notnull { }
            }
            """,
            testHost,
            TypeParameter("T"),
            Keyword("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_Method_ExistingInterface(TestHost testHost)
    {
        await TestAsync("""
            interface notnull {}
            class X
            {
                void M<T>() where T : notnull { }
            }
            """,
            testHost,
            TypeParameter("T"),
            Keyword("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_Method_ExistingInterfaceButOutOfScope(TestHost testHost)
    {
        await TestAsync("""
            namespace OtherScope
            {
                interface notnull {}
            }
            class X
            {
                void M<T>() where T : notnull { }
            }
            """,
            testHost,
            Namespace("OtherScope"),
            TypeParameter("T"),
            Keyword("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_Delegate_Keyword(TestHost testHost)
    {
        await TestAsync(
            "delegate void D<T>() where T : notnull;",
            testHost,
            TypeParameter("T"),
            Keyword("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_Delegate_ExistingInterface(TestHost testHost)
    {
        await TestAsync("""
            interface notnull {}
            delegate void D<T>() where T : notnull;
            """,
            testHost,
            TypeParameter("T"),
            Keyword("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_Delegate_ExistingInterfaceButOutOfScope(TestHost testHost)
    {
        await TestAsync("""
            namespace OtherScope
            {
                interface notnull {}
            }
            delegate void D<T>() where T : notnull;
            """,
            testHost,
            Namespace("OtherScope"),
            TypeParameter("T"),
            Keyword("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_LocalFunction_Keyword(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    void M<T>() where T : notnull { }
                }
            }
            """,
            testHost,
            TypeParameter("T"),
            Keyword("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_LocalFunction_ExistingInterface(TestHost testHost)
    {
        await TestAsync("""
            interface notnull {}
            class X
            {
                void N()
                {
                    void M<T>() where T : notnull { }
                }
            }
            """,
            testHost,
            TypeParameter("T"),
            Keyword("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task TestNotNullConstraint_LocalFunction_ExistingInterfaceButOutOfScope(TestHost testHost)
    {
        await TestAsync("""
            namespace OtherScope
            {
                interface notnull {}
            }
            class X
            {
                void N()
                {
                    void M<T>() where T : notnull { }
                }
            }
            """,
            testHost,
            Namespace("OtherScope"),
            TypeParameter("T"),
            Keyword("notnull"));
    }
 
    [Theory, CombinatorialData]
    public async Task NonDiscardVariableDeclaration(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    var _ = int.Parse("");
                }
            }
            """,
            testHost,
            Keyword("var"),
            Method("Parse"),
            Static("Parse"));
    }
 
    [Theory, CombinatorialData]
    public async Task NonDiscardVariableDeclarationMultipleDeclarators(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    int i = 1, _ = 1;
                    int _ = 2, j = 1;
                }
            }
            """, testHost);
    }
 
    [Theory, CombinatorialData]
    public async Task DiscardAssignment(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    _ = int.Parse("");
                }
            }
            """,
            testHost,
            Keyword("_"),
            Method("Parse"),
            Static("Parse"));
    }
 
    [Theory, CombinatorialData]
    public async Task DiscardInOutDeclaration(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    int.TryParse("", out var _);
                }
            }
            """,
            testHost,
            Method("TryParse"),
            Static("TryParse"),
            Keyword("var"),
            Keyword("_"));
    }
 
    [Theory, CombinatorialData]
    public async Task DiscardInOutAssignment(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    int.TryParse("", out _);
                }
            }
            """,
            testHost,
            Method("TryParse"),
            Static("TryParse"),
            Keyword("_"));
    }
 
    [Theory, CombinatorialData]
    public async Task DiscardInDeconstructionAssignment(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    (x, _) = (0, 0);
                }
            }
            """,
            testHost,
            Keyword("_"));
    }
 
    [Theory, CombinatorialData]
    public async Task DiscardInDeconstructionDeclaration(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    (int x, int _) = (0, 0);
                }
            }
            """,
            testHost,
            Keyword("_"));
    }
 
    [Theory, CombinatorialData]
    public async Task DiscardInPatternMatch(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                bool N(object x)
                {
                    return x is int _;
                }
            }
            """,
            testHost,
            Parameter("x"),
            Keyword("_"));
    }
 
    [Theory, CombinatorialData]
    public async Task DiscardInSwitch(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                bool N(object x)
                {
                    switch(x)
                    {
                        case int _:
                            return true;
                        default:
                            return false;
                    }
                }
            }
            """,
            testHost,
            Parameter("x"),
            Keyword("_"));
    }
 
    [Theory, CombinatorialData]
    public async Task DiscardInSwitchPatternMatch(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                bool N(object x)
                {
                    return x switch
                    {
                        _ => return true;
                    };
                }
            }
            """,
            testHost,
            Parameter("x"),
            Keyword("_"));
    }
 
    [Theory, CombinatorialData]
    public async Task UnusedUnderscoreParameterInLambda(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    System.Func<int, int> a = (int _) => 0;
                }
            }
            """,
            testHost,
            Namespace("System"),
            Delegate("Func"));
    }
 
    [Theory, CombinatorialData]
    public async Task UsedUnderscoreParameterInLambda(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    System.Func<int, int> a = (int _) => _;
                }
            }
            """,
            testHost,
            Namespace("System"),
            Delegate("Func"),
            Parameter("_"));
    }
 
    [Theory, CombinatorialData]
    public async Task DiscardsInLambda(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    System.Func<int, int, int> a = (int _, int _) => 0;
                }
            }
            """,
            testHost,
            Namespace("System"),
            Delegate("Func"),
            Keyword("_"),
            Keyword("_"));
    }
 
    [Theory, CombinatorialData]
    public async Task DiscardsInLambdaWithInferredType(TestHost testHost)
    {
        await TestAsync("""
            class X
            {
                void N()
                {
                    System.Func<int, int, int> a = (_, _) => 0;
                }
            }
            """,
            testHost,
            Namespace("System"),
            Delegate("Func"),
            Keyword("_"),
            Keyword("_"));
    }
 
    [Theory, CombinatorialData]
    public async Task NativeInteger(TestHost testHost)
    {
        await TestInMethodAsync(
            @"nint i = 0; nuint i2 = 0;",
            testHost,
            Classifications(Keyword("nint"), Keyword("nuint")));
    }
 
    [Theory, CombinatorialData]
    public async Task NotNativeInteger(TestHost testHost)
    {
        await TestInMethodAsync(
            "nint",
            "M",
            "nint i = 0;",
            testHost,
            Classifications(Class("nint")));
    }
 
    [Theory, CombinatorialData]
    public async Task NotNativeUnsignedInteger(TestHost testHost)
    {
        await TestInMethodAsync(
            "nuint",
            "M",
            "nuint i = 0;",
            testHost,
            Classifications(Class("nuint")));
    }
 
    [Theory, CombinatorialData]
    public async Task StaticBoldingMethodName(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                public static void Method()
                {
                    System.Action action = Method;
                }
            }
            """,
            testHost,
            Namespace("System"),
            Delegate("Action"),
            Method("Method"),
            Static("Method"));
    }
 
    [Theory, CombinatorialData]
    public async Task StaticBoldingMethodNameNestedInNameof(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                public static void Method()
                {
                    _ = nameof(Method);
                }
            }
            """,
            testHost,
            Keyword("_"),
            Keyword("nameof"),
            Static("Method"),
            Method("Method"));
    }
 
    [Theory, CombinatorialData]
    public async Task BoldingMethodNameStaticAndNot(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                public static void Method()
                {
 
                }
 
                public void Method(int x) 
                {
 
                }
 
                public void Test() {
                    _ = nameof(Method);
                }
            }
            """,
            testHost,
            Keyword("_"),
            Keyword("nameof"),
            Static("Method"),
            Method("Method"));
    }
 
    [Theory, CombinatorialData]
    [WorkItem("https://github.com/dotnet/roslyn/issues/46985")]
    public async Task BasicRecordClassification(TestHost testHost)
    {
        await TestAsync(
            """
            record R
            {
                R r;
 
                R() { }
            }
            """,
            testHost,
            RecordClass("R"));
    }
 
    [Theory, CombinatorialData]
    [WorkItem("https://github.com/dotnet/roslyn/issues/46985")]
    public async Task ParameterizedRecordClassification(TestHost testHost)
    {
        await TestAsync(
            """
            record R(int X, int Y);
 
            class C
            {
                R r;
            }
            """,
            testHost,
            RecordClass("R"));
    }
 
    [Theory, CombinatorialData]
    public async Task BasicRecordClassClassification(TestHost testHost)
    {
        await TestAsync(
            """
            record class R
            {
                R r;
 
                R() { }
            }
            """,
            testHost,
            RecordClass("R"));
    }
 
    [Theory, CombinatorialData]
    public async Task BasicRecordStructClassification(TestHost testHost)
    {
        await TestAsync(
            """
            record struct R
            {
                R property { get; set; }
            }
            """,
            testHost,
            RecordStruct("R"));
    }
 
    [Theory, CombinatorialData]
    public async Task BasicFileScopedNamespaceClassification(TestHost testHost)
    {
        await TestAsync(
            """
            namespace NS;
 
            class C { }
            """,
            testHost,
            Namespace("NS"));
    }
 
    [Theory, CombinatorialData]
    public async Task NullCheckedParameterClassification(TestHost testHost)
    {
        await TestAsync(
            """
            class C
            {
                void M(string s!!) { }
            }
            """,
            testHost);
    }
 
    [Theory, CombinatorialData]
    [WorkItem("https://github.com/dotnet/roslyn/issues/57184")]
    public async Task MethodGroupClassifications(TestHost testHost)
    {
        await TestAsync(
            """
            var f = m;
            Delegate d = m;
            MulticastDelegate md = m;
            ICloneable c = m;
            object obj = m;
            m(m);
 
            int m(Delegate d) { }
            """,
            testHost,
            Keyword("var"),
            Method("m"),
            Method("m"),
            Method("m"),
            Method("m"),
            Method("m"),
            Method("m"),
            Method("m"));
    }
 
    /// <seealso cref="SyntacticClassifierTests.LocalFunctionDeclaration"/>
    /// <seealso cref="TotalClassifierTests.LocalFunctionDeclarationAndUse"/>
    [Theory, CombinatorialData]
    public async Task LocalFunctionUse(TestHost testHost)
    {
        await TestAsync(
            """
            using System;
 
            class C
            {
                void M(Action action)
                {
                    [|localFunction();
                    staticLocalFunction();
 
                    M(localFunction);
                    M(staticLocalFunction);
 
                    void localFunction() { }
                    static void staticLocalFunction() { }|]
                }
            }
 
            """,
            testHost,
            Method("localFunction"),
            Method("staticLocalFunction"),
            Static("staticLocalFunction"),
            Method("M"),
            Method("localFunction"),
            Method("M"),
            Method("staticLocalFunction"),
            Static("staticLocalFunction"));
    }
 
    [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/744813")]
    public async Task TestCreateWithBufferNotInWorkspace()
    {
        // don't crash
        using var workspace = EditorTestWorkspace.CreateCSharp("");
        var document = workspace.CurrentSolution.GetRequiredDocument(workspace.Documents.First().Id);
 
        var contentTypeService = document.GetRequiredLanguageService<IContentTypeLanguageService>();
        var contentType = contentTypeService.GetDefaultContentType();
        var extraBuffer = workspace.ExportProvider.GetExportedValue<ITextBufferFactoryService>().CreateTextBuffer("", contentType);
 
        WpfTestRunner.RequireWpfFact($"Creates an {nameof(IWpfTextView)} explicitly with an unrelated buffer");
        using var disposableView = workspace.ExportProvider.GetExportedValue<ITextEditorFactoryService>().CreateDisposableTextView(extraBuffer);
        var listenerProvider = workspace.ExportProvider.GetExportedValue<IAsynchronousOperationListenerProvider>();
        var globalOptions = workspace.ExportProvider.GetExportedValue<IGlobalOptionService>();
 
        var provider = new SemanticClassificationViewTaggerProvider(
            workspace.GetService<TaggerHost>(),
            workspace.GetService<ClassificationTypeMap>());
 
        using var tagger = provider.CreateTagger(disposableView.TextView, extraBuffer);
        using (var edit = extraBuffer.CreateEdit())
        {
            edit.Insert(0, "class A { }");
            edit.Apply();
        }
 
        var waiter = listenerProvider.GetWaiter(FeatureAttribute.Classification);
        await waiter.ExpeditedWaitAsync();
    }
}