Roslyn:如何用表达式替换标识符名称

Roslyn: How to replace an IdentifierName with an Expression

我正在尝试使用 Roslyn 重写器,但无法用表达式替换标识符名称。

据我了解,当访问者进行此类替换时,他们需要在类型上匹配。是否有任何解决方法可以忽略类型来执行此替换?

public class NameRewriter : CSharpSyntaxRewriter
{
   private readonly ExpressionSyntax newExpr;

   public NameRewriter(ExpressionSyntax newExpr) {
          this.newExpr = newExpr;
   }

  public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node) {
          return node.ReplaceNode(node, newExpr);
  }

}

ReplaceNode() 的 return 类型与其 this 参数相同,因此要确保 ReplaceNode() 不抛出,将其转换为 SyntaxNode:

return ((SyntaxNode)node).ReplaceNode(node, newExpr);

虽然在您的情况下,根本不需要 ReplaceNode(),但只需 return 新表达式就足够了:

return newExpr;

只有当 IdentifierNameSyntax 可以用给定的表达式实际替换时,以上两个选项才有效。例如,替换 foo(); 中的所有 IdentfierName 将适用于几乎任何表达式,例如使用 bar() 结果是 bar()();。但是对 var x = foo(); 做同样的事情是行不通的,因为 bar() x = bar()(); 在句法上是无效的。

另一方面,使用 bar 之类的东西应该可以随时使用,因为它是另一个 IdentifierName

此外,这样做可能会使您缺少所需的空格,例如,在 var x = foo(); 上使用 bar 会生成有效的树,但文本表示无效:barx = bar();。所以不要忘记在之后格式化生成的树。