Edit cycle in Roslyn

I am trying to understand how the Roslyn compiler works.

I am trying to write a simple function that will parse the loop statements and loop changes from increasing to decreasing.

For example, changing:

for(int i=0; i<10; i++)
    int a = i;

      

in

for(int i=9; i>=0; i--)
    int a=i;

      

I wrote arleady code to find this loop, but I don't know how to edit it.

This is what I have done so far:

SyntaxTree tree = CSharpSyntaxTree.ParseText(
    @"using System;
    using System.Collections.Generic;
    using System.Text;

        static void Main(string[] args)
        {
        for(int i=0; i<10; i++)
        int a = i;
        }");
var root = (CompilationUnitSyntax)tree.GetRoot();

IEnumerable<ForStatementSyntax> forStatementSyntaxs = root.DescendantNodes().OfType<ForStatementSyntax>();

ForStatementSyntax forStatementSyntax = forStatementSyntaxs.First();
ExpressionSyntax expressionSyntax = forStatementSyntax.Incrementors.First();

      

I would like to know how to change with Roslyn's 'for loop' statement. Also, how to change the expressions that this loop contains.

+3


source to share


1 answer


Create a SyntaxRewriter, which is a visitor that can be used to replace nodes in your syntax tree with new nodes you create. There are also methods for all nodes that can be used to create new nodes with a change to it.

In your case, you want to create a new ForStatementSyntax

node with modified condition and operator. Thus, you can use the WithCondition()

and methods WithStatement()

to generate updates accordingly. You can create new nodes manually or you can parse the string using one of the methods SyntaxFactory

.

eg.

class Rewriter : CSharpSyntaxRewriter
{
    public override SyntaxNode VisitForStatement(ForStatementSyntax node)
    {
        // update the current node with the new condition and statement
        return node.WithCondition(
            SyntaxFactory.ParseExpression("i>=0")
        ).WithStatement(
            SyntaxFactory.ParseStatement(@"{
              Console.WriteLine(i);
              Console.WriteLine(i*2);
            }")
        );
    }
}

      

With the visitor created, you can simply use it.



var root = SyntaxFactory.ParseCompilationUnit(
@"using System;
using System.Collections.Generic;
using System.Text;

static void Main(string[] args)
{
    for(int i=0; i<10; i++)
        int a = i;
}");
var rewritten = new Rewriter().Visit(root);

      


On the other hand, for simpler rewriting tasks, you don't necessarily need a rewriter. You can simply use the Replace Extension methods to replace nodes in the tree.

var forStmt = root.DescendantNodes().OfType<ForStatementSyntax>().Single();
var rewritten = root.ReplaceNode(forStmt,
    forStmt.WithCondition(
        SyntaxFactory.ParseExpression("i>=0")
    ).WithStatement(
        SyntaxFactory.ParseStatement(@"    {
          Console.WriteLine(i);
          Console.WriteLine(i*2);
        }
      ")
    ));

      

+1


source







All Articles