2014-10-22 5 views
2

我正在根據某些條件使用SyntaxFactory.VariableDeclarationSyntaxNode收集的自定義生成變量聲明。如何使用Roslyn代碼修復提供程序API從文檔中刪除SyntaxNode列表?

我做了以下內容:

  1. 修改

    var newRoot = root.ReplaceNode(expression, newVariableDeclaration) 
    

    這成功修改了節點與newVariableDeclaration節點。

  2. 在循環中刪除對應於存在於列表中的那些

    foreach (var listObject in listObjects) 
    { 
        newRoot = newRoot.RemoveNode(listObject, SyntaxRemoveOptions.KeepNoTrivia); 
    } 
    

    這並不改變newRoot和需要被改變了所有的listObject保持相同的節點。

如果我們使用root.RemoveNode(listObject, SyntaxRemoveOptions.KeepNoTrivia)相反,它會很明顯,不斷取代了以往的變化。

所以這裏的newVariableDeclaration是在整個文檔中改變的唯一節點,這是因爲newRootSyntaxNodes具有不同於我從root獲得SyntaxNode的變化。

請糾正我,如果我做錯了。

編輯: 我看着CSharpSyntaxRewriter但現在看來,它是分析單個節點每次它訪問一個節點,並只能在同一時間修改單個節點。在我的場景中,我將不得不訪問特定節點,對其進行更改,並根據對訪問節點所做的更改刪除其他節點。

回答

1

您的方法存在的問題是,無論何時更改樹(使用ReplaceNode()RemoveNode()),這意味着所有節點都會發生更改。這就是爲什麼ReplaceNode()之後您撥打RemoveNode()不會做任何事情的原因。

解決此問題的一種方法是使用TrackNodes(),以便您可以找到修改的樹中的哪些節點與原始樹中的節點相對應。

Uisng此,替換節點的序列與單個節點可能看起來像這樣的方法:

public static T ReplaceNodes<T>(
    this T root, IReadOnlyList<SyntaxNode> oldNodes, SyntaxNode newNode) 
    where T : SyntaxNode 
{ 
    if (oldNodes.Count == 0) 
     throw new ArgumentException(); 

    var newRoot = root.TrackNodes(oldNodes); 

    var first = newRoot.GetCurrentNode(oldNodes[0]); 

    newRoot = newRoot.ReplaceNode(first, newNode); 

    var toRemove = oldNodes.Skip(1).Select(newRoot.GetCurrentNode); 

    newRoot = newRoot.RemoveNodes(toRemove, SyntaxRemoveOptions.KeepNoTrivia); 

    return newRoot; 
} 
相關問題