在 Roslyn 中解析 nameof 表达式

Parsing nameof expressions in Roslyn

我试图用 CSharpSyntaxWalker 中的 nameof 表达式做一些事情,但是,我注意到 AST 中没有 NameOfExpressionSyntax。相反,我得到一个 InvocationExpressionSyntax SemanticModel.GetSymbolInfo returns 没有匹配的符号,并且调用的表达式是一个 IdentifierNameSyntax 包含标识符标记 "nameof".

所以为了识别 nameof 表达式,我会在 VisitInvocationExpression 中添加一个特例,寻找是否 GetSymbolInfo returns 任何东西,如果没有,寻找是否标识符是 nameof。但是,这对我来说听起来有点不确定。是否有更好的方法将这种检测逻辑转移到解析器?

(P.S.: 我知道出于向后兼容性的原因,这可能是这样解析的;只是想知道是否有 API 来区分 nameof 和正常调用。)

nameof 表达式是编译时常量。您可以使用该事实将其与正常调用区分开来。您可以在 InvocationExpressionSyntax 上调用 SematicModel.GetConstantValue()。如果它是 nameof,您将返回 Optional<object>.Value 中的字符串/名称(HasValue 也 returns true)。

我现在确实使用了以下片段:

if (symbolInfo.Symbol == null &&
    symbolInfo.CandidateSymbols.IsEmpty &&
    symbolInfo.CandidateReason == CandidateReason.None) {
  var identifier = node.Expression as IdentifierNameSyntax;
  if (identifier != null && identifier.Identifier.Kind() == SyntaxKind.IdentifierToken && identifier.Identifier.Text == "nameof") {
    // We have a nameof expression
  }
}

我选择不利用常量值进行检测,以防万一 C# 8 左右添加了一个不同的运算符,它可能也有一个常量值,但不是 nameof。检测几乎准确地检测到规范所说的用于确定调用是 nameof 表达式的内容:

Because nameof is not a reserved keyword, a nameof expression is always syntactically ambiguous with an invocation of the simple name nameof. For compatibility reasons, if a name lookup of the name nameof succeeds, the expression is treated as an invocation_expression – regardless of whether the invocation is legal. Otherwise it is a nameof_expression.