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
If you look into non-private members of
Identifieryou will see that there is propertyRawContextualKind. When you are parsingnameoffrom code, you will get this contextual kind:But if you create identifier with
SyntaxFactory.IdentifierName("nameof")you get this:In second case,
nameofis treated as normal identifier and that is why you receive an error. You should useSyntaxFactory.Identifier()overload which allows you to specify a contextual kind: