2016-01-13 75 views
2

我想编写一个方法来确保树中的所有if语句后面都有支撑代码块。这里是我的代码:重写if语句:其中一条语句以一对太括号结尾

class Program 
{ 
    static void Main(string[] args) 
    { 
     var tree = CSharpSyntaxTree.ParseText(@" 
               class Program 
               { 
                static void main() 
                { 
                 if(true) 
                  Console.WriteLine(""It was true!""); 
                 if(false) 
                  Console.WriteLine(""It was false!""); 
                } 
               }"); 

     var root = tree.GetRoot(); 
     var rewriter = new MyRewriter(); 

     var newRoot = rewriter.Visit(root); 
     var ifStatements = newRoot.DescendantNodes().OfType<IfStatementSyntax>(); 

     foreach (var ifStatement in ifStatements) 
     { 
      SyntaxNode newIfStatement = rewriter.VisitIfStatement(ifStatement); 
      newRoot = newRoot.ReplaceNode(ifStatement, newIfStatement); 
     } 

     var result = newRoot; 

     Console.WriteLine(result.ToString()); 
     Console.ReadKey(); 
    } 
} 

public class MyRewriter: CSharpSyntaxRewriter 
{ 
    public override SyntaxNode VisitIfStatement(IfStatementSyntax node) 
    { 
     var body = node.Statement; 
     var block = SyntaxFactory.Block(body); 
     var newIfStatement = node.WithStatement(block); 

     return newIfStatement; 
    } 
} 

这里是我的输出:

类节目 { 静态无效的主要(){ 如果 (真){{
Console.WriteL国家统计局(”这是真的!“);如果(假){
Console.WriteLi ne(“It was false!”);}}
if }
} }

正如你可以看到,下面的第一if语句的代码块被支撑两次(如预期),而下面的第二码块if语句仅支撑一次(如预期)。

我确信我对Roslyn的工作原理有一些错误的假设,所以有人会好心地告诉我哪里出了问题?我应该做什么改变?

回答

2

您正在混合两件事情:要么使用SyntaxRewriter要么“手动”。现在你正在做这两件事:首先你打电话给重写器,然后你遍历所有的节点,并在每个IfStatementSyntax上再次打电话给重写器。

  • 修复所有if声明:var newRoot = rewriter.Visit(root);

  • 手动更换所有if声明:

var ifStatements = newRoot.DescendantNodes().OfType<IfStatementSyntax>(); 

foreach (var ifStatement in ifStatements) 
{ 
    SyntaxNode newIfStatement = rewriter.VisitIfStatement(ifStatement); 
    newRoot = newRoot.ReplaceNode(ifStatement, newIfStatement); 
} 

可以省略循环干脆:这是一个特别的任务SyntaxRewriter

为什么只有第一个语句会得到两个大括号?

例如,可以通过DocumentEditor完成对树的多重修改。第一次替换后,ifStatements集合中的第二个IfStatementSyntax与您首次替换时收到的新创建的语法树不同步。由于它不同步,原始ifStatementSyntax的位置现在位于新创建的树中的不同位置(已经添加了一个括号 - >取决于所应用的格式,这会将所有字符移至至少一个位置)。 结果:第一次替换成功,第二次替换失败(静默)。


而且备注:通过添加Formatter注释添加的节点,并呼吁Formatter.Format以后这样的应用格式:

var newRoot = rewriter.Visit(root).WithAdditionalAnnotations(Formatter.Annotation); 
var result = Formatter.Format(newRoot, Formatter.Annotation, new AdhocWorkspace()); 
+0

非常感谢您的帮助!你能激励你为什么建议我应用格式? –

+0

因为如果你没有这个注释打印它,它看起来像这样:http://i.imgur.com/0cvpZaR.png这不是很漂亮;-)通过注释你可以得到这个:http://i.imgur。 com/uXZAQ8k.png –

+0

这些截图非常有用 - 谢谢! –