【问题标题】:Parsing nameof expressions in Roslyn在 Roslyn 中解析 nameof 表达式
【发布时间】:2016-09-07 18:01:03
【问题描述】:

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

所以要识别nameof 表达式,我会在VisitInvocationExpression 中添加一个特殊情况,查找GetSymbolInfo 是否返回任何内容,如果没有,则查找标识符是否为nameof。然而,这对我来说听起来有点不确定。有没有更好的方法可以将这种检测逻辑转移到解析器?

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

【问题讨论】:

  • 仍然没有 c# 6 的正式规范,但 this draft 似乎确实确认它是一个模棱两可的解析,因此需要额外的推理。
  • @Damien_The_Unbeliever:我实际上尝试在 Roslyn 的源代码中找到它确定但无法粗略搜索的位置。也许我应该再看看。
  • 不,照你的做。考虑到任何人都可以在 C# 6 之前拥有 nameof() 方法,因此无法保证它不是引用类中的方法或通过 static using 导入的方法。在语法分析的时候还没有语义模型的概念,之后显然为时已晚。任何进行nameof 解析的人都必须连接自己的解决方案;-)

标签: c# roslyn nameof


【解决方案1】:

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

【讨论】:

  • GetConstantValue 在这种情况下对我没有帮助,因为我需要将符号映射到自定义名称,但是当然,这可能是将其与其他通常不是常量的调用区分开来的好方法。
【解决方案2】:

我现在确实使用了以下sn-p:

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 表达式的内容:

因为nameof 不是保留关键字,所以nameof 表达式在调用简单名称nameof 时总是在语法上模棱两可。出于兼容性原因,如果名称 nameof 的名称查找成功,则表达式将被视为 invocation_expression - 无论调用是否合法。否则它是一个nameof_expression

【讨论】:

    猜你喜欢
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    相关资源
    最近更新 更多