【问题标题】:Roslyn SyntaxTree DiffRoslyn 语法树差异
【发布时间】:2016-01-27 07:21:44
【问题描述】:

假设我有两个SyntaxTrees AB
其中 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


【解决方案1】:

我们internally have a differ 位于编译器层,因此使用绿色节点,我们只是没有将其作为 API 公开。实际上,这就是我们用来驱动 GetChangedSpans 的方法。我们有意没有直接暴露绿色节点,因为这是一个实现细节。

API 不能公开并没有具体原因。我认为当这个问题出现时,我们担心一个人实际上如何指定行为是什么,或者你可以从差异中期望什么是最小的“善良”。那样的话,我们没有一个激励性的场景来真正确保我们的工作是有用的。

【讨论】:

  • 这回答了第一个问题:没有公共 API。 SyntaxDiffer 有可能公开吗? (拉请求?)。或者我们可以使用SyntaxTree.GetChangedSpansSyntaxTree.GetChanges 解决它吗?
  • 旁白:我应该在哪里询问有关 Roslyn API 的问题?所以,GitHub,MSDN? (例如“SyntaxTree.GetChangedSpansSyntaxTree.GetChanges 有什么区别”)
  • 你完全可以提交一个拉取请求。我首先建议您在 GitHub 上打开一个错误,以便人们知道存在问题并且有一些表示您实际上正在做这项工作。这也将让人们在公开之前提出他们知道的任何你想要解决的问题。也许这段代码实际上和所有东西一样都是错误的,这就是我们没有公开它的原因。仅将访问修饰符更改为 public 的“驱动”拉取请求将被拒绝,因为我们必须维护一个受支持的、经过深思熟虑的、格式良好的 API。 :-)
  • 就问题而言,StackOverflow 或 GitHub 都是很棒的论坛。我们也有一个 Gitter 频道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-27
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
  • 2015-08-28
相关资源
最近更新 更多