Roslyn: Not all InvocationExpression are rewritten

Created on 27 Feb 2020  路  4Comments  路  Source: dotnet/roslyn

Version Used:
Core3.1 ConsoleApp
Steps to Reproduce:

private class Rewriter : CSharpSyntaxRewriter
    {
        public int Id { get; set; }
        public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node)
        {
            var invokName = node.Expression.ToString();
            if (invokName == "MyMethod")
            {
                var argus = node.ArgumentList.AddArguments(
SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(Id))));
                return node.Update((ExpressionSyntax)Visit(node.Expression), argus);
            }
            return node;
        }
    }
    static void Main(string[] args)
    {
        SyntaxTree oriTree = CSharpSyntaxTree.ParseText(@"
        public class MyClass
        {
            public string MyMethod(int id)
            {
                return $""{id}"";
            }
            public void Say()
            {
                var tmp = MyMethod();//worked
                var tmp1 = MyMethod();//worked
                var tmp2 = ""Hi "" + MyMethod();//worked
                Console.WriteLine($""Say {MyMethod()}"");//Not worked
                Console.WriteLine(""Hello "" + MyMethod());//Not worked                    
            }
        }");
        var syntaxRoot = oriTree.GetCompilationUnitRoot();
        var visitor = new Rewriter();
        visitor.Id = 0;
        var changedSyntaxTree = visitor.Visit(syntaxRoot).SyntaxTree;
    }

Expected Behavior:
I want to rewrite all InvocationExpression of "MyMethod" in a SyntaxTree to add a literal param 0
Actual Behavior:
Not all InvocationExpression are rewritten.

var methods = syntaxRoot.DescendantNodes().OfType<InvocationExpressionSyntax>().Where(o => o.Expression.ToString() == "MyMethod"); can enumerate all InvocationExpression of "MyMethod".

Area-Compilers Question

Most helpful comment

you need to do this instead:

c# public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node) { node = (InvocationExpressionSyntax)base.VisitInvocationExpression(node); // now, the rest of your code: var invokName = node.Expression.ToString(); // etc.

Note: i would recomment using SyntaxEditor instead of a rewriter here. it will make the code a lot easier and cleaner.

All 4 comments

do you need to call base.Visit(node) in order to visit nested invocation expressions?

do you need to call base.Visit(node) in order to visit nested invocation expressions?

if (invokName == "MyMethod")
 {
    var argus = node.ArgumentList.AddArguments(
SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(Id))));
    return node.Update((ExpressionSyntax)Visit(node.Expression), argus);
 }
//???
else if (node.ArgumentList.Arguments.Any(o => o.Expression.ToString().Contains("MyMethod")))
 {
     //???
 }
return node;

you need to do this instead:

c# public override SyntaxNode VisitInvocationExpression(InvocationExpressionSyntax node) { node = (InvocationExpressionSyntax)base.VisitInvocationExpression(node); // now, the rest of your code: var invokName = node.Expression.ToString(); // etc.

Note: i would recomment using SyntaxEditor instead of a rewriter here. it will make the code a lot easier and cleaner.

@CyrusNajmabadi
Wow, It's done. Thands a lot!
I haven't learned to use the syntax editor yet, and I can find very little information

Was this page helpful?
0 / 5 - 0 ratings