gpt4 book ai didi

c# - 一次对 SyntaxTree 进行多项修改

转载 作者:太空狗 更新时间:2023-10-29 19:41:23 25 4
gpt4 key购买 nike

我想一次对 Roslyn 语法树进行多项修改,都围绕同一代码区域

tree = tree.ReplaceNodes(oldNode, newNode).RemoveNode(toRemove);

但是,只有第一次修改成功。似乎第一个更改更改了它周围的所有节点,因此 RemoveNodes 方法不再在生成的树中找到 toRemove。我真的非常不想重新计算新树中的 toRemove 并使用单个 SyntaxRewriter 执行所有工作(覆盖 DefaultVisit 方法)慢得离谱。

我怎样才能做我想做的事?

最佳答案

在我提供一些替代方案之前,您对 SyntaxRewriter“慢得离谱”的评论有点令人惊讶。当您说“慢”时,您的意思是“要编写很多代码”还是“它的性能非常糟糕”?这是执行多个替换的最快(执行时间明智)方式,并且 ReplaceNodes 和 RemoveNode 都在内部使用重写器。如果您遇到性能问题,请确保在实现 DefaultVisit 时仅在您感兴趣的节点位于调用它的节点下时才访问子类型。简单的技巧是比较跨度并确保传递的节点的跨度与您正在处理的节点相交。

无论如何,SyntaxAnnotations 提供了一种有用的方法来在修改后定位树中的节点。您可以只创建该类型的实例,然后使用 WithAdditionalAnnotations 扩展方法将其附加到节点。您可以使用 GetAnnotatedNodesOrTokens 方法再次定位该节点。

因此,解决您的问题的一种方法是注释您的 toRemove,然后当您调用 ReplaceNodes 时,在同一调用中执行两次替换——一次执行旧节点 -> 新节点替换,然后一次执行 toRemove -> toRemoveWithAnnotation替代品。然后在结果树中找到带注释的节点并调用 RemoveNode。

如果您知道 oldNode 和 toRemove 不是彼此的祖先(即它们位于树的不相关部分),另一种选择是颠倒顺序。获取 toRemove 的父节点(称为 oldNodeParent)并调用 RemoveNode,这意味着您将获得更新的父节点(称为 oldNodeParentRewritten)。然后,调用 ReplaceNodes 进行两次替换:oldNode -> newNode 和 oldNodeParent -> oldNodeParentRewritten。无需注释。

关于c# - 一次对 SyntaxTree 进行多项修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13435168/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com