【发布时间】:2016-01-27 07:21:44
【问题描述】:
假设我有两个SyntaxTrees A和B,
其中 B 是通过对 A 应用更改生成的。
我想获得以下信息:
- 已从 A 中删除以生成 B 的语法节点和标记
- 已添加到 A 以生成 B 的语法节点和标记
有这方面的 API 吗?
如果不是,如何有效计算?
此信息必须对 Roslyn 可用,
因为不变的GreenNodes 在树之间共享。
我能想到的一个解决方案是使用SyntaxTree.GetChangedSpans()
然后查找相交的标记。
但是,这感觉像是一种 hack,我不确定它是否总是准确的。
一个小的文本更改可能会对SyntaxTree 产生很大影响:
(例如,在表达式中将 * 替换为 + 可能会改变其顺序/优先级)
【问题讨论】:
-
如果你真的有两个 AST 并且可以访问它们,这看起来很简单。列出A的节点,B的节点。nodes(A)-Green是那些已经被删除的节点。节点(B)-绿色是那些已经添加的。你需要做的就是做一个树行走,建立一些集合并做集合减法。我不是 Rosyln 用户,但这很难吗?
-
我认为由于技术原因无法有效地做到这一点。 (不能使用
HashSets,因为节点的“不稳定”GetHashCode()实现)。平等工作:SyntaxNode.IsEquivalentTo()。但是我想避免将 A 中的每个节点与 B bcs O(n^2) 中的每个节点进行比较。 -
所以罗斯林很失望。 (我构建了一个系统,可以像 Rosyln 那样做,我建议的方法可以正常工作;事实上,我们有一个“智能差分器”,它通过更壮观的树木比较工作,以一种更智能的方式。见我的生物)。
-
你的语法树有共享历史吗?还是您在更改之间从头开始重新解析它们?
-
@IraBaxter:感谢您的建议,但出于各种原因,我现在必须坚持使用 Roslyn。我以前检查过你的个人资料和网站。在 SO 上浏览与 AST 相关的内容时,你很难避免;)
标签: syntax diff abstract-syntax-tree roslyn roslyn-code-analysis