尝试使用C#nameof
从头开始构建SyntaxFactory
表达式。 Roslyn无法将我的InvocationExpressionSyntax
识别为上下文nameof
关键字,并在Emit
命令上引发错误诊断。
试图给Roslyn提供有效的代码以进行解析,希望我能发现我的语法构造与“正确解析的”语法之间的差异。我能够追踪到“nameof”标识符 token 之间的差异,但这就是我遇到的问题。我找不到nameof
token 和已解析的 token 之间的任何区别,但是它们仍然有所不同。
当我使用“已解析的代码”时,一切正常,并且Emit
正常工作,没有错误。另一方面,当我使用自己的nameof
token 时,它无法编译,并且Emit
引发错误诊断。
我在以下代码上对其进行测试的代码:
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());
谁能指出解析的 token 和我的 token 之间的任何差异,这导致Roslyn(正确)无法将
nameof
表达式绑定(bind)到任何“代码内”符号,但不能将其视为上下文关键字吗?编译错误:(1,30):错误CS0103:名称'nameof'在当前上下文中不存在
编译#语言版本: CSharp7
Roslyn版本:(最新Nuget)Microsoft.CodeAnalysis.CSharp v2.3.2
最佳答案
如果查看Identifier
的非私有(private)成员,您将看到存在RawContextualKind
属性。当您从代码中解析nameof
时,您将获得以下上下文类型:
但是,如果您使用SyntaxFactory.IdentifierName("nameof")
创建标识符,则会得到以下信息:
在第二种情况下,nameof
被视为普通标识符,这就是为什么您收到错误的原因。您应该使用SyntaxFactory.Identifier()
重载,它允许您指定上下文类型:
SyntaxFactory.IdentifierName(
SyntaxFactory.Identifier(
SyntaxFactory.TriviaList(),
SyntaxKind.NameOfKeyword,
"nameof",
"nameof",
SyntaxFactory.TriviaList()))