通过 SyntaxFactory (Roslyn) 构造 NameOf 表达式
Constructing NameOf expression via SyntaxFactory (Roslyn)
正在尝试使用 C# SyntaxFactory
从头开始构造 nameof
表达式。 Roslyn 无法将我的 InvocationExpressionSyntax
识别为上下文 nameof
关键字,并在 Emit
命令上抛出错误诊断。
尝试为 Roslyn 提供有效代码进行解析,希望我能找到我的语法结构与 "correctly parsed one" 之间的差异。我能够追踪到 "nameof" 标识符令牌的差异,但这就是我被卡住的地方。我找不到我的 nameof
令牌和解析的令牌之间的任何区别,但它们仍然有些不同。
当我使用 "parsed one" 时,一切正常,Emit
按预期工作,没有错误。另一方面,当我使用自己的 nameof
令牌时,它无法编译并且 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());
任何人都可以指出解析的令牌和我的令牌之间的任何区别,这导致 Roslyn 无法(正确地)将 nameof
表达式绑定到任何 "in-code" 符号,但是不将其视为上下文关键字?
编译错误: (1,30):错误 CS0103:名称 'nameof' 在当前上下文中不存在
编译#LanguageVersion: CSharp7
Roslyn 版本:(Nuget 最新)Microsoft.CodeAnalysis.CSharp v2.3.2
如果您查看 Identifier
的非私有成员,您会发现有 属性 RawContextualKind
。当您从代码中解析 nameof
时,您将获得这种上下文类型:
但是如果你用 SyntaxFactory.IdentifierName("nameof")
创建标识符,你会得到这个:
在第二种情况下,nameof
被视为普通标识符,这就是您收到错误的原因。您应该使用 SyntaxFactory.Identifier()
重载,它允许您指定上下文类型:
SyntaxFactory.IdentifierName(
SyntaxFactory.Identifier(
SyntaxFactory.TriviaList(),
SyntaxKind.NameOfKeyword,
"nameof",
"nameof",
SyntaxFactory.TriviaList()))
正在尝试使用 C# SyntaxFactory
从头开始构造 nameof
表达式。 Roslyn 无法将我的 InvocationExpressionSyntax
识别为上下文 nameof
关键字,并在 Emit
命令上抛出错误诊断。
尝试为 Roslyn 提供有效代码进行解析,希望我能找到我的语法结构与 "correctly parsed one" 之间的差异。我能够追踪到 "nameof" 标识符令牌的差异,但这就是我被卡住的地方。我找不到我的 nameof
令牌和解析的令牌之间的任何区别,但它们仍然有些不同。
当我使用 "parsed one" 时,一切正常,Emit
按预期工作,没有错误。另一方面,当我使用自己的 nameof
令牌时,它无法编译并且 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());
任何人都可以指出解析的令牌和我的令牌之间的任何区别,这导致 Roslyn 无法(正确地)将 nameof
表达式绑定到任何 "in-code" 符号,但是不将其视为上下文关键字?
编译错误: (1,30):错误 CS0103:名称 'nameof' 在当前上下文中不存在
编译#LanguageVersion: CSharp7
Roslyn 版本:(Nuget 最新)Microsoft.CodeAnalysis.CSharp v2.3.2
如果您查看 Identifier
的非私有成员,您会发现有 属性 RawContextualKind
。当您从代码中解析 nameof
时,您将获得这种上下文类型:
但是如果你用 SyntaxFactory.IdentifierName("nameof")
创建标识符,你会得到这个:
在第二种情况下,nameof
被视为普通标识符,这就是您收到错误的原因。您应该使用 SyntaxFactory.Identifier()
重载,它允许您指定上下文类型:
SyntaxFactory.IdentifierName(
SyntaxFactory.Identifier(
SyntaxFactory.TriviaList(),
SyntaxKind.NameOfKeyword,
"nameof",
"nameof",
SyntaxFactory.TriviaList()))