通过 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()))