Roslyn在更改的文档中查找相同的节点

时间:2017-05-26 18:36:58

标签: c# roslyn

众所周知,Roslyn语法树是不可变的,因此在进行更改后,您需要获得一个新节点。

我正在尝试使用文档编辑器更新文档,但我一直收到错误,即在语法树中找不到该节点。

public static T FindEquivalentNode<T>(this Document newDocument, T node)
    where T : CSharpSyntaxNode
{
    var root = newDocument.GetSyntaxRootAsync().Result;
    return root.DescendantNodes().OfType<T>()
            .FirstOrDefault(newNode => SyntaxFactory.AreEquivalent(newNode, node));
}

当我尝试再次调用文档编辑器时:

var newFieldDeclaration = documentEditor.GetChangedDocument().FindEquivalentNode(syntaxNode);
documentEditor.ReplaceNode(newFieldDeclaration, propertyDeclaration);

我收到错误:

  

节点不是树的一部分

newField声明不为null它找到一个等效的字段但我仍然得到这个错误,我该如何替换这个节点?

1 个答案:

答案 0 :(得分:2)

您获得节点是因为在您的FindEquivalentNode方法中,您正在这样做:

SyntaxFactory.AreEquivalent(newNode, node)

SyntaxFactory.AreEquivalent对于&#34;真实&#34;不会返回true相同的节点,但对于结构中似乎相等的节点\令牌(考虑topLevel参数)。

回到你的问题,如果你想致电ReplaceNode,你必须拥有&#34;真实&#34;旧节点,所以你不会得到

  

节点不是树的一部分

要实现这一点,你有几个选择,其中一个是@Tamas在评论中写的,使用SyntaxAnnotations

示例:

//Add annotation to node 
var annotation = new SyntaxAnnotation("your_annotation", "some_data");
node = node .WithAdditionalAnnotations(annotation);

// Now you can change the tree as much you want

// And when you want to get the node from the changed tree 
var annotatedNode = someNode.DescendantNodesAndSelf().
        FirstOrDefault(n => n.GetAnnotations("your_annotation").Any())