2014-08-29 62 views
3

我想了解Roslyn編譯器如何工作。編輯循環在Roslyn

我正在嘗試編寫簡單的函數,它將分析代碼並將循環語句從增加到減少。

例如改變:

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

到:

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

我寫arleady代碼,發現循環,但我不知道如何編輯它。

這是我迄今所做的:

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

我想知道如何與羅斯林改變「for循環」的聲明。此外,如何更改該循環包含的表達式。

+2

您的問題是什麼? – DLeh 2014-08-29 14:13:11

+1

如何更改Roslyn'for循環'聲明。此外,如何更改該循環包含的表達式。 – Tomasz 2014-08-30 11:09:36

回答

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

在另一方面,對於簡單的重寫工作,你不一定需要重寫。您可以使用替換擴展方法替換樹中的節點。

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