2014-06-26 127 views
3

我正在嘗試用Roslyn重寫代碼。 我想將GreaterThanToken更改爲EqualsEqualsToken。這是我到目前爲止的代碼:羅斯林代碼重寫

//ToParse.cs 
    public class ToParse 
    { 
     public bool MethodToConvert(int param) 
     { 
      return (1 > param); 
     } 
    } 

//Program.cs 
class Rewriter : SyntaxRewriter 
{ 
    private readonly SyntaxKind _replace; 
    private readonly SyntaxKind _replacewith; 
    public Rewriter(SyntaxKind replace, SyntaxKind replacewith) 
    { 
     _replace = replace; 
     _replacewith = replacewith; 
    } 
    public override SyntaxToken VisitToken(SyntaxToken token) 
    { 
     if (token.Kind != _replace) 
     { 
      return token; 
     } 
     return Syntax.Token(_replacewith); 
    } 
} 

var code = new StreamReader("ToParse.cs").ReadToEnd(); 
var tree = SyntaxTree.ParseText(code); 
var root = tree.GetRoot(); 
var rewriter = new Rewriter(SyntaxKind.GreaterThanToken, SyntaxKind.EqualsEqualsToken); 
var newRoot = rewriter.Visit(root); 

var newTree = SyntaxTree.Create((CompilationUnitSyntax)newRoot); 
var compilation = Compilation.Create("TestAssembly.dll", 
     new CompilationOptions(OutputKind.DynamicallyLinkedLibrary), 
     references: new[]{ new MetadataFileReference(typeof(object).Assembly.Location)}, 
     syntaxTrees: new[] { newTree }); 
Console.WriteLine(newTree); 
EmitResult res; 
using (var file = new FileStream("e:\\TestAssembly.dll", FileMode.Create)) 
{ 
    res = compilation.Emit(file); 
} 

執行後,Console.WriteLine打印改變令牌return (1 == param); 但是當我打開testassembly.dll與ilspy我仍然看到return 1 > param; 有什麼建議?

+0

你重建項目? – jgauffin

+0

是的,我也試過調試/發佈配置 – mrK

+0

Roslyn不允許你在編譯過程中重寫。 – SLaks

回答

6

[注意:您正在使用稍舊版本的Roslyn。這個答案應該爲該版本工作太,但我可以用更近的名字引用類和成員,使他們可在源匹配CodePlex]

,你已經解析了原樹包含一個SyntaxKind一個BinaryExpressionSyntax節點GreaterThanExpression。當你換出GreaterThanTokenEqualsEqualsToken 這裏面BinaryExpressionSyntax,它自動調節的EqualsExpression含有SyntaxNode

其結果是,你最終有一個EqualsEqualsTokenGreaterThanExpression。由於這不是一個可能由編譯器本身合法生成的語法樹,因此您可能會看到像這樣的意外行爲。

要在這種情況下,產生一個正確的樹,我建議通過重寫CSharpSyntaxRewriter.VisitBinaryExpression和做這樣的事情改寫節點本身,而不是令牌:

public override SyntaxNode VisitBinaryExpression(BinaryExpressionSyntax node) 
{ 
    if (node.CSharpKind() == SyntaxKind.GreaterThanExpression) 
    { 
     return SyntaxFactory.BinaryExpression(SyntaxKind.EqualsExpression, node.Left, node.Right); 
    } 

    return node; 
} 
+0

是的!是工作。謝謝! – mrK

+0

編譯過程的某些部分不應該驗證語法樹不包含這種錯誤嗎? – svick