108

我试图找到一些语义差异/合并实用程序的好例子。比较源代码文件的传统范例是通过比较行和字符来工作的。但是在比较文件时是否有任何实用程序(适用于任何语言)实际考虑代码结构

例如,现有的差异程序将报告“在第 125 行的字符 2 处发现差异。文件 x 包含 void,其中文件 y 包含布尔值”。一个专门的工具应该能够报告“方法的返回类型 doSomething() 从 void 更改为 bool”。

我认为这种类型的语义信息实际上是用户在比较代码时所寻找的,并且应该是下一代编程工具的目标。可用工具中有这方面的例子吗?

4

8 回答 8

37

我们开发了一种能够精确处理这种情况的工具。检查http://www.semanticmerge.com

它基于代码结构进行合并(和差异),而不是使用基于文本的算法,这基本上允许您处理以下情况,涉及强重构。它还能够呈现差异和合并冲突,如下所示:

在此处输入图像描述

并且不会对被移动的文本块感到困惑,因为它首先解析,它能够基于每个方法(实际上是每个元素)显示冲突。像以前这样的案例甚至不需要手动解决冲突。

在此处输入图像描述

它是一个语言感知的合并工具,最终能够回答这个 SO 问题真是太好了 :-)

于 2013-04-23T07:15:12.793 回答
30

Eclipse早就有了这个特性。它被称为“结构比较”,非常好。这是 Java 的示例屏幕截图,然后是 XML 文件的示例屏幕截图:

(注意上方窗格中方法上的减号和加号图标。)

Eclipse 的 Java 结构比较器 Eclipse 的 XML 结构比较器

于 2009-03-07T08:55:45.993 回答
14

要做好“语义比较”,需要比较语言的语法树,并考虑符号的含义。一个非常好的语义差异会理解语言语义,并意识到一个代码块在功能上与另一个代码块是等价的。走到这一步需要一个定理证明器,虽然它非常可爱,但目前对于真正的工具来说并不实用。

一个可行的近似方法是简单地比较语法树,并根据插入、删除、移动或更改的结构报告更改。更接近“语义比较”,可以报告标识符何时在代码块中一致更改。

请参阅我们的http://www.semanticdesigns.com/Products/SmartDifferencer/index.html ,了解可与多种语言一起使用的基于语法树的比较引擎,该引擎执行上述近似。

编辑 2010 年 1 月:可用于 C++、C#、Java、PHP 和 COBOL 的版本。该网站显示了其中大多数的具体示例。

编辑 2010 年 5 月:添加了 Python 和 JavaScript。

编辑 2010 年 10 月:添加了 EGL。

编辑 2010 年 11 月:添加了 VB6、VBScript、VB.net

于 2009-06-17T09:53:09.957 回答
12

你正在摸索的是一个“树差异”。事实证明,这比简单的面向行的文本差异更难做好,这实际上只是两个平面序列的比较。

一种细粒度的 XML 结构比较方法”总结如下:

我们的理论研究以及我们的实验评估表明,所提出的方法相对于现有替代方案产生了改进的结构相似性结果,同时具有相同的时间复杂度(O(N^2))

(强调我的)

事实上,如果您正在寻找更多关于树差分的示例,我建议您关注 XML,因为这一直在推动该领域的实际发展。

于 2009-03-07T08:27:15.937 回答
5

我自己的项目的无耻插件:

HTML Tree Diff 对 xml 和 html 文档进行结构感知比较,用 python 编写。

http://pypi.python.org/pypi/html-tree-diff/0.1.0

于 2011-02-09T16:55:23.230 回答
2

对此的解决方案将基于每种语言。也就是说,除非它的设计采用插件架构,将大量的代码解析延迟到树中,并将语义比较与特定语言的插件进行比较,否则将很难支持多种语言。您对拥有这样的工具感兴趣的语言是什么。就我个人而言,我喜欢 C# 的一个。

对于 C#,Reflector 有一个程序集差异插件,但它只对 IL 而非 C# 进行差异。

您可以在此处下载 diff 插件[zip] 或在此处访问 codeplex 站点上的项目。

于 2009-03-07T07:41:43.003 回答
2

一家名为 Zynamics 的公司提供了一种二进制级语义差异工具。它使用一种称为 REIL 的元汇编语言对二进制的 2 个版本进行图论分析,并生成一个颜色编码的图来说明它们之间的差异。我不确定价格,但我怀疑它是免费的。

于 2010-01-19T21:09:01.037 回答
2

http://prettydiff.com/

Pretty Diff 缩小每个输入以删除注释和不必要的空白,然后在 diff 算法之前美化代码。无论如何,我想不出比这更多的代码语义。而且,它编写了 JavaScript,因此它直接在浏览器中运行。

于 2011-06-30T20:14:30.990 回答