File: Semantics\NameOfTests.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Semantic\Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
    public sealed class NameofTests : CSharpTestBase
    {
        [Fact]
        public void TestGoodNameofInstances()
        {
            var source = @"
using System;
using System.Collections.Generic;
using alias1 = System;
using alias2 = System.Collections.Generic;
namespace Source
{
    class Class { }
    struct Struct { }
    enum Enum { e }
    interface Interface { }
    class StaticClass { }
}
 
class Test
{
    public int instanceVar;
    private static int privateVar;
}
class TestGeneric<T>
{
    public class NestedGeneric<T1> { }
}
 
class Program
{
    string var1;
    static byte @static;
    char nameof;
    event EventHandler Event;
    delegate void DelegateExample(object sender, EventArgs e);
 
    static void Main(string[] args)
    {
        // (1) identifier
        int var2;
        Console.WriteLine(nameof(var2));
        Console.WriteLine(nameof(nameof));
        Console.WriteLine(nameof(var1));
        Console.WriteLine(nameof(@static));
        Console.WriteLine(nameof(args));
        Console.WriteLine(nameof(Program));
        Console.WriteLine(nameof(Event));
        Console.WriteLine(nameof(DelegateExample));
        Console.WriteLine(nameof(Source));
 
        // (1.1) from metadata
        Console.WriteLine(nameof(IFormattable));
        Console.WriteLine(nameof(Math));
 
 
        // (2) unbound-type-name . identifier
 
        // (2.1) identifier . identifier
        Console.WriteLine(nameof(Source.Class));
        Console.WriteLine(nameof(Source.Struct));
        Console.WriteLine(nameof(Source.Enum));
        Console.WriteLine(nameof(Source.Interface));
        Console.WriteLine(nameof(Source.StaticClass));
        Console.WriteLine(nameof(Program.Main));
        Console.WriteLine(nameof(System.Byte));
        Console.WriteLine(nameof(System.Int64));
 
        // (2.2) generic name . identifier
        Console.WriteLine(nameof(List<int>.Equals));
        Console.WriteLine(nameof(Dictionary<int,int>.Add));
        Console.WriteLine(nameof(List<int>.Enumerator));
 
        // (2.3) qualified name . identifier
        Console.WriteLine(nameof(TestGeneric<int>.NestedGeneric<int>.Equals));
        Console.WriteLine(nameof(global::Test.instanceVar));
        Console.WriteLine(nameof(System.IO.FileMode));
        Console.WriteLine(nameof(System.Collections.Generic.List<int>));
        Console.WriteLine(nameof(alias1::Collections.Generic.List<int>.Add));
 
        // (2.4) accessing instance members of other classes
        Console.WriteLine(nameof(Test.instanceVar));
 
        // (2.5) members that hide
        Console.WriteLine(nameof(E.D));
        Console.WriteLine(nameof(A.D.C));
 
        ////// (3) identifier :: identifier
        ////Console.WriteLine(nameof(alias2::List<int>));
        ////Console.WriteLine(nameof(global::Microsoft));
 
        // postfix
        Console.WriteLine(nameof(System)[0]);
    }
}
 
class A
{
    public class B
    {
        public class C { }
    }
 
    public class D : B
    {
        new public const int C = 0;
    }
}
 
class E : A
{
    new public const int D = 0;
}
 
interface I1
{
    int M();
    int N { get; }
}
interface I2
{
    int M<T>();
    int N { get; }
}
interface I3 : I1, I2
{
    // testing ambiguous
    int Test(string arg = nameof(M), string arg2 = ""N"" /* nameof(N) */);
}
";
            var comp = CompileAndVerify(source, expectedOutput: @"
var2
nameof
var1
static
args
Program
Event
DelegateExample
Source
IFormattable
Math
Class
Struct
Enum
Interface
StaticClass
Main
Byte
Int64
Equals
Add
Enumerator
Equals
instanceVar
FileMode
List
Add
instanceVar
D
C
S");
        }
 
        [Fact]
        public void TestBadNameofInstances()
        {
            var source = @"
using System;
using System.Linq;
 
class Program
{
    static void Main(string[] args)
    {
        string s;
        // identifier expected errors
        s = nameof(System.Action<>);
        s = nameof(int);
        s = nameof(void);
 
        // unexpected unbound errors
        s = nameof(List<int>.Enumerator);
        s = nameof(System.Collections.Generic.Dictionary<Program,>.KeyCollection);
        s = nameof(global::System.Collections.Generic.List<string>.Enumerator);
        s = nameof(Test<Object>.s);
 
        // does not exist in current context
        s = nameof(nameof);
        s = nameof(Program.s2);
        s = nameof(Object.Something);
        s = nameof(global::Something);
        s = nameof(global2::Something);
        s = nameof(System.Collections2.Generic.List);
        s = nameof(List2<>.Add);
 
        // other type of errors
        s = nameof(global::Program); // not an expression
        s = nameof(Test<>.s); // inaccessible
        s = nameof(b); // cannot use before declaration
        //s = nameof(System.Collections.Generic.List<int>.Select); // extension methods are now candidates for nameof
        s = nameof(System.Linq.Enumerable.Select<int, int>); // type parameters not allowed on method group in nameof
        int b;
 
    }
    void ParsedAsInvocation()
    {
        string s;
        // parsed as invocation expression 
        s = nameof();
        s = nameof(this);
        s = nameof(this.ParsedAsInvocation);
        s = nameof(int.ToString);
        s = nameof(typeof(string));
        string[] a = null;
        s = nameof(a[4].Equals);
    }
}
class Test<T>
{
    static string s;
}";
            var option = TestOptions.ReleaseExe.WithWarningLevel(0);
            CreateCompilationWithMscorlib40AndSystemCore(source, options: option).VerifyDiagnostics(
                // (12,20): error CS1525: Invalid expression term 'int'
                //         s = nameof(int);
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(12, 20),
                // (13,20): error CS1525: Invalid expression term 'void'
                //         s = nameof(void);
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "void").WithArguments("void").WithLocation(13, 20),
                // (17,66): error CS1031: Type expected
                //         s = nameof(System.Collections.Generic.Dictionary<Program,>.KeyCollection);
                Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(17, 66),
                // (16,20): error CS0103: The name 'List' does not exist in the current context
                //         s = nameof(List<int>.Enumerator);
                Diagnostic(ErrorCode.ERR_NameNotInContext, "List<int>").WithArguments("List").WithLocation(16, 20),
                // (19,33): error CS0122: 'Test<object>.s' is inaccessible due to its protection level
                //         s = nameof(Test<Object>.s);
                Diagnostic(ErrorCode.ERR_BadAccess, "s").WithArguments("Test<object>.s").WithLocation(19, 33),
                // (22,20): error CS0103: The name 'nameof' does not exist in the current context
                //         s = nameof(nameof);
                Diagnostic(ErrorCode.ERR_NameNotInContext, "nameof").WithArguments("nameof").WithLocation(22, 20),
                // (23,28): error CS0117: 'Program' does not contain a definition for 's2'
                //         s = nameof(Program.s2);
                Diagnostic(ErrorCode.ERR_NoSuchMember, "s2").WithArguments("Program", "s2").WithLocation(23, 28),
                // (24,27): error CS0117: 'object' does not contain a definition for 'Something'
                //         s = nameof(Object.Something);
                Diagnostic(ErrorCode.ERR_NoSuchMember, "Something").WithArguments("object", "Something").WithLocation(24, 27),
                // (25,28): error CS0400: The type or namespace name 'Something' could not be found in the global namespace (are you missing an assembly reference?)
                //         s = nameof(global::Something);
                Diagnostic(ErrorCode.ERR_GlobalSingleTypeNameNotFound, "Something").WithArguments("Something").WithLocation(25, 28),
                // (26,20): error CS0432: Alias 'global2' not found
                //         s = nameof(global2::Something);
                Diagnostic(ErrorCode.ERR_AliasNotFound, "global2").WithArguments("global2").WithLocation(26, 20),
                // (27,20): error CS0234: The type or namespace name 'Collections2' does not exist in the namespace 'System' (are you missing an assembly reference?)
                //         s = nameof(System.Collections2.Generic.List);
                Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInNS, "System.Collections2").WithArguments("Collections2", "System").WithLocation(27, 20),
                // (28,20): error CS0103: The name 'List2' does not exist in the current context
                //         s = nameof(List2<>.Add);
                Diagnostic(ErrorCode.ERR_NameNotInContext, "List2<>").WithArguments("List2").WithLocation(28, 20),
                // (31,20): error CS8083: An alias-qualified name is not an expression.
                //         s = nameof(global::Program); // not an expression
                Diagnostic(ErrorCode.ERR_AliasQualifiedNameNotAnExpression, "global::Program").WithLocation(31, 20),
                // (32,27): error CS0122: 'Test<T>.s' is inaccessible due to its protection level
                //         s = nameof(Test<>.s); // inaccessible
                Diagnostic(ErrorCode.ERR_BadAccess, "s").WithArguments("Test<T>.s").WithLocation(32, 27),
                // (33,20): error CS0841: Cannot use local variable 'b' before it is declared
                //         s = nameof(b); // cannot use before declaration
                Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "b").WithArguments("b").WithLocation(33, 20),
                // (35,20): error CS8084: Type parameters are not allowed on a method group as an argument to 'nameof'.
                //         s = nameof(System.Linq.Enumerable.Select<int, int>); // type parameters not allowed on method group in nameof
                Diagnostic(ErrorCode.ERR_NameofMethodGroupWithTypeParameters, "System.Linq.Enumerable.Select<int, int>").WithLocation(35, 20),
                // (43,13): error CS0103: The name 'nameof' does not exist in the current context
                //         s = nameof();
                Diagnostic(ErrorCode.ERR_NameNotInContext, "nameof").WithArguments("nameof").WithLocation(43, 13),
                // (44,20): error CS8081: Expression does not have a name.
                //         s = nameof(this);
                Diagnostic(ErrorCode.ERR_ExpressionHasNoName, "this").WithLocation(44, 20),
                // (47,20): error CS8081: Expression does not have a name.
                //         s = nameof(typeof(string));
                Diagnostic(ErrorCode.ERR_ExpressionHasNoName, "typeof(string)").WithLocation(47, 20),
                // (49,20): error CS8082: Sub-expression cannot be used in an argument to nameof.
                //         s = nameof(a[4].Equals);
                Diagnostic(ErrorCode.ERR_SubexpressionNotInNameof, "a[4]").WithLocation(49, 20)
            );
        }
 
        [Fact]
        public void TestWhenNameofOperatorBinds()
        {
            var source = @"
using System;
class Class
{
    public static int var;
}
class NameofField
{
    static string nameof;
    static void Main(string[] args)
    {
        Console.WriteLine(nameof(Class.var));
    }
}
class NameofTypeParameter<nameof>
{
    static void test()
    {
        Console.WriteLine(nameof(Class.var));
    }
}
class NameofLabel
{
    static void test()
    {
    nameof:
        Console.WriteLine(nameof(Class.var));
        goto nameof;
    }
}
class NameofDelegate
{
    public delegate void nameof(object sender, EventArgs e);
    static void test()
    {
        Console.WriteLine(nameof(Class.var));
    }
}
class PrivateNameofMethodInSuperClass : Super1
{
    static void test()
    {
        Console.WriteLine(nameof(Class.var));
    }
}
class Super1
{
    private static void nameof() { }
}
class NameofProperty
{
    public int nameof
    {
        get { return 3; }
    }
    void test()
    {
        Console.WriteLine(nameof(Class.var));
    }
}
class NameofDynamic
{
    dynamic nameof;
    void test()
    {
        Console.WriteLine(nameof(Class.var));
    }
}
class NameofEvent
{
    event Action nameof { add { } remove { } }
    void test()
    {
        nameof(Class.var);
    }
}
class NameofParameter
{
    static void test(string nameof)
    {
        Console.WriteLine(nameof(Class.var));
    }
}
class NameofLocal
{
    static void test()
    {
        string nameof = ""naber"";
        Console.WriteLine(nameof(Class.var));
        }
    }
    class NameofMethod
    {
        static void test()
        {
            Console.WriteLine(nameof(Class.var));
        }
        int nameof() { return 3; }
    }
    class NameofMethodInSuperClass : Super2
    {
        static void test()
        {
            Console.WriteLine(nameof(Class.var));
        }
    }
    public class Super2
    {
        public static int nameof() { return 3; }
    }
";
            MetadataReference[] references = new[] { SystemCoreRef, CSharpRef };
            var option = TestOptions.ReleaseExe.WithWarningLevel(0);
            CreateCompilationWithMscorlib461(source, references, options: option).VerifyDiagnostics(
                // (104,31): error CS1501: No overload for method 'nameof' takes 1 arguments
                //             Console.WriteLine(nameof(Class.var));
                Diagnostic(ErrorCode.ERR_BadArgCount, "nameof").WithArguments("nameof", "1").WithLocation(104, 31),
                // (74,9): error CS0079: The event 'NameofEvent.nameof' can only appear on the left hand side of += or -=
                //         nameof(Class.var);
                Diagnostic(ErrorCode.ERR_BadEventUsageNoField, "nameof").WithArguments("NameofEvent.nameof").WithLocation(74, 9),
                // (74,9): error CS1593: Delegate 'System.Action' does not take 1 arguments
                //         nameof(Class.var);
                Diagnostic(ErrorCode.ERR_BadDelArgCount, "nameof").WithArguments("System.Action", "1").WithLocation(74, 9),
                // (81,27): error CS0149: Method name expected
                //         Console.WriteLine(nameof(Class.var));
                Diagnostic(ErrorCode.ERR_MethodNameExpected, "nameof").WithLocation(81, 27),
                // (96,31): error CS1501: No overload for method 'nameof' takes 1 arguments
                //             Console.WriteLine(nameof(Class.var));
                Diagnostic(ErrorCode.ERR_BadArgCount, "nameof").WithArguments("nameof", "1").WithLocation(96, 31),
                // (89,27): error CS0149: Method name expected
                //         Console.WriteLine(nameof(Class.var));
                Diagnostic(ErrorCode.ERR_MethodNameExpected, "nameof").WithLocation(89, 27)
            );
        }
 
        [Fact]
        public void TestNameofDifferentContexts()
        {
            var source = @"
using System;
using System.Collections.Generic;
using System.Linq;
namespace Source
{
    class Class { }
    struct Struct { }
    enum Enum { e }
    interface Interface { }
    class StaticClass { }
}
class Program
{
    // field initializer
    string className = nameof(Program);
    string temp;
 
    // in getter and setter
    public string EntryMethodName { get { return nameof(Program.Main); } set { temp = nameof(Program.Main); } }
 
    static void Main(string[] args)
    {
        // array initializer
        string[] values = { nameof(Source.Enum), nameof(Source.Interface), nameof(Source.Struct), nameof(Source.Class) };
        // as an argument
        TestParameter(nameof(EntryMethodName));
 
        // switch argument
        switch (nameof(Dictionary<int,int>.Add))
        {
            // case expression
            case nameof(List<int>.Equals):
                // goto case
                goto case nameof(Dictionary<int,int>.Add);
                break;
            case nameof(List<int>.Add):
                Console.WriteLine(""Correct"");
                break;
        }
 
        // in query expression
        string result = (from value in values where value == nameof(Source.Struct) select value).First();
        // as a range variable
        var s = (from value in values let name = nameof(Source.Enum) select new { value, name });
        // in if condition
        if (values[0] == nameof(Source.Enum) && result == nameof(Source.Struct))
            Console.WriteLine(""Correct"");
    }
    // default parameter value
    static void TestParameter(string arg = nameof(Program.TestParameter))
    {
        Console.WriteLine(arg);
    }
 
    // in attribute with string concatenation 
    [Obsolete(""Please do not use this method: "" + nameof(Program.Old), true)]
    static void Old() { }
}";
            CompileAndVerify(source, expectedOutput: @"
EntryMethodName
Correct
Correct");
        }
 
        [Fact]
        public void TestNameofLowerLangVersion()
        {
            var comp = CreateCompilation(@"
class Program
{
    Program(string s = nameof(Program))
    { }
}
", parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp5));
 
            comp.VerifyDiagnostics(
                // (4,24): error CS8026: Feature 'nameof operator' is not available in C# 5. Please use language version 6 or greater.
                //     Program(string s = nameof(Program))
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion5, "nameof(Program)").WithArguments("nameof operator", "6").WithLocation(4, 24)
                );
        }
 
        [Fact]
        [WorkItem(33564, "https://github.com/dotnet/roslyn/issues/33564")]
        public void TestNameofIndexerName()
        {
            var source = @"
using System.Linq;
class C
{
    public static void Main(string[] args)
    {
        var t = typeof(C);
        foreach (var m in t.GetMethods().Where(m => m.DeclaringType == t).OrderBy(m => m.Name))
        {
            System.Console.WriteLine(m.Name);
        }
    }
    public int Other(int index) { return 0; }
    [System.Runtime.CompilerServices.IndexerName(""_"" + nameof(Other))]
    public int this[int index]
    {
        get { return 0; }
    }
}";
            CompileAndVerify(source, expectedOutput:
@"get__Other
Main
Other");
        }
 
        [Fact]
        public void TestNameofAliasMember()
        {
            var source = @"
using System;
using SCGL = System.Collections.Generic.List<int>;
class C
{
    public static void Main(string[] args)
    {
        System.Console.WriteLine(nameof(SCGL.Contains));
    }
}";
            CompileAndVerify(source, expectedOutput: @"Contains");
        }
 
        [Fact, WorkItem(1013334, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1013334")]
        public void TestCompatStatementExpressionInvocation()
        {
            var source = @"
using System;
class Program
{
    static void nameof(object o)
    {
        Console.WriteLine(o);
    }
    static int N = 12;
    static void Main(string[] args)
    {
        nameof(N);
    }
}";
            var compilation = CreateCompilation(
                source,
                options: TestOptions.DebugExe,
                parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp5));
            CompileAndVerify(compilation, expectedOutput: @"12");
        }
 
        [Fact, WorkItem(1013334, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1013334")]
        public void TestCompatStatementExpressionInvocation02()
        {
            var source = @"
using System;
class Program
{
    static void nameof(object o)
    {
        Console.WriteLine(o);
    }
    static int N = 12;
    static void Main(string[] args)
    {
        nameof(N);
    }
}";
            var compilation = CreateCompilation(
                source,
                options: TestOptions.DebugExe,
                parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6));
            CompileAndVerify(compilation, expectedOutput: @"12");
        }
 
        [Fact, WorkItem(1013334, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1013334")]
        public void TestCompatStatementExpressionInvocation03()
        {
            var source = @"
class Program
{
    const int N = 12;
    static void Main(string[] args)
    {
        nameof(N);
    }
}";
            var compilation = CreateCompilation(
                source,
                options: TestOptions.DebugExe,
                parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)).VerifyDiagnostics(
                    // (7,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
                    //         nameof(N);
                    Diagnostic(ErrorCode.ERR_IllegalStatement, "nameof(N)").WithLocation(7, 9)
                );
        }
 
        [Fact, WorkItem(1013334, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1013334")]
        public void TestCompatStatementExpressionInvocation04()
        {
            var source = @"
class Program
{
    const int N = 12;
    static void Main(string[] args)
    {
        nameof(N);
    }
}";
            var compilation = CreateCompilation(
                source,
                options: TestOptions.DebugExe,
                parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp5)).VerifyDiagnostics(
                    // (7,9): error CS8026: Feature 'nameof operator' is not available in C# 5. Please use language version 6 or greater.
                    //         nameof(N);
                    Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion5, "nameof(N)").WithArguments("nameof operator", "6").WithLocation(7, 9),
                    // (7,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
                    //         nameof(N);
                    Diagnostic(ErrorCode.ERR_IllegalStatement, "nameof(N)").WithLocation(7, 9)
                );
        }
 
        [Fact]
        [WorkItem(1023539, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1023539")]
        public void SymbolInfoForMethodGroup01()
        {
            var source =
@"public class SomeClass
{
    public const string GooName = nameof(SomeClass.Goo);
    public static int Goo()
    {
        return 1;
    }
}";
            var compilation = CreateCompilation(source);
            var tree = compilation.SyntaxTrees[0];
            var model = compilation.GetSemanticModel(tree);
            var node = tree.GetRoot().DescendantNodes().Where(n => n.ToString() == "SomeClass.Goo").OfType<ExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(node, default(CancellationToken));
            Assert.Equal(CandidateReason.MemberGroup, symbolInfo.CandidateReason);
            Assert.Equal("Goo", symbolInfo.CandidateSymbols[0].Name);
        }
 
        [Fact]
        [WorkItem(1023539, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1023539")]
        public void SymbolInfoForMethodGroup02()
        {
            var source =
@"public class SomeClass
{
    public const string GooName = nameof(SomeClass.Goo);
    public static int Goo()
    {
        return 1;
    }
    public static string Goo()
    {
        return string.Empty;
    }
}";
            var compilation = CreateCompilation(source);
            var tree = compilation.SyntaxTrees[0];
            var model = compilation.GetSemanticModel(tree);
            var node = tree.GetRoot().DescendantNodes().Where(n => n.ToString() == "SomeClass.Goo").OfType<ExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(node, default(CancellationToken));
            Assert.Equal(CandidateReason.MemberGroup, symbolInfo.CandidateReason);
            Assert.Equal(2, symbolInfo.CandidateSymbols.Length);
        }
 
        [Fact]
        [WorkItem(1077150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077150")]
        public void SymbolInfoForMethodGroup03()
        {
            var source =
@"public class A
{
}
public static class X1
{
    public static string Extension(this A a) { return null; }
}
public class Program
{
    public static void Main(string[] args)
    {
        A a = null;
        Use(nameof(a.Extension));
    }
    private static void Use(object o) {}
}";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
            compilation.VerifyDiagnostics(
                // (13,20): error CS8093: Extension method groups are not allowed as an argument to 'nameof'.
                //         Use(nameof(a.Extension));
                Diagnostic(ErrorCode.ERR_NameofExtensionMethod, "a.Extension").WithLocation(13, 20)
                );
            var tree = compilation.SyntaxTrees[0];
            var model = compilation.GetSemanticModel(tree);
            var node = tree.GetRoot().DescendantNodes().Where(n => n.ToString() == "a.Extension").OfType<ExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(node, default(CancellationToken));
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.MemberGroup, symbolInfo.CandidateReason);
            Assert.Equal(1, symbolInfo.CandidateSymbols.Length);
        }
 
        [Fact]
        [WorkItem(1077150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077150")]
        public void SymbolInfoForMethodGroup04()
        {
            var source =
@"public class A
{
}
namespace N1
{
    public static class X1
    {
        public static string Extension(this A a) { return null; }
    }
    namespace N2
    {
        public static class X2
        {
            public static string Extension(this A a, long x) { return null; }
            public static string Extension(this A a, int x) { return null; }
        }
        public class Program
        {
            public static void Main(string[] args)
            {
                A a = null;
                Use(nameof(a.Extension));
            }
            private static void Use(object o) {}
        }
    }
}";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
            compilation.VerifyDiagnostics(
                // (22,28): error CS8093: Extension method groups are not allowed as an argument to 'nameof'.
                //                 Use(nameof(a.Extension));
                Diagnostic(ErrorCode.ERR_NameofExtensionMethod, "a.Extension").WithLocation(22, 28)
                );
            var tree = compilation.SyntaxTrees[0];
            var model = compilation.GetSemanticModel(tree);
            var node = tree.GetRoot().DescendantNodes().Where(n => n.ToString() == "a.Extension").OfType<ExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(node, default(CancellationToken));
            Assert.Equal(CandidateReason.MemberGroup, symbolInfo.CandidateReason);
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(3, symbolInfo.CandidateSymbols.Length);
        }
 
        [Fact]
        [WorkItem(1077150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077150")]
        public void SymbolInfoForEmptyMethodGroup()
        {
            var source =
@"public class A
{
}
public static class X1
{
    public static string Extension(this string a) { return null; }
    public static string Extension(this int a) { return null; }
}
public class Program
{
    public static void Main(string[] args)
    {
        A a = null;
        Use(nameof(a.Extension));
    }
    private static void Use(object o) {}
}";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
            compilation.VerifyDiagnostics(
                // (14,22): error CS1061: 'A' does not contain a definition for 'Extension' and no accessible extension method 'Extension' accepting a first argument of type 'A' could be found (are you missing a using directive or an assembly reference?)
                //         Use(nameof(a.Extension));
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Extension").WithArguments("A", "Extension").WithLocation(14, 22)
                );
            var tree = compilation.SyntaxTrees[0];
            var model = compilation.GetSemanticModel(tree);
            var node = tree.GetRoot().DescendantNodes().Where(n => n.ToString() == "a.Extension").OfType<ExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(node, default(CancellationToken));
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(0, symbolInfo.CandidateSymbols.Length);
        }
 
        [Fact]
        [WorkItem(1077150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077150")]
        public void SymbolInfoForTypeFromInstance()
        {
            var source =
@"public class A
{
    public class Nested {}
}
public class Program
{
    public static void Main(string[] args)
    {
        A a = null;
        Use(nameof(a.Nested));
    }
    private static void Use(object o) {}
}";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
            compilation.VerifyDiagnostics(
                // (10,22): error CS0572: 'Nested': cannot reference a type through an expression; try 'A.Nested' instead
                //         Use(nameof(a.Nested));
                Diagnostic(ErrorCode.ERR_BadTypeReference, "Nested").WithArguments("Nested", "A.Nested").WithLocation(10, 22),
                // (9,11): warning CS0219: The variable 'a' is assigned but its value is never used
                //         A a = null;
                Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "a").WithArguments("a").WithLocation(9, 11)
                );
            var tree = compilation.SyntaxTrees[0];
            var model = compilation.GetSemanticModel(tree);
            var node = tree.GetRoot().DescendantNodes().Where(n => n.ToString() == "a.Nested").OfType<ExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(node, default(CancellationToken));
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.NotNull(symbolInfo.Symbol);
            Assert.Equal(0, symbolInfo.CandidateSymbols.Length);
        }
 
        [Fact]
        [WorkItem(1077150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077150")]
        public void SymbolInfoForMethodGroup05()
        {
            var source =
@"public class A
{
}
namespace N1
{
    public static class X1
    {
        public static string Extension(this A a) { return null; }
    }
    namespace N2
    {
        public static class X2
        {
            public static string Extension(this A a, long x) { return null; }
            public static string Extension(this A a, int x) { return null; }
        }
        public class Program
        {
            public static void Main(string[] args)
            {
                Use(nameof(A.Extension));
            }
            private static void Use(object o) {}
        }
    }
}";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
            compilation.VerifyDiagnostics(
                // (21,28): error CS8093: Extension method groups are not allowed as an argument to 'nameof'.
                //                 Use(nameof(A.Extension));
                Diagnostic(ErrorCode.ERR_NameofExtensionMethod, "A.Extension").WithLocation(21, 28)
                );
            var tree = compilation.SyntaxTrees[0];
            var model = compilation.GetSemanticModel(tree);
            var node = tree.GetRoot().DescendantNodes().Where(n => n.ToString() == "A.Extension").OfType<ExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(node, default(CancellationToken));
            Assert.Equal(CandidateReason.MemberGroup, symbolInfo.CandidateReason);
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(3, symbolInfo.CandidateSymbols.Length);
        }
 
        [Fact]
        [WorkItem(1077150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077150")]
        public void SymbolInfoForNothingFound()
        {
            var source =
@"public class A
{
}
public class Program
{
    public static void Main(string[] args)
    {
        A a = null;
        Use(nameof(a.Extension));
    }
    private static void Use(object o) {}
}
";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
            compilation.VerifyDiagnostics(
                // (9,22): error CS1061: 'A' does not contain a definition for 'Extension' and no extension method 'Extension' accepting a first argument of type 'A' could be found (are you missing a using directive or an assembly reference?)
                //         Use(nameof(a.Extension));
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Extension").WithArguments("A", "Extension").WithLocation(9, 22)
                );
            var tree = compilation.SyntaxTrees[0];
            var model = compilation.GetSemanticModel(tree);
            var node = tree.GetRoot().DescendantNodes().Where(n => n.ToString() == "a.Extension").OfType<ExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(node, default(CancellationToken));
            Assert.Equal(CandidateReason.None, symbolInfo.CandidateReason);
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(0, symbolInfo.CandidateSymbols.Length);
        }
 
        [Fact]
        public void SymbolInfo_InstanceMemberFromStatic_Flat()
        {
            var source = """
                public class C
                {
                    public int Property { get; }
                    public int Field;
                    public event System.Action Event;
 
                    public static string StaticField =
                        nameof(Property) +
                        nameof(Field) +
                        nameof(Event);
                }
                """;
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var cProperty = comp.GetMember("C.Property");
            var cField = comp.GetMember("C.Field");
            var cEvent = comp.GetMember("C.Event");
 
            var tree = comp.SyntaxTrees.Single();
            var tree2 = SyntaxFactory.ParseSyntaxTree(source + " ");
 
            var initializer = tree2.GetRoot().DescendantNodes().OfType<EqualsValueClauseSyntax>().Single();
 
            var nameofCalls = getNameOfCalls(tree);
            Assert.Equal(3, nameofCalls.Length);
            var nameofCalls2 = getNameOfCalls(tree2);
            Assert.Equal(3, nameofCalls2.Length);
 
            var model = comp.GetSemanticModel(tree);
 
            verify(0, "Property", cProperty);
            verify(1, "Field", cField);
            verify(2, "Event", cEvent);
 
            void verify(int index, string expression, Symbol symbol)
            {
                var argument = nameofCalls[index].ArgumentList.Arguments.Single().Expression;
                Assert.Equal(expression, argument.ToString());
 
                verifySymbolInfo(model.GetSymbolInfo(argument));
 
                var argument2 = nameofCalls2[index].ArgumentList.Arguments.Single().Expression;
                Assert.Equal(expression, argument2.ToString());
 
                Assert.True(model.TryGetSpeculativeSemanticModel(initializer.Position, initializer, out var model2));
 
                verifySymbolInfo(model2.GetSymbolInfo(argument2));
 
                verifySymbolInfo(model.GetSpeculativeSymbolInfo(argument2.Position, argument2, SpeculativeBindingOption.BindAsExpression));
 
                Assert.True(model.GetSpeculativeSymbolInfo(argument2.Position, argument2, SpeculativeBindingOption.BindAsTypeOrNamespace).IsEmpty);
 
                void verifySymbolInfo(SymbolInfo symbolInfo)
                {
                    Assert.NotNull(symbolInfo.Symbol);
                    Assert.Same(symbol.GetPublicSymbol(), symbolInfo.Symbol);
                }
            }
 
            static ImmutableArray<InvocationExpressionSyntax> getNameOfCalls(SyntaxTree tree)
            {
                return tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>()
                    .Where(e => e.Expression is IdentifierNameSyntax { Identifier.ValueText: "nameof" })
                    .ToImmutableArray();
            }
        }
 
        [Fact]
        public void SymbolInfo_InstanceMemberFromStatic_Flat_MethodGroup()
        {
            var source = """
                public class C
                {
                    public void Method1() { }
                    public void Method1(int i) { }
                    public void Method2() { }
                    public static void Method2(int i) { }
                
                    public static string StaticField =
                        nameof(Method1) +
                        nameof(Method2);
                }
                """;
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var cMethods1 = comp.GetMembers("C.Method1");
            Assert.Equal(2, cMethods1.Length);
            var cMethods2 = comp.GetMembers("C.Method2");
            Assert.Equal(2, cMethods2.Length);
 
            var tree = comp.SyntaxTrees.Single();
            var tree2 = SyntaxFactory.ParseSyntaxTree(source + " ");
 
            var initializer = tree2.GetRoot().DescendantNodes().OfType<EqualsValueClauseSyntax>().Single();
 
            var nameofCalls = getNameOfCalls(tree);
            Assert.Equal(2, nameofCalls.Length);
            var nameofCalls2 = getNameOfCalls(tree2);
            Assert.Equal(2, nameofCalls2.Length);
 
            var model = comp.GetSemanticModel(tree);
 
            verify(0, "Method1", cMethods1);
            verify(1, "Method2", cMethods2);
 
            void verify(int index, string expression, ImmutableArray<Symbol> symbols)
            {
                var argument = nameofCalls[index].ArgumentList.Arguments.Single().Expression;
                Assert.Equal(expression, argument.ToString());
 
                verifySymbolInfo(CandidateReason.MemberGroup, model.GetSymbolInfo(argument));
 
                var argument2 = nameofCalls2[index].ArgumentList.Arguments.Single().Expression;
                Assert.Equal(expression, argument2.ToString());
 
                Assert.True(model.TryGetSpeculativeSemanticModel(initializer.Position, initializer, out var model2));
 
                verifySymbolInfo(CandidateReason.MemberGroup, model2.GetSymbolInfo(argument2));
 
                verifySymbolInfo(CandidateReason.OverloadResolutionFailure, model.GetSpeculativeSymbolInfo(argument2.Position, argument2, SpeculativeBindingOption.BindAsExpression));
 
                Assert.True(model.GetSpeculativeSymbolInfo(argument2.Position, argument2, SpeculativeBindingOption.BindAsTypeOrNamespace).IsEmpty);
 
                void verifySymbolInfo(CandidateReason reason, SymbolInfo symbolInfo)
                {
                    Assert.Equal(reason, symbolInfo.CandidateReason);
                    AssertEx.SetEqual(
                        symbols.Select(s => s.GetPublicSymbol()),
                        symbolInfo.CandidateSymbols,
                        Roslyn.Utilities.ReferenceEqualityComparer.Instance);
                }
            }
 
            static ImmutableArray<InvocationExpressionSyntax> getNameOfCalls(SyntaxTree tree)
            {
                return tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>()
                    .Where(e => e.Expression is IdentifierNameSyntax { Identifier.ValueText: "nameof" })
                    .ToImmutableArray();
            }
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67565")]
        public void SymbolInfo_InstanceMemberFromStatic_Nested()
        {
            var source = """
                public class C
                {
                    public C1 Property { get; }
                    public C1 Field;
 
                    public static string StaticField =
                        nameof(Property.Property) +
                        nameof(Property.Field) +
                        nameof(Property.Event) +
                        nameof(Field.Property) +
                        nameof(Field.Field) +
                        nameof(Field.Event);
                }
                
                public class C1
                {
                    public int Property { get; }
                    public int Field;
                    public event System.Action Event;
                }
                """;
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var c1Property = comp.GetMember("C1.Property");
            var c1Field = comp.GetMember("C1.Field");
            var c1Event = comp.GetMember("C1.Event");
 
            var tree = comp.SyntaxTrees.Single();
            var tree2 = SyntaxFactory.ParseSyntaxTree(source + " ");
 
            var initializer = tree2.GetRoot().DescendantNodes().OfType<EqualsValueClauseSyntax>().Single();
 
            var nameofCalls = getNameOfCalls(tree);
            Assert.Equal(6, nameofCalls.Length);
            var nameofCalls2 = getNameOfCalls(tree2);
            Assert.Equal(6, nameofCalls2.Length);
 
            var model = comp.GetSemanticModel(tree);
 
            verify(0, "Property.Property", c1Property);
            verify(1, "Property.Field", c1Field);
            verify(2, "Property.Event", c1Event);
            verify(3, "Field.Property", c1Property);
            verify(4, "Field.Field", c1Field);
            verify(5, "Field.Event", c1Event);
 
            void verify(int index, string expression, Symbol symbol)
            {
                var argument = nameofCalls[index].ArgumentList.Arguments.Single().Expression;
                Assert.Equal(expression, argument.ToString());
 
                verifySymbolInfo(model.GetSymbolInfo(argument));
 
                var argument2 = nameofCalls2[index].ArgumentList.Arguments.Single().Expression;
                Assert.Equal(expression, argument2.ToString());
 
                Assert.True(model.TryGetSpeculativeSemanticModel(initializer.Position, initializer, out var model2));
 
                verifySymbolInfo(model2.GetSymbolInfo(argument2));
 
                verifySymbolInfo(model.GetSpeculativeSymbolInfo(argument2.Position, argument2, SpeculativeBindingOption.BindAsExpression));
 
                Assert.True(model.GetSpeculativeSymbolInfo(argument2.Position, argument2, SpeculativeBindingOption.BindAsTypeOrNamespace).IsEmpty);
 
                void verifySymbolInfo(SymbolInfo symbolInfo)
                {
                    Assert.NotNull(symbolInfo.Symbol);
                    Assert.Same(symbol.GetPublicSymbol(), symbolInfo.Symbol);
                }
            }
 
            static ImmutableArray<InvocationExpressionSyntax> getNameOfCalls(SyntaxTree tree)
            {
                return tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>()
                    .Where(e => e.Expression is IdentifierNameSyntax { Identifier.ValueText: "nameof" })
                    .ToImmutableArray();
            }
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67565")]
        public void SymbolInfo_InstanceMemberFromStatic_Nested_MethodGroup()
        {
            var source = """
                public class C
                {
                    public C1 Property { get; }
                    public C1 Field;
                    public event System.Action Event;
                
                    public static string StaticField =
                        nameof(Property.Method) +
                        nameof(Field.Method) +
                        nameof(Event.Invoke);
                }
                
                public class C1
                {
                    public void Method() { }
                    public void Method(int i) { }
                }
                """;
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var c1Methods = comp.GetMembers("C1.Method").ToArray();
            Assert.Equal(2, c1Methods.Length);
            var c1Event = comp.GetMember("C1.Event");
            var actionInvoke = comp.GetWellKnownType(WellKnownType.System_Action).GetMember("Invoke");
 
            var tree = comp.SyntaxTrees.Single();
            var tree2 = SyntaxFactory.ParseSyntaxTree(source + " ");
 
            var initializer = tree2.GetRoot().DescendantNodes().OfType<EqualsValueClauseSyntax>().Single();
 
            var nameofCalls = getNameOfCalls(tree);
            Assert.Equal(3, nameofCalls.Length);
            var nameofCalls2 = getNameOfCalls(tree2);
            Assert.Equal(3, nameofCalls2.Length);
 
            var model = comp.GetSemanticModel(tree);
 
            verify(0, "Property.Method", c1Methods);
            verify(1, "Field.Method", c1Methods);
            verify(2, "Event.Invoke", actionInvoke);
 
            void verify(int index, string expression, params Symbol[] symbols)
            {
                var argument = nameofCalls[index].ArgumentList.Arguments.Single().Expression;
                Assert.Equal(expression, argument.ToString());
 
                verifySymbolInfo(CandidateReason.MemberGroup, model.GetSymbolInfo(argument));
 
                var argument2 = nameofCalls2[index].ArgumentList.Arguments.Single().Expression;
                Assert.Equal(expression, argument2.ToString());
 
                Assert.True(model.TryGetSpeculativeSemanticModel(initializer.Position, initializer, out var model2));
 
                verifySymbolInfo(CandidateReason.MemberGroup, model2.GetSymbolInfo(argument2));
 
                verifySymbolInfo(CandidateReason.OverloadResolutionFailure, model.GetSpeculativeSymbolInfo(argument2.Position, argument2, SpeculativeBindingOption.BindAsExpression));
 
                Assert.True(model.GetSpeculativeSymbolInfo(argument2.Position, argument2, SpeculativeBindingOption.BindAsTypeOrNamespace).IsEmpty);
 
                void verifySymbolInfo(CandidateReason reason, SymbolInfo symbolInfo)
                {
                    Assert.Equal(reason, symbolInfo.CandidateReason);
                    AssertEx.SetEqual(
                        symbols.Select(s => s.GetPublicSymbol()),
                        symbolInfo.CandidateSymbols,
                        Roslyn.Utilities.ReferenceEqualityComparer.Instance);
                }
            }
 
            static ImmutableArray<InvocationExpressionSyntax> getNameOfCalls(SyntaxTree tree)
            {
                return tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>()
                    .Where(e => e.Expression is IdentifierNameSyntax { Identifier.ValueText: "nameof" })
                    .ToImmutableArray();
            }
        }
 
        [Fact]
        public void ExtensionMethodConstraintFailed()
        {
            var source =
@"public class A
{
}
public interface Interface
{
}
public static class B
{
    public static void Extension<T>(this T t) where T : Interface {}
}
public class Program
{
    public static void Main(string[] args)
    {
        A a = null;
        Use(nameof(a.Extension));
    }
    private static void Use(object o) {}
}
";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
            compilation.VerifyDiagnostics(
                // (16,22): error CS1061: 'A' does not contain a definition for 'Extension' and no accessible extension method 'Extension' accepting a first argument of type 'A' could be found (are you missing a using directive or an assembly reference?)
                //         Use(nameof(a.Extension));
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Extension").WithArguments("A", "Extension").WithLocation(16, 22)
                );
        }
 
        [Fact]
        public void StaticMemberFromType()
        {
            var source =
@"public class A
{
    public static int Field;
    public static int Property { get; }
    public static event System.Action Event;
    public class Type {}
}
public class Program
{
    public static void Main(string[] args)
    {
        Use(nameof(A.Field));
        Use(nameof(A.Property));
        Use(nameof(A.Event));
        Use(nameof(A.Type));
    }
    private static void Use(object o) {}
}";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
            compilation.VerifyDiagnostics();
        }
 
        [Fact]
        public void AllowImplicitThisInStaticContext()
        {
            var source =
@"
public class MyAttribute : System.Attribute
{
    public MyAttribute(string S) {}
}
 
[My(nameof(SS))] // attribute argument (NOTE: class members in scope here)
public class Program
{
    string SS;
    static string S1 = nameof(SS); // static initializer
    string S2 = nameof(SS); // instance initializer
    Program(string s) {}
    Program() : this(nameof(SS)) {} // ctor initializer
 
    static string L(string s = nameof(SS)) // default value
    {
        return nameof(SS); // in static method
    }
    public void M()
    {
        SS = SS + S1 + S2;
    }
}";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
            compilation.VerifyDiagnostics();
        }
 
        [Fact]
        public void NameofInaccessibleMethod()
        {
            var source =
@"
public class Class
{
    protected void Method() {}
}
public class Program
{
    public string S = nameof(Class.Method);
}";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
            compilation.VerifyDiagnostics(
                // (8,36): error CS0122: 'Class.Method()' is inaccessible due to its protection level
                //     public string S = nameof(Class.Method);
                Diagnostic(ErrorCode.ERR_BadAccess, "Method").WithArguments("Class.Method()").WithLocation(8, 36)
                );
        }
 
        [Fact]
        public void NameofAmbiguousProperty()
        {
            var source =
@"
public interface I1
{
    int Property { get; }
}
public interface I2
{
    int Property { get; }
}
public interface I3 : I1, I2 {}
public class Program
{
    public string S = nameof(I3.Property);
}";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
            compilation.VerifyDiagnostics(
                // (13,33): error CS0229: Ambiguity between 'I1.Property' and 'I2.Property'
                //     public string S = nameof(I3.Property);
                Diagnostic(ErrorCode.ERR_AmbigMember, "Property").WithArguments("I1.Property", "I2.Property").WithLocation(13, 33)
                );
        }
 
        [Fact]
        [WorkItem(1077150, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1077150")]
        public void SymbolInfoForMethodGroup06()
        {
            var source =
@"public class A
{
}
public static class X1
{
    public static string Extension(this A a) { return null; }
}
public class Program
{
    public static void Main(string[] args)
    {
        Use(nameof(X1.Extension));
    }
    private static void Use(object o) {}
}";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source);
            compilation.VerifyDiagnostics();
            var tree = compilation.SyntaxTrees[0];
            var model = compilation.GetSemanticModel(tree);
            var node = tree.GetRoot().DescendantNodes().Where(n => n.ToString() == "X1.Extension").OfType<ExpressionSyntax>().First();
            var symbolInfo = model.GetSymbolInfo(node, default(CancellationToken));
            Assert.Null(symbolInfo.Symbol);
            Assert.Equal(CandidateReason.MemberGroup, symbolInfo.CandidateReason);
            Assert.Equal(1, symbolInfo.CandidateSymbols.Length);
        }
 
        [Fact, WorkItem(40, "github.com/dotnet/roslyn")]
        public void ConstInitializerUsingSelf()
        {
            var source =
@"public class X
{
    const string N1 = nameof(N1);
    public static void Main()
    {
        const string N2 = nameof(N2);
        System.Console.WriteLine(N1 + N2);
    }
}";
            var compilation = CreateCompilationWithMscorlib461(source, options: TestOptions.DebugExe);
            var comp = CompileAndVerify(compilation, expectedOutput: @"N1N2");
        }
 
        [Fact, WorkItem(42, "github.com/dotnet/roslyn")]
        public void NameofTypeParameterInParameterInitializer()
        {
            var source =
@"class Test {
  void M<T>(
    T t = default(T), // ok
    string s = nameof(T) // ok
  ) { }
}";
            var compilation = CreateCompilationWithMscorlib461(source).VerifyDiagnostics();
        }
 
        [Fact, WorkItem(10467, "https://github.com/dotnet/roslyn/issues/10467")]
        public void NameofFixedBuffer()
        {
            var source =
@"
using System;
unsafe struct Struct1
{
    public fixed char MessageType[50];
 
    public override string ToString()
    {
        return nameof(MessageType);
    }
 
    public void DoSomething(out char[] x)
    {
        x = new char[] { };
        Action a = () => { System.Console.Write($"" {nameof(x)} ""); };
        a();
    }
 
    public static void Main()
    {
        Struct1 myStruct = default(Struct1);
        Console.Write(myStruct.ToString());
        char[] o;
        myStruct.DoSomething(out o);
        Console.Write(Other.GetFromExternal());
    }
}
 
class Other {
    public static string GetFromExternal() {
        Struct1 myStruct = default(Struct1);
        return nameof(myStruct.MessageType);
    }
}
";
            var compilation = CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeDebugExe);
            CompileAndVerify(compilation, expectedOutput:
                "MessageType x MessageType").VerifyDiagnostics();
        }
 
        [Fact, WorkItem(10467, "https://github.com/dotnet/roslyn/issues/10467")]
        public void NameofMethodFixedBuffer()
        {
            var source =
@"
using System;
 
unsafe struct Struct1
{
  public fixed char MessageType[50];
  public static string nameof(char[] mt)
  {
    return """";
  }
 
  public override string ToString()
  {
    return nameof(MessageType);
  }
 
  public void DoSomething(out char[] x)
  {
    x = new char[] {};
    Action a = () => { System.Console.WriteLine(nameof(x)); };
  }
 
  class Other {
    public static string GetFromExternal() {
        Struct1 myStruct = default(Struct1);
        return nameof(myStruct.MessageType);
    }
  }
}";
            var compilation = CreateCompilationWithMscorlib461(source, null,
                TestOptions.UnsafeDebugDll).VerifyDiagnostics(
                // (14,19): error CS1666: You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement.
                //     return nameof(MessageType);
                Diagnostic(ErrorCode.ERR_FixedBufferNotFixed, "MessageType").WithLocation(14, 19),
                // (20,29): error CS1628: Cannot use ref or out parameter 'x' inside an anonymous method, lambda expression, or query expression
                //     Action a = () => nameof(x);
                Diagnostic(ErrorCode.ERR_AnonDelegateCantUse, "x").WithArguments("x").WithLocation(20, 56),
                // (26,23): error CS1503: Argument 1: cannot convert from 'char*' to 'char[]'
                //         return nameof(myStruct.MessageType);
                Diagnostic(ErrorCode.ERR_BadArgType, "myStruct.MessageType").WithArguments("1", "char*", "char[]").WithLocation(26, 23));
        }
 
        [Fact, WorkItem(12696, "https://github.com/dotnet/roslyn/issues/12696")]
        public void FixedFieldAccessInsideNameOf()
        {
            var source =
@"
using System;
 
struct MyType
{
  public static string a = nameof(MyType.normalField);
  public static string b = nameof(MyType.fixedField);
  public static string c = nameof(fixedField);
 
  public int normalField;
  public unsafe fixed short fixedField[6];
 
  public MyType(int i) {
      this.normalField = i;
  }
}
 
class EntryPoint
{
    public static void Main(string[] args)
    {
        Console.Write(MyType.a + "" "");
        Console.Write(MyType.b + "" "");
        Console.Write(MyType.c);
    }
}
";
            var compilation = CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeDebugExe);
            CompileAndVerify(compilation, expectedOutput: "normalField fixedField fixedField").VerifyDiagnostics();
        }
 
        [Fact, WorkItem(12696, "https://github.com/dotnet/roslyn/issues/12696")]
        public void FixedFieldAccessFromInnerClass()
        {
            var source =
@"
using System;
 
public struct MyType
{
  public static class Inner
  {
     public static string a = nameof(normalField);
     public static string b = nameof(fixedField);
  }
 
  public int normalField;
  public unsafe fixed short fixedField[6];
}
 
class EntryPoint
{
    public static void Main(string[] args)
    {
        Console.Write(MyType.Inner.a + "" "");
        Console.Write(MyType.Inner.b);
    }
}
";
            var compilation = CreateCompilationWithMscorlib461(source, null, TestOptions.UnsafeDebugExe);
            CompileAndVerify(compilation, expectedOutput: "normalField fixedField").VerifyDiagnostics();
        }
 
        [Fact]
        public void PassingNameOfToInShouldCopy()
        {
            CompileAndVerify(@"
class Program
{
    public static void Main()
    {
        M(nameof(Main));
    }
    private static void M(in string value)
    {
        System.Console.WriteLine(value);
    }
}", expectedOutput: "Main");
        }
 
        [Fact, WorkItem(20600, "https://github.com/dotnet/roslyn/issues/20600")]
        public void PermitInstanceQualifiedFromType()
        {
            var source = @"
class Program
{
    static void Main()
    {
        new C().M();
        new C<int>().M();
        System.Console.WriteLine(""passed"");
    }
}
class C
{
    public string Instance1 = null;
    public static string Static1 = null;
    public string Instance2 => string.Empty;
    public static string Static2 => string.Empty;
      
    public void M()
    {
        nameof(C.Instance1).Verify(""Instance1"");
        nameof(C.Instance1.Length).Verify(""Length"");
        nameof(C.Static1).Verify(""Static1"");
        nameof(C.Static1.Length).Verify(""Length"");
        nameof(C.Instance2).Verify(""Instance2"");
        nameof(C.Instance2.Length).Verify(""Length"");
        nameof(C.Static2).Verify(""Static2"");
        nameof(C.Static2.Length).Verify(""Length"");
    }
}
class C<T>
{
    public string Instance1 = null;
    public static string Static1 = null;
    public string Instance2 => string.Empty;
    public static string Static2 => string.Empty;
 
    public void M()
    {
        nameof(C<string>.Instance1).Verify(""Instance1"");
        nameof(C<string>.Instance1.Length).Verify(""Length"");
        nameof(C<string>.Static1).Verify(""Static1"");
        nameof(C<string>.Static1.Length).Verify(""Length"");
        nameof(C<string>.Instance2).Verify(""Instance2"");
        nameof(C<string>.Instance2.Length).Verify(""Length"");
        nameof(C<string>.Static2).Verify(""Static2"");
        nameof(C<string>.Static2.Length).Verify(""Length"");
    }
}
public static class Extensions
{
    public static void Verify(this string actual, string expected)
    {
        if (expected != actual) throw new System.Exception($""expected={expected}; actual={actual}"");
    }
}
";
            var compilation = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics(
                );
            var comp = CompileAndVerify(compilation, expectedOutput: @"passed");
        }
 
        [Fact]
        public void TestDynamicWhenNotDefined()
        {
            var source = @"
class Program
{
    static string M() => nameof(dynamic);
}
";
            var option = TestOptions.ReleaseDll;
            CreateCompilation(source, options: option).VerifyDiagnostics(
                // (4,33): error CS0103: The name 'dynamic' does not exist in the current context
                //     static string M() => nameof(dynamic);
                Diagnostic(ErrorCode.ERR_NameNotInContext, "dynamic").WithArguments("dynamic").WithLocation(4, 33)
            );
        }
 
        [Fact]
        public void TestNintWhenDefined()
        {
            var source = @"
class Program
{
    static string M(object nint) => nameof(nint);
}
";
            var option = TestOptions.ReleaseDll;
            CreateCompilation(source, options: option).VerifyDiagnostics();
        }
 
        [Fact]
        public void TestDynamicWhenDefined()
        {
            var source = @"
class Program
{
    static string M(object dynamic) => nameof(dynamic);
}
";
            var option = TestOptions.ReleaseDll;
            CreateCompilation(source, options: option).VerifyDiagnostics();
        }
 
        [Fact]
        public void TestTypeArguments()
        {
            var source = @"
interface I<T> { }
class Program
{
    static string F1() => nameof(I<int>);
    static string F2() => nameof(I<nint>);
    static string F3() => nameof(I<dynamic>);
}";
            var option = TestOptions.ReleaseDll;
            CreateCompilation(source, options: option).VerifyDiagnostics();
        }
 
        [Fact]
        public void TestNameOfTypeOf()
        {
            var source = @"
class Program
{
    static string F1() => nameof(typeof(int));
    static string F2() => nameof(typeof(nint));
    static string F3() => nameof(typeof(dynamic));
}";
            var option = TestOptions.ReleaseDll;
            CreateCompilation(source, options: option).VerifyDiagnostics(
                // (4,34): error CS8081: Expression does not have a name.
                //     static string F1() => nameof(typeof(int));
                Diagnostic(ErrorCode.ERR_ExpressionHasNoName, "typeof(int)").WithLocation(4, 34),
                // (5,34): error CS8081: Expression does not have a name.
                //     static string F2() => nameof(typeof(nint));
                Diagnostic(ErrorCode.ERR_ExpressionHasNoName, "typeof(nint)").WithLocation(5, 34),
                // (6,34): error CS1962: The typeof operator cannot be used on the dynamic type
                //     static string F3() => nameof(typeof(dynamic));
                Diagnostic(ErrorCode.ERR_BadDynamicTypeof, "typeof(dynamic)").WithLocation(6, 34));
        }
 
        [Fact]
        public void TestNameOfNintWhenTheyAreIdentifierNames()
        {
            var source = @"
public class C 
{
    public string nint;
    public void nameof(string x)
    {
        nameof(nint);
    }
}";
            var option = TestOptions.ReleaseDll;
            CreateCompilation(source, options: option).VerifyDiagnostics();
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanReferenceInstanceMembersFromStaticMemberInNameof_Flat()
        {
            var source = @"
System.Console.Write(C.M());
public class C
{
    public object Property { get; }
    public object Field;
    public event System.Action Event;
    public void M2() { }
    public static string M() => nameof(Property)
        + "","" + nameof(Field)
        + "","" + nameof(Event)
        + "","" + nameof(M2)
        ;
}";
            var expectedOutput = "Property,Field,Event,M2";
 
            CompileAndVerify(source, parseOptions: TestOptions.Regular11, expectedOutput: expectedOutput).VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: expectedOutput).VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: expectedOutput).VerifyDiagnostics();
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanReferenceInstanceMembersFromStaticMemberInNameof_Nested()
        {
            var source = @"
System.Console.Write(C.M());
public class C
{
    public C1 Property { get; }
    public C1 Field;
    public event System.Action Event;
    public static string M() => nameof(Property.Property) 
        + "","" + nameof(Property.Field)
        + "","" + nameof(Property.Method)
        + "","" + nameof(Property.Event)
        + "","" + nameof(Field.Property) 
        + "","" + nameof(Field.Field)
        + "","" + nameof(Field.Method)
        + "","" + nameof(Field.Event)
        + "","" + nameof(Event.Invoke)
        ;
}
 
public class C1
{
    public int Property { get; }
    public int Field;
    public void Method(){}
    public event System.Action Event;
}";
            var expectedOutput = "Property,Field,Method,Event,Property,Field,Method,Event,Invoke";
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: expectedOutput).VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: expectedOutput).VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (8,40): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     public static string M() => nameof(Property.Property) 
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Property").WithArguments("instance member in 'nameof'", "12.0").WithLocation(8, 40),
                // (9,24): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         + "," + nameof(Property.Field)
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Property").WithArguments("instance member in 'nameof'", "12.0").WithLocation(9, 24),
                // (10,24): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         + "," + nameof(Property.Method)
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Property").WithArguments("instance member in 'nameof'", "12.0").WithLocation(10, 24),
                // (11,24): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         + "," + nameof(Property.Event)
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Property").WithArguments("instance member in 'nameof'", "12.0").WithLocation(11, 24),
                // (12,24): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         + "," + nameof(Field.Property) 
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Field").WithArguments("instance member in 'nameof'", "12.0").WithLocation(12, 24),
                // (13,24): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         + "," + nameof(Field.Field)
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Field").WithArguments("instance member in 'nameof'", "12.0").WithLocation(13, 24),
                // (14,24): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         + "," + nameof(Field.Method)
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Field").WithArguments("instance member in 'nameof'", "12.0").WithLocation(14, 24),
                // (15,24): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         + "," + nameof(Field.Event)
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Field").WithArguments("instance member in 'nameof'", "12.0").WithLocation(15, 24),
                // (16,24): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         + "," + nameof(Event.Invoke)
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Event").WithArguments("instance member in 'nameof'", "12.0").WithLocation(16, 24));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void InstanceFromStatic_Lambdas()
        {
            var source = """
                using System;
                Console.Write(C.Names());
                public class C
                {
                    public object Property { get; }
                    public object Field;
                    public event Action Event;
                    public void Method() { }
                    public static string Names()
                    {
                        var lambda1 = static () => nameof(Property);
                        var lambda2 = static (string f = nameof(Field)) => f;
                        var lambda3 = static () => nameof(Event.Invoke);
                        var lambda4 = static (string i = nameof(Event.Invoke)) => i;
                        return lambda1() + "," + lambda2() + "," + lambda3() + "," + lambda4();
                    }
                }
                """;
            var expectedOutput = "Property,Field,Invoke,Invoke";
 
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: expectedOutput).VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: expectedOutput).VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (12,40): error CS9058: Feature 'lambda optional parameters' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         var lambda2 = static (string f = nameof(Field)) => f;
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "=").WithArguments("lambda optional parameters", "12.0").WithLocation(12, 40),
                // (13,43): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         var lambda3 = static () => nameof(Event.Invoke);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Event").WithArguments("instance member in 'nameof'", "12.0").WithLocation(13, 43),
                // (14,40): error CS9058: Feature 'lambda optional parameters' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         var lambda4 = static (string i = nameof(Event.Invoke)) => i;
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "=").WithArguments("lambda optional parameters", "12.0").WithLocation(14, 40),
                // (14,49): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         var lambda4 = static (string i = nameof(Event.Invoke)) => i;
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Event").WithArguments("instance member in 'nameof'", "12.0").WithLocation(14, 49));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void InstanceFromStatic_LocalFunctions()
        {
            var source = """
                using System;
                Console.Write(C.Names());
                public class C
                {
                    public object Property { get; }
                    public object Field;
                    public event Action Event;
                    public void Method() { }
                    public static string Names()
                    {
                        static string local1() => nameof(Property);
                        static string local2(string f = nameof(Field)) => f;
                        static string local3() => nameof(Event.Invoke);
                        static string local4(string i = nameof(Event.Invoke)) => i;
                        return local1() + "," + local2() + "," + local3() + "," + local4();
                    }
                }
                """;
            var expectedOutput = "Property,Field,Invoke,Invoke";
 
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: expectedOutput).VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: expectedOutput).VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (13,42): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         static string local3() => nameof(Event.Invoke);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Event").WithArguments("instance member in 'nameof'", "12.0").WithLocation(13, 42),
                // (14,48): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         static string local4(string i = nameof(Event.Invoke)) => i;
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Event").WithArguments("instance member in 'nameof'", "12.0").WithLocation(14, 48));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanReferenceInstanceMembersFromFieldInitializerInNameof()
        {
            var source = @"
System.Console.Write(new C().S);
public class C
{
    public string S { get; } = nameof(S.Length);
}";
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: "Length").VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "Length").VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (5,39): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     public string S { get; } = nameof(S.Length);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "S").WithArguments("instance member in 'nameof'", "12.0").WithLocation(5, 39));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanReferenceInstanceMembersFromAttributeInNameof()
        {
            var source = @"
var p = new C().P; // 1
public class C
{
    [System.Obsolete(nameof(S.Length))]
    public int P { get; }
    public string S { get; }
}";
            var expectedDiagnostics = new[]
            {
                // (2,9): warning CS0618: 'C.P' is obsolete: 'Length'
                // var p = new C().P; // 1
                Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "new C().P").WithArguments("C.P", "Length").WithLocation(2, 9)
            };
            CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(expectedDiagnostics);
            CreateCompilation(source, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(expectedDiagnostics);
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (5,29): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     [System.Obsolete(nameof(S.Length))]
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "S").WithArguments("instance member in 'nameof'", "12.0").WithLocation(5, 29));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanReferenceInstanceMembersFromConstructorInitializersInNameof()
        {
            var source = @"
System.Console.WriteLine(new C().S);
public class C
{
    public C(string s){ S = s; }
    public C() : this(nameof(S.Length)){}
    public string S { get; }
}";
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: "Length").VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "Length").VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (6,30): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     public C() : this(nameof(S.Length)){}
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "S").WithArguments("instance member in 'nameof'", "12.0").WithLocation(6, 30));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanAccessStructInstancePropertyInLambdaInNameof()
        {
            var source = @"
using System;
 
string s = ""str"";
new S().M(ref s);
 
public struct S
{
    public string P { get; }
    public void M(ref string x)
    {
        Func<string> func = () => nameof(P.Length);
        Console.WriteLine(func());
    }
}";
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: "Length").VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "Length").VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (12,42): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         Func<string> func = () => nameof(P.Length);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "P").WithArguments("instance member in 'nameof'", "12.0").WithLocation(12, 42));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanReferenceStaticMembersFromInstanceMemberInNameof1()
        {
            var source = @"
System.Console.WriteLine(new C().M());
public class C
{
    public C Prop { get; }
    public static int StaticProp { get; }
    public string M() => nameof(Prop.StaticProp);
}";
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: "StaticProp").VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "StaticProp").VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (7,33): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     public string M() => nameof(Prop.StaticProp);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Prop.StaticProp").WithArguments("instance member in 'nameof'", "12.0").WithLocation(7, 33));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanReferenceStaticMembersFromInstanceMemberInNameof2()
        {
            var source = @"
System.Console.WriteLine(C.M());
public class C
{
    public C Prop { get; }
    public static int StaticProp { get; }
    public static string M() => nameof(Prop.StaticProp);
}";
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: "StaticProp").VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "StaticProp").VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (7,40): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     public static string M() => nameof(Prop.StaticProp);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Prop").WithArguments("instance member in 'nameof'", "12.0").WithLocation(7, 40),
                // (7,40): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     public static string M() => nameof(Prop.StaticProp);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Prop.StaticProp").WithArguments("instance member in 'nameof'", "12.0").WithLocation(7, 40));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanReferenceStaticMembersFromInstanceMemberInNameof3()
        {
            var source = @"
System.Console.WriteLine(C.M());
public class C
{
    public C Prop { get; }
    public static string M() => nameof(Prop.M);
}";
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: "M").VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "M").VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (6,40): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     public static string M() => nameof(Prop.M);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Prop").WithArguments("instance member in 'nameof'", "12.0").WithLocation(6, 40));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanReferenceStaticMembersFromInstanceMemberInNameof4()
        {
            var source = @"
System.Console.WriteLine(new C().M());
public class C
{
    public C Prop { get; }
    public static void StaticMethod(){}
    public string M() => nameof(Prop.StaticMethod);
}";
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: "StaticMethod").VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "StaticMethod").VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics();
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCannotReferenceInstanceMembersFromStaticMemberInNameofInCSharp11()
        {
            var source = @"
public class C
{
    public string S { get; }
    public static string M() => nameof(S.Length);
}";
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (5,40): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     public static string M() => nameof(S.Length);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "S").WithArguments("instance member in 'nameof'", "12.0").WithLocation(5, 40));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCannotReferenceInstanceMembersFromFieldInitializerInNameofInCSharp11()
        {
            var source = @"
public class C
{
    public string S { get; } = nameof(S.Length);
}";
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (4,39): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     public string S { get; } = nameof(S.Length);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "S").WithArguments("instance member in 'nameof'", "12.0").WithLocation(4, 39));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCannotReferenceInstanceMembersFromAttributeInNameofInCSharp11()
        {
            var source = @"
public class C
{
    [System.Obsolete(nameof(S.Length))]
    public int P { get; }
    public string S { get; }
}";
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (4,29): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     [System.Obsolete(nameof(S.Length))]
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "S").WithArguments("instance member in 'nameof'", "12.0").WithLocation(4, 29));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCannotReferenceInstanceMembersFromConstructorInitializersInNameofInCSharp11()
        {
            var source = @"
public class C
{
    public C(string s){}
    public C() : this(nameof(S.Length)){}
    public string S { get; }
}";
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (5,30): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     public C() : this(nameof(S.Length)){}
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "S").WithArguments("instance member in 'nameof'", "12.0").WithLocation(5, 30));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCannotAccessStructInstancePropertyInLambdaInNameofInCSharp11()
        {
            var source = @"
using System;
 
public struct S
{
    public string P { get; }
    public void M(ref string x)
    {
        Func<string> func = () => nameof(P.Length);
    }
}";
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (9,42): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //         Func<string> func = () => nameof(P.Length);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "P").WithArguments("instance member in 'nameof'", "12.0").WithLocation(9, 42));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCannotReferenceStaticPropertyFromInstanceMemberInNameofInCSharp11()
        {
            var source = @"
public class C
{
    public C Prop { get; }
    public static int StaticProp { get; }
    public string M() => nameof(Prop.StaticProp);
}";
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (6,33): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     public string M() => nameof(Prop.StaticProp);
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Prop.StaticProp").WithArguments("instance member in 'nameof'", "12.0").WithLocation(6, 33));
        }
 
        [Fact]
        public void TestCanReferenceStaticMethodFromInstanceMemberInNameofInCSharp11()
        {
            var source = @"
System.Console.WriteLine(new C().M());
public class C
{
    public C Prop { get; }
    public static void StaticMethod(){}
    public string M() => nameof(Prop.StaticMethod);
}";
            CompileAndVerify(source, parseOptions: TestOptions.Regular11, expectedOutput: "StaticMethod").VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "StaticMethod").VerifyDiagnostics();
        }
 
        [Fact]
        public void TestCanAccessRefParameterInLambdaInNameof()
        {
            var source = @"
using System;
 
string s = ""str"";
new S().M(ref s);
 
public struct S
{
    public void M(ref string x)
    {
        Func<string> func = () => nameof(x.Length);
        Console.WriteLine(func());
    }
}";
            CompileAndVerify(source, parseOptions: TestOptions.Regular11, expectedOutput: "Length").VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "Length").VerifyDiagnostics();
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanReferenceStaticMembersFromInstanceMemberInNameofUsedRecursivelyInAttributes1()
        {
            var source = @"
using System;
using System.Reflection;
Console.WriteLine(typeof(C).GetProperty(""Prop"").GetCustomAttribute<Attr>().S);
class C
{
    [Attr(nameof(Prop.StaticMethod))]
    public C Prop { get; }
    public static void StaticMethod(){}
}
class Attr : Attribute
{
    public readonly string S;
    public Attr(string s) { S = s; }
}";
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: "StaticMethod").VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "StaticMethod").VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (7,18): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     [Attr(nameof(Prop.StaticMethod))]
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Prop").WithArguments("instance member in 'nameof'", "12.0").WithLocation(7, 18));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanReferenceStaticMembersFromInstanceMemberInNameofUsedRecursivelyInAttributes2()
        {
            var source = @"
using System;
using System.Reflection;
Console.WriteLine(typeof(C).GetProperty(""Prop"").GetCustomAttribute<Attr>().S);
class C
{
    [Attr(nameof(Prop.Prop))]
    public static C Prop { get; }
}
class Attr : Attribute
{
    public readonly string S;
    public Attr(string s) { S = s; }
}";
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: "Prop").VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "Prop").VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (7,18): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                //     [Attr(nameof(Prop.Prop))]
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "Prop.Prop").WithArguments("instance member in 'nameof'", "12.0").WithLocation(7, 18));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestCanReferenceStaticMembersFromInstanceMemberInNameofUsedRecursivelyInAttributes3()
        {
            var source = @"
using System;
using System.Reflection;
Console.WriteLine(typeof(C).GetCustomAttribute<Attr>().S);
[Attr(nameof(C.Prop.Prop))]
class C
{
    public static C Prop { get; }
}
class Attr : Attribute
{
    public readonly string S;
    public Attr(string s) { S = s; }
}";
            CompileAndVerify(source, parseOptions: TestOptions.Regular12, expectedOutput: "Prop").VerifyDiagnostics();
            CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "Prop").VerifyDiagnostics();
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(
                // (5,14): error CS9058: Feature 'instance member in 'nameof'' is not available in C# 11.0. Please use language version 12.0 or greater.
                // [Attr(nameof(C.Prop.Prop))]
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion11, "C.Prop.Prop").WithArguments("instance member in 'nameof'", "12.0").WithLocation(5, 14));
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestInvalidRecursiveUsageOfNameofInAttributesDoesNotCrashCompiler1()
        {
            var source = @"
class C
{
    [Attr(nameof(Method().Method))]
    T Method<T>() where T : C => default;
}
class Attr : System.Attribute { public Attr(string s) {} }";
            var expectedDiagnostics = new[]
            {
                // (4,18): error CS0411: The type arguments for method 'C.Method<T>()' cannot be inferred from the usage. Try specifying the type arguments explicitly.
                //     [Attr(nameof(Method().Method))]
                Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Method").WithArguments("C.Method<T>()").WithLocation(4, 18)
            };
            CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(expectedDiagnostics);
            CreateCompilation(source, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(expectedDiagnostics);
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(expectedDiagnostics);
        }
 
        [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")]
        public void TestInvalidRecursiveUsageOfNameofInAttributesDoesNotCrashCompiler2()
        {
            var source = @"
class C
{
    [Attr(nameof(Method<C>().Method))]
    T Method<T>() where T : C => default;
}
class Attr : System.Attribute { public Attr(string s) {} }";
            var expectedDiagnostics = new[]
            {
                // (4,18): error CS8082: Sub-expression cannot be used in an argument to nameof.
                //     [Attr(nameof(Method<C>().Method))]
                Diagnostic(ErrorCode.ERR_SubexpressionNotInNameof, "Method<C>()").WithLocation(4, 18)
            };
            CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(expectedDiagnostics);
            CreateCompilation(source, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(expectedDiagnostics);
            CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(expectedDiagnostics);
        }
 
        [Fact]
        public void OpenTypeInNameof_Preview()
        {
            CompileAndVerify("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(List<>);
                Console.WriteLine(v);
                """, expectedOutput: "List").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_CSharp13()
        {
            CreateCompilation("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(List<>);
                Console.WriteLine(v);
                """, parseOptions: TestOptions.Regular13).VerifyDiagnostics(
                    // (4,16): error CS8652: The feature 'unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                    // var v = nameof(List<>);
                    Diagnostic(ErrorCode.ERR_FeatureInPreview, "List<>").WithArguments("unbound generic types in nameof operator").WithLocation(4, 16));
        }
 
        [Fact]
        public void OpenTypeInNameof_Next()
        {
            CompileAndVerify("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(List<>);
                Console.WriteLine(v);
                """, parseOptions: TestOptions.RegularNext, expectedOutput: "List").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_CSharp13_Nested1()
        {
            CreateCompilation("""
                using System;
                
                var v = nameof(A<>.B<int>);
                Console.WriteLine(v);
 
                class A<X> { public class B<Y>; }
                """, parseOptions: TestOptions.Regular13).VerifyDiagnostics(
                // (3,16): error CS8652: The feature 'unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                // var v = nameof(A<>.B<int>);
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "A<>").WithArguments("unbound generic types in nameof operator").WithLocation(3, 16));
        }
 
        [Fact]
        public void OpenTypeInNameof_CSharp13_Nested2()
        {
            CreateCompilation("""
                using System;
                
                var v = nameof(A<int>.B<>);
                Console.WriteLine(v);
 
                class A<X> { public class B<Y>; }
                """, parseOptions: TestOptions.Regular13).VerifyDiagnostics(
                // (3,23): error CS8652: The feature 'unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                // var v = nameof(A<int>.B<>);
                Diagnostic(ErrorCode.ERR_FeatureInPreview, "B<>").WithArguments("unbound generic types in nameof operator").WithLocation(3, 23));
        }
 
        [Fact]
        public void OpenTypeInNameof_CSharp13_Nested3()
        {
            CreateCompilation("""
                using System;
                
                var v = nameof(A<>.B<>);
                Console.WriteLine(v);
 
                class A<X> { public class B<Y>; }
                """, parseOptions: TestOptions.Regular13).VerifyDiagnostics(
                    // (3,16): error CS8652: The feature 'unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                    // var v = nameof(A<>.B<>);
                    Diagnostic(ErrorCode.ERR_FeatureInPreview, "A<>").WithArguments("unbound generic types in nameof operator").WithLocation(3, 16),
                    // (3,20): error CS8652: The feature 'unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.
                    // var v = nameof(A<>.B<>);
                    Diagnostic(ErrorCode.ERR_FeatureInPreview, "B<>").WithArguments("unbound generic types in nameof operator").WithLocation(3, 20));
        }
 
        [Fact]
        public void OpenTypeInNameof_BaseCase()
        {
            CompileAndVerify("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(List<>);
                Console.WriteLine(v);
                """, expectedOutput: "List").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_Nested1()
        {
            CompileAndVerify("""
                using System;
                    
                var v = nameof(A<>.B<int>);
                Console.WriteLine(v);
 
                class A<X> { public class B<Y>; }
                """, expectedOutput: "B").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_Nested2()
        {
            CompileAndVerify("""
                using System;
                    
                var v = nameof(A<int>.B<>);
                Console.WriteLine(v);
 
                class A<X> { public class B<Y>; }
                """, expectedOutput: "B").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_Nested3()
        {
            CompileAndVerify("""
                using System;
                    
                var v = nameof(A<>.B<>);
                Console.WriteLine(v);
 
                class A<X> { public class B<Y>; }
                """, expectedOutput: "B").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_MultipleTypeArguments()
        {
            CompileAndVerify("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(Dictionary<,>);
                Console.WriteLine(v);
                """, expectedOutput: "Dictionary").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_IncorrectTypeArgumentCount1()
        {
            CreateCompilation("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(Dictionary<>);
                Console.WriteLine(v);
                """).VerifyDiagnostics(
                    // (2,1): hidden CS8019: Unnecessary using directive.
                    // using System.Collections.Generic;
                    Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using System.Collections.Generic;").WithLocation(2, 1),
                    // (4,16): error CS0305: Using the generic type 'Dictionary<TKey, TValue>' requires 2 type arguments
                    // var v = nameof(Dictionary<>);
                    Diagnostic(ErrorCode.ERR_BadArity, "Dictionary<>").WithArguments("System.Collections.Generic.Dictionary<TKey, TValue>", "type", "2").WithLocation(4, 16));
        }
 
        [Fact]
        public void OpenTypeInNameof_IncorrectTypeArgumentCount2()
        {
            CreateCompilation("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(List<,>);
                Console.WriteLine(v);
                """).VerifyDiagnostics(
                // (2,1): hidden CS8019: Unnecessary using directive.
                // using System.Collections.Generic;
                Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using System.Collections.Generic;").WithLocation(2, 1),
                // (4,16): error CS0305: Using the generic type 'List<T>' requires 1 type arguments
                // var v = nameof(List<,>);
                Diagnostic(ErrorCode.ERR_BadArity, "List<,>").WithArguments("System.Collections.Generic.List<T>", "type", "1").WithLocation(4, 16));
        }
 
        [Fact]
        public void OpenTypeInNameof_NoNestedOpenTypes1()
        {
            CreateCompilation("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(List<List<>>);
                Console.WriteLine(v);
                """).VerifyDiagnostics(
                    // (4,21): error CS7003: Unexpected use of an unbound generic name
                    // var v = nameof(List<List<>>);
                    Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(4, 21));
        }
 
        [Fact]
        public void OpenTypeInNameof_NoNestedOpenTypes2()
        {
            CreateCompilation("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(List<List<>[]>);
                Console.WriteLine(v);
                """).VerifyDiagnostics(
                    // (4,21): error CS7003: Unexpected use of an unbound generic name
                    // var v = nameof(List<List<>>);
                    Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(4, 21));
        }
 
        [Fact]
        public void OpenTypeInNameof_NoNestedOpenTypes3()
        {
            CreateCompilation("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(List<Outer<>.Inner>);
                Console.WriteLine(v);
                
                public class Outer<T> { public class Inner { } }
                """).VerifyDiagnostics(
                    // (4,21): error CS7003: Unexpected use of an unbound generic name
                    // var v = nameof(List<Outer<>.Inner>);
                    Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "Outer<>").WithLocation(4, 21));
        }
 
        [Fact]
        public void OpenTypeInNameof_NoNestedOpenTypes4()
        {
            CreateCompilation("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(List<Outer.Inner<>>);
                Console.WriteLine(v);
                
                public class Outer { public class Inner<T> { } }
                """).VerifyDiagnostics(
                    // (4,27): error CS7003: Unexpected use of an unbound generic name
                    // var v = nameof(List<Outer.Inner<>>);
                    Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "Inner<>").WithLocation(4, 27));
        }
 
        [Fact]
        public void Nameof_NestedClosedType1()
        {
            CompileAndVerify("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(List<List<int>>);
                Console.WriteLine(v);
                """, expectedOutput: "List").VerifyDiagnostics();
        }
 
        [Fact]
        public void Nameof_NestedClosedType2()
        {
            CompileAndVerify("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(List<List<int>[]>);
                Console.WriteLine(v);
                """, expectedOutput: "List").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_NoPartialOpenTypes_1()
        {
            CreateCompilation("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(Dictionary<,int>);
                Console.WriteLine(v);
                """).VerifyDiagnostics(
                    // (4,27): error CS1031: Type expected
                    // var v = nameof(Dictionary<,int>);
                    Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(4, 27));
        }
 
        [Fact]
        public void OpenTypeInNameof_NoPartialOpenTypes_2()
        {
            CreateCompilation("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(Dictionary<int,>);
                Console.WriteLine(v);
                """).VerifyDiagnostics(
                // (4,31): error CS1031: Type expected
                // var v = nameof(Dictionary<int,>);
                Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(4, 31));
        }
 
        [Fact]
        public void OpenTypeInNameof_MemberAccessThatDoesNotUseTypeArgument()
        {
            CompileAndVerify("""
                using System;
                using System.Collections.Generic;
 
                var v = nameof(List<>.Count);
                Console.WriteLine(v);
                """, expectedOutput: "Count").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument()
        {
            CompileAndVerify("""
                using System;
                    
                var v = nameof(IGoo<>.Count);
                Console.WriteLine(v);
 
                interface IGoo<T>
                {
                    T Count { get; }
                }
                """, expectedOutput: "Count").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceObjectMember()
        {
            CompileAndVerify("""
                using System;
                    
                var v = nameof(IGoo<>.Count.ToString);
                Console.WriteLine(v);
 
                interface IGoo<T>
                {
                    T Count { get; }
                }
                """, expectedOutput: "ToString").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstraintMember_Interface()
        {
            CompileAndVerify("""
                using System;
                    
                var v = nameof(IGoo<>.X.CompareTo);
                Console.WriteLine(v);
 
                interface IGoo<T> where T : IComparable<T>
                {
                    T X { get; }
                }
                """, expectedOutput: "CompareTo").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstraintMember_ThroughTypeParameter()
        {
            CompileAndVerify("""
                using System;
                    
                var v = nameof(IGoo<,>.X.CompareTo);
                Console.WriteLine(v);
 
                interface IGoo<T,U> where T : U where U : IComparable<T>
                {
                    T X { get; }
                }
                """, expectedOutput: "CompareTo").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstraintMember_Class()
        {
            CompileAndVerify("""
                using System;
                    
                var v = nameof(IGoo<>.X.Z);
                Console.WriteLine(v);
 
                class Base
                {
                    public int Z { get; }
                }
 
                interface IGoo<T> where T : Base
                {
                    T X { get; }
                }
                """, expectedOutput: "Z").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_GenericMethod1()
        {
            CompileAndVerify("""
                using System;
                    
                var v = nameof(IGoo.M);
                Console.WriteLine(v);
 
                interface IGoo
                {
                    void M<T>();
                }
                """, expectedOutput: "M").VerifyDiagnostics();
        }
 
        [Fact]
        public void OpenTypeInNameof_GenericMethod2()
        {
            CreateCompilation("""
                using System;
                    
                var v = nameof(IGoo.M<>);
                Console.WriteLine(v);
 
                interface IGoo
                {
                    void M<T>();
                }
                """).VerifyDiagnostics(
                    // (3,16): error CS0305: Using the generic method group 'M' requires 1 type arguments
                    // var v = nameof(IGoo.M<>);
                    Diagnostic(ErrorCode.ERR_BadArity, "IGoo.M<>").WithArguments("M", "method group", "1").WithLocation(3, 16));
        }
 
        [Fact]
        public void OpenTypeInNameof_GenericMethod3()
        {
            CreateCompilation("""
                using System;
                    
                var v = nameof(IGoo.M<int>);
                Console.WriteLine(v);
 
                interface IGoo
                {
                    void M<T>();
                }
                """).VerifyDiagnostics(
                // (3,16): error CS8084: Type parameters are not allowed on a method group as an argument to 'nameof'.
                // var v = nameof(IGoo.M<int>);
                Diagnostic(ErrorCode.ERR_NameofMethodGroupWithTypeParameters, "IGoo.M<int>").WithLocation(3, 16));
        }
 
        [Fact]
        public void NameofFunctionPointer1()
        {
            CreateCompilation("""
                class C
                {
                    unsafe void M()
                    {
                        var v = nameof(delegate*<int>);
                    }
                }
                """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
                // (5,32): error CS1514: { expected
                //         var v = nameof(delegate*<int>);
                Diagnostic(ErrorCode.ERR_LbraceExpected, "*").WithLocation(5, 32),
                // (5,32): warning CS8848: Operator '*' cannot be used here due to precedence. Use parentheses to disambiguate.
                //         var v = nameof(delegate*<int>);
                Diagnostic(ErrorCode.WRN_PrecedenceInversion, "*").WithArguments("*").WithLocation(5, 32),
                // (5,33): error CS1525: Invalid expression term '<'
                //         var v = nameof(delegate*<int>);
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "<").WithArguments("<").WithLocation(5, 33),
                // (5,34): error CS1525: Invalid expression term 'int'
                //         var v = nameof(delegate*<int>);
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(5, 34),
                // (5,38): error CS1525: Invalid expression term ')'
                //         var v = nameof(delegate*<int>);
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(5, 38));
        }
 
        [Fact]
        public void NameofFunctionPointer2()
        {
            CreateCompilation("""
                using System.Collections.Generic;
                    
                class C
                {
                    unsafe void M()
                    {
                        var v = nameof(delegate*<List<>>);
                    }
                }
                """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
                // (7,32): error CS1514: { expected
                //         var v = nameof(delegate*<List<>>);
                Diagnostic(ErrorCode.ERR_LbraceExpected, "*").WithLocation(7, 32),
                // (7,32): warning CS8848: Operator '*' cannot be used here due to precedence. Use parentheses to disambiguate.
                //         var v = nameof(delegate*<List<>>);
                Diagnostic(ErrorCode.WRN_PrecedenceInversion, "*").WithArguments("*").WithLocation(7, 32),
                // (7,33): error CS1525: Invalid expression term '<'
                //         var v = nameof(delegate*<List<>>);
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "<").WithArguments("<").WithLocation(7, 33),
                // (7,34): error CS0119: 'List<T>' is a type, which is not valid in the given context
                //         var v = nameof(delegate*<List<>>);
                Diagnostic(ErrorCode.ERR_BadSKunknown, "List<>").WithArguments("System.Collections.Generic.List<T>", "type").WithLocation(7, 34),
                // (7,41): error CS1525: Invalid expression term ')'
                //         var v = nameof(delegate*<List<>>);
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(7, 41));
        }
 
        [Fact]
        public void NameofFunctionPointer3()
        {
            CreateCompilation("""
                using System.Collections.Generic;
                    
                class C
                {
                    unsafe void M()
                    {
                        var v = nameof(List<delegate*<int>>);
                    }
                }
                """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
                // (7,13): warning CS0219: The variable 'v' is assigned but its value is never used
                //         var v = nameof(List<delegate*<int>>);
                Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "v").WithArguments("v").WithLocation(7, 13),
                // (7,29): error CS0306: The type 'delegate*<int>' may not be used as a type argument
                //         var v = nameof(List<delegate*<int>>);
                Diagnostic(ErrorCode.ERR_BadTypeArgument, "delegate*<int>").WithArguments("delegate*<int>").WithLocation(7, 29));
        }
 
        [Fact]
        public void NameofFunctionPointer4()
        {
            CreateCompilation("""
                using System.Collections.Generic;
                    
                class C
                {
                    unsafe void M()
                    {
                        var v = nameof(List<delegate*<List<>>>);
                    }
                }
                """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
                // (7,13): warning CS0219: The variable 'v' is assigned but its value is never used
                //         var v = nameof(List<delegate*<List<>>>);
                Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "v").WithArguments("v").WithLocation(7, 13),
                // (7,29): error CS0306: The type 'delegate*<List<T>>' may not be used as a type argument
                //         var v = nameof(List<delegate*<List<>>>);
                Diagnostic(ErrorCode.ERR_BadTypeArgument, "delegate*<List<>>").WithArguments("delegate*<System.Collections.Generic.List<T>>").WithLocation(7, 29),
                // (7,39): error CS7003: Unexpected use of an unbound generic name
                //         var v = nameof(List<delegate*<List<>>>);
                Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(7, 39));
        }
 
        [Fact]
        public void NameofFunctionPointer5()
        {
            CreateCompilation("""
                using System.Collections.Generic;
                
                class D<A, B, C>
                {
                    unsafe void M()
                    {
                        var v = nameof(D<, delegate*<int>, List<>>);
                    }
                }
                """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
                // (7,26): error CS1031: Type expected
                //         var v = nameof(D<, delegate*<int>, List<>>);
                Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(7, 26),
                // (7,44): error CS7003: Unexpected use of an unbound generic name
                //         var v = nameof(D<, delegate*<int>, List<>>);
                Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(7, 44));
        }
 
        [Fact]
        public void Nameof_NestedOpenType1()
        {
            CompileAndVerify("""
                using System;
                using System.Collections.Generic;
                    
                var v = nameof(List<List<int>[]>);
                Console.WriteLine(v);
                """, expectedOutput: "List").VerifyDiagnostics();
        }
 
        [Fact]
        public void Nameof_NestedOpenType2()
        {
            CreateCompilation("""
                using System;
                using System.Collections.Generic;
                    
                var v = nameof(List<List<>[]>);
                Console.WriteLine(v);
                """).VerifyDiagnostics(
                // (4,21): error CS7003: Unexpected use of an unbound generic name
                // var v = nameof(List<List<>[]>);
                Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(4, 21));
        }
 
        [Fact]
        public void Nameof_NestedOpenType3()
        {
            CompileAndVerify("""
                #nullable enable
                using System;
                using System.Collections.Generic;
                    
                var v = nameof(List<List<int>?>);
                Console.WriteLine(v);
                """, expectedOutput: "List").VerifyDiagnostics();
        }
 
        [Fact]
        public void Nameof_NestedOpenType4()
        {
            CreateCompilation("""
                #nullable enable
                using System;
                using System.Collections.Generic;
                    
                var v = nameof(List<List<>?>);
                Console.WriteLine(v);
                """).VerifyDiagnostics(
                // (5,21): error CS7003: Unexpected use of an unbound generic name
                // var v = nameof(List<List<>?>);
                Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(5, 21));
        }
 
        [Fact]
        public void Nameof_AliasQualifiedName()
        {
            CompileAndVerify("""
                using System;
                    
                var v = nameof(global::System.Collections.Generic.List<>);
                Console.WriteLine(v);
                """, expectedOutput: "List").VerifyDiagnostics();
        }
 
        [Theory]
        [InlineData("IGoo<>")]
        [InlineData("IGoo<>.Count")]
        public void OpenTypeInNameof_SemanticModelTest1(string nameofTypeString)
        {
            var compilation = CreateCompilation($$"""
                using System;
                    
                var v1 = nameof({{nameofTypeString}});
                var v2 = typeof(IGoo<>);
                Console.WriteLine(v1 + v2);
 
                interface IGoo<T> { public T Count { get; } }
                """).VerifyDiagnostics();
            var tree = compilation.SyntaxTrees.Single();
            var semanticModel = compilation.GetSemanticModel(tree);
 
            var root = tree.GetRoot();
 
            var firstGeneric = root.DescendantNodes().OfType<GenericNameSyntax>().First();
            var lastGeneric = root.DescendantNodes().OfType<GenericNameSyntax>().Last();
 
            Assert.NotSame(firstGeneric, lastGeneric);
 
            // Ensure the type inside the nameof is the same as the type inside the typeof.
            var nameofType = semanticModel.GetTypeInfo(firstGeneric).Type;
            var typeofType = semanticModel.GetTypeInfo(lastGeneric).Type;
 
            Assert.NotNull(nameofType);
            Assert.NotNull(typeofType);
 
            // typeof will produce IGoo<>, while nameof will produce IGoo<T>.  These are distinctly different types (the
            // latter has members for example).
            Assert.NotEqual(nameofType, typeofType);
 
            Assert.True(nameofType.IsDefinition);
            Assert.False(nameofType.IsUnboundGenericType());
 
            Assert.False(typeofType.IsDefinition);
            Assert.True(typeofType.IsUnboundGenericType());
 
            Assert.Empty(typeofType.GetMembers("Count"));
            Assert.Single(nameofType.GetMembers("Count"));
 
            var igooType = compilation.GetTypeByMetadataName("IGoo`1").GetPublicSymbol();
            Assert.NotNull(igooType);
 
            Assert.Equal(igooType, nameofType);
        }
    }
}