I am trying to understand how Roslyn Compiler is working.
I am trying to write simple function, which will analyze code and change loop statements from increasing to decreasing.
For example change:
for(int i=0; i<10; i++)
int a = i;
to:
for(int i=9; i>=0; i--)
int a=i;
I have written arleady code to find that loop, but I don't know how to edit it.
This is what i 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 'for loop' declaration. Additionally, how to change expressions which that loop contains.
Create a SyntaxRewriter which is a visitor that can be used to replace nodes in your syntax tree with new nodes that 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 changed condition and statement. So you can use the WithCondition() and WithStatement() methods to make the updates respectively. You can create the new nodes by hand or you can parse a string using one of the many SyntaxFactory methods.
e.g.,
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 just 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 the rewriter. You can just use the Replace extension methods to replace nodes in a 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);
}
")
));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With