【问题标题】:Edit loop in Roslyn在 Roslyn 中编辑循环
【发布时间】:2014-08-29 12:58:56
【问题描述】:

我正在尝试了解 Roslyn 编译器的工作原理。

我正在尝试编写简单的函数,它将分析代码并将循环语句从增加变为减少。

例如更改:

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

到:

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

我已经编写了很早的代码来查找该循环,但我不知道如何编辑它。

这是我到目前为止所做的:

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

我想知道如何使用 Roslyn 的“for loop”声明进行更改。此外,如何更改该循环包含的表达式。

【问题讨论】:

  • 你有什么问题?
  • 如何使用 Roslyn 'for loop' 声明进行更改。此外,如何更改该循环包含的表达式。

标签: c# for-loop roslyn


【解决方案1】:

创建一个 SyntaxRewriter,它是一个访问者,可用于将语法树中的节点替换为您创建的新节点。对于所有节点,也有一些方法可用于创建新节点并对其进行更改。

在您的情况下,您希望创建一个新的 ForStatementSyntax 节点,并更改条件和语句。因此,您可以使用WithCondition()WithStatement() 方法分别进行更新。您可以手动创建新节点,也可以使用多种 SyntaxFactory 方法之一解析字符串。

例如,

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

创建访问者后,您可以简单地使用它。

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

另一方面,对于更简单的重写任务,您不一定需要重写器。您可以只使用 Replace 扩展方法来替换树中的节点。

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

【讨论】:

    猜你喜欢
    • 2014-08-05
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 2015-07-25
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多