2014-06-26 80 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