2015-07-09 15 views
6

Tôi đang cố gắng thay thế một vài nút trong cây cú pháp bằng roslyn. Nhưng bản chất bất biến của nó dường như cản trở tôi.Thay thế nhiều nút trong cây cú pháp Roslyn

public static string Rewrite(string content) 
    { 
     var tree = CSharpSyntaxTree.ParseText(content); 
     var root = tree.GetRoot(); 

     var methods =root 
      .DescendantNodes(node=>true) 
      .OfType<MethodDeclarationSyntax>() 
      .ToList(); 

     foreach(var method in methods) 
     { 
      var returnActions = method 
       .DescendantNodes(node => true) 
       .OfType<BinaryExpressionSyntax>() 
       //Ok this is cheating 
       .Where(node => node.OperatorToken.ValueText == "==") 
       .Where(node => node.Right.ToString() == "\"#exit#\"" || node.Right.ToString() == "\"#break#\"") 
       .Select(node => node.Parent as IfStatementSyntax) 
       .ToList(); 

      var lookup = new Dictionary<StatementSyntax,StatementSyntax>(); 

      if (returnActions.Count > 0) 
      { 
       foreach(var ifStatement in returnActions) 
       { 
        var mainCall = ifStatement.GetPrevious() as ExpressionStatementSyntax;       
        var newIfStatement = ifStatement.WithCondition(mainCall.Expression.WithoutTrivia()); 

        lookup[mainCall] = null; 
        lookup[ifStatement] = newIfStatement; 
       } 

       //this only replace some of the nodes 
       root = root.ReplaceNodes(lookup.Keys, (s, d) => lookup[s]); 
      } 
     } 

     return root.ToFullString(); 
    } 

Vấn đề là khi tôi gọi root.ReplaceNodes chỉ một số nút được thay thế.

Tôi đoán rằng thay thế thay đổi cây sao cho các nút khác không còn khớp với cây gốc và do đó không thể thay thế được.

Nhưng cách tốt nhất để giải quyết vấn đề này là gì?

Looping qua quá trình lặp đi lặp cho đến khi thay đổi không xảy ra cảm thấy khập khiễng :)

Những thay đổi có thể xảy ra lồng nhau, và tôi nghĩ rằng đó là những gì gây ra những vấn đề ở đây. Tôi có thể sắp xếp các changeset bằng cách nào đó để có được xung quanh này hoặc là có một cách thành ngữ để đi về những thứ ở đây?

Trả lời

10

Tôi đoán rằng thay thế thay đổi cây sao cho các nút khác không còn khớp với cây gốc và do đó không thể thay thế được.

Bạn nói đúng. Thay thế các nút tạo cây cú pháp hoàn toàn mới. Các nút từ các cây cú pháp trước không thể so sánh được với các cây cú pháp mới này.

Có bốn cách để áp dụng nhiều thay đổi cho một cây cú pháp:

  1. Sử dụng DocumentEditor - Xem: https://stackoverflow.com/a/30563669/300908
  2. Sử dụng Annotations (dòng 235 và 239)
  3. Sử dụng .TrackNodes()
  4. Tạo a CSharpSyntaxRewriter thay thế các nút theo cách tiếp cận từ dưới lên. Tôi đã viết về điều này trên blog của tôi.

Trong số các tùy chọn này, tôi tin rằng DocumentEditor có tiếng là dễ sử dụng nhất. Nó rất có thể là cách thành ngữ để áp dụng nhiều thay đổi trong tương lai.

Các vấn đề liên quan