Constructing NameOf expression via SyntaxFactory (Roslyn)

Viewed 598

Trying to construct nameof expression from scratch using C# SyntaxFactory. Roslyn fails to recognize my InvocationExpressionSyntax as a contextual nameof keyword and throws error diagnostics upon Emit command.

Tried to give Roslyn valid code to parse in hope that I'll find differences between my syntax construct and the "correctly parsed one". I was able to track the difference down to "nameof" identifier token, but that's where I got stuck. I can't find any difference between my nameof token and the parsed one, yet they are still somehow different.

When I use the "parsed one" everything works and Emit works as expected, without errors. On the other hand, when I use my own nameof token, it fails to compile and Emit throws error diagnostics.

Code I was testing it on:

var CODE = "class X { void Q() { var q = nameof(Q); } }";

var correctSyntaxTree = CSharpSyntaxTree.ParseText(CODE);
var correctRoot = correctSyntaxTree.GetRoot();
var correctNameOf = correctRoot.DescendantNodes().OfType<InvocationExpressionSyntax>().First();

var correctExpression = (IdentifierNameSyntax)correctNameOf.Expression;

var myNameOf = SyntaxFactory.InvocationExpression (
    correctExpression, //Works
    //SyntaxFactory.IdentifierName("nameof"), //Doesn't work
    //SyntaxFactory.IdentifierName(SyntaxFactory.Token(SyntaxKind.NameOfKeyword)), //System.ArgumentException: 'identifier'

    //SyntaxFactory.IdentifierName(correctExpression.Identifier), //Works
    //SyntaxFactory.IdentifierName(correctExpression.Identifier.ValueText), //Doesn't work

    //correctExpression.WithIdentifier(SyntaxFactory.Identifier("nameof")), //Doesn't work
    //correctExpression.WithIdentifier(SyntaxFactory.Identifier(correctExpression.Identifier.ValueText)), //Doesn't work

    //SyntaxFactory.IdentifierName("nameof").WithTriviaFrom(correctExpression), //Doesn't work
    //correctExpression.CopyAnnotationsTo(SyntaxFactory.IdentifierName("nameof")), //Doesn't work
    //SyntaxFactory.IdentifierName(correctExpression.Identifier.WithoutAnnotations().WithoutTrivia()), //Works

    SyntaxFactory.ArgumentList (
        SyntaxFactory.SingletonSeparatedList (
            SyntaxFactory.Argument (
                SyntaxFactory.IdentifierName("Q")
            )
        )
    )
);

var newRoot = correctRoot.ReplaceNode(correctNameOf, myNameOf);
var newTree = CSharpSyntaxTree.Create((CSharpSyntaxNode)newRoot);

var compilation = CSharpCompilation.Create (
    "Compilation",
    new[] { newTree },
    references: MsCorLib,
    options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
);

var compilationResult = compilation.Emit(new MemoryStream());

Could anyone point out any difference between the parsed token and my token, which is causing the Roslyn to (correctly) not be able to bind the nameof expression to any "in-code" symbol, yet not treat it as contextual keyword?

Compilation error: (1,30): error CS0103: The name 'nameof' does not exist in the current context

Compilation#LanguageVersion: CSharp7

Roslyn version: (Nuget newest) Microsoft.CodeAnalysis.CSharp v2.3.2

1 Answers
Related