pinker
pinker

Reputation: 1293

Roslyn: How to replace an IdentifierName with an Expression

I am trying to use a Roslyn rewriter but I am not being able to replace an IdentifierName by an Expression.

From what I understood when doing a visitor to do such replacement they need to match in type. Is there any workaround to do this substitution ignoring the type?

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);
  }

}

Upvotes: 3

Views: 613

Answers (1)

svick
svick

Reputation: 245018

The return type of ReplaceNode() is the same as its this parameter, so to make sure ReplaceNode() does not throw, cast it to SyntaxNode:

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

Though in your case, ReplaceNode() is not necessary at all, it's enough to just return the new expression:

return newExpr;

Both of the above options will work only when the IdentifierNameSyntax can actually be replaced with the given expression. For example replacing all IdentfierNames in foo(); will work with pretty much any expression, e.g. using bar() results in bar()();. But doing the same for var x = foo(); won't work, because bar() x = bar()(); is not syntactically valid.

On the other hand, using something like bar should work anytime, since it's another IdentifierName.

Also, doing this can leave you with missing required whitespace, for example using bar on var x = foo(); results in valid tree, but one with invalid textual representation: barx = bar();. So don't forget to format the resulting tree afterwards.

Upvotes: 1

Related Questions