语义差异工具

113

我正在寻找一些优秀的语义差异/合并工具的好例子。传统的比较源代码文件的范式是通过比较行和字符来实现的...但是是否有任何工具(适用于任何语言)在比较文件时实际上考虑到代码的结构?

例如,现有的差异程序会报告“在第125行的第2个字符发现差异。文件x包含v-o-i-d,而文件y包含b-o-o-l”。专用的工具应该能够报告“方法doSomething()的返回类型已从void更改为bool”。

我认为,这种语义信息实际上是用户在比较代码时寻找的内容,也应该是下一代编程工具的目标。是否有任何可用工具中存在这种例子?


3
似乎已经对树编辑距离进行了一些研究。将其应用于抽象语法树似乎是首先要尝试的事情(如果有人想尝试编写此类内容)。 - Jay Kominek
2
我不确定它是否真的有用。像你提到的那样的差异比阅读更容易看到,特别是如果您有一个突出显示行内差异的工具。在我看来,识别某些代码是否只是移动而没有改变会更容易和更有用! - UncleZeiv
2
@UncleZeiv 我希望这个功能能够自然地从工具的本质中衍生出来。此外,它还应该能够检测到如果有人更改了花括号或缩进样式,或者重新排列文件以便将静态方法分组等情况下,是否存在任何更改。 - jasonmray
9
我现在需要在Visual Studio中使用这个。强迫团队内的开发人员使用相同的格式结构以促进差异处理是一种倒退的思维方式。代码应该在提交时按照某个标准进行格式化,每当开发人员打开文件时,它都应按照他们自己的喜好进行格式化。我很震惊这种思维方式目前还没有更广泛的传播。 - Langdon
3
个人认为这是适合在 Stack Overflow 上讨论的话题。如果你也同意,就投票支持“重新开放讨论”。 - Ira Baxter
显示剩余4条评论
8个回答

38
我们开发了一个工具,能够精确地处理这种情况。请检查http://www.semanticmerge.com
它基于代码结构合并(和diff),而不是使用基于文本的算法,这基本上允许您处理以下情况,包括强大的重构。它还能够呈现差异和合并冲突,如下所示: enter image description here 而且它不会因为移动文本块而感到困惑,因为它首先解析,所以它能够按方法(实际上是按元素)显示冲突。像之前的案例甚至都没有需要手动解决的冲突。 enter image description here 这是一个语言感知的合并工具,对我们终于能够回答这个SO问题感到非常高兴 :-)

能否将其与SVN集成? - Revious
1
然而,Linux和Mac版本非常老旧。 - Michael Piefel
这个工具似乎已经被其所有者下架并不再提供。 - osiris

30

Eclipse 长期以来一直拥有一个名为“结构比较”的功能,非常好用。以下是Java和XML文件的示例截图:

(请注意上方面板中方法前的减号和加号图标。)

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


3
「结构比较」能像其他源代码控制的合并编辑器一样合并更改吗?例如,将此方法从一个版本复制到另一个版本。 - Jonathan Parker
1
是的,当您选择更改或差异(无论是在上方还是下方窗格中)时,工具栏按钮(如屏幕截图所示)会提供将更改从左侧复制到右侧或反之亦然的选项。 - Hosam Aly
1
很不幸,您(最受赞同和接受的!)答案中的截图已不再可见。您能否重新提交它们? - blubb
@blubb 感谢您的通知。我已经纠正了Java Comparer图片的错误。我会尽快为XML结构比较器添加屏幕截图。 - Hosam Aly
不适用于嵌套类... - leppie
1
除了Java之外,这对其他编程语言也适用吗? - einpoklum

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。

2
嗨,艾拉,你发表过关于你的差异算法的论文吗?我在寻找树编辑距离差异文献方面遇到了困难。谢谢,特伦斯。 - Terence Parr
更具体地说,我正在寻找diff3而不是普通的diff2。 - Terence Parr
2
@Terence:我们的差异算法没有任何出版物。它是使用后缀树进行Levenstein最小距离计算,以识别相等的子树,并使用一些启发式方法来处理重命名。如果我没记错的话,Yang在《软件实践与经验》上发表了一篇关于此的论文。我们和Yang的都是diff2,而不是diff3。 - Ira Baxter

13
你所需要的是"树形差异"。事实证明,这比简单的基于行的文本差异要难得多,后者实际上只是两个平面序列的比较。
"一种细粒度XML结构比较方法"在部分结论中指出:
我们的理论研究以及实验评估表明,所提出的方法在具有相同时间复杂度(O(N ^ 2))的情况下,产生了改进的结构相似性结果,相对于现有的替代方案而言。
(强调是我的)
如果你正在寻找更多的树形差异示例,我建议集中关注XML,因为它一直推动该领域的实际发展。

谢谢提供链接。对于实现语义 diff 工具,我可以想到几种不同的方法,而且您说得对 -- 大多数都可以抽象成“树 diff”。更复杂的情况甚至可能需要抽象成“图 diff”。 - jasonmray
是的。IBM的Rational Modeler(基于eclipse)尝试使用UML模型来实现此目的(以图形方式显示两个模型之间的差异)。由于我很少使用它,因此无法评论结果的有用性。 - bendin
我认为XML是一个很好的起点,因为你可以轻松地想出用于表示其他结构(例如Java代码)的模式,并使用基于XML的树形差异来实现代码差异。 - jasonmray
"do this" => 做类似于“图形差异”的操作。 - bendin
1
请访问http://www.semdesigns.com/Products/SmartDifferencer/index.html,了解一种基于语法树的比较引擎,可用于多种编程语言。 - Ira Baxter

5

2

Zynamics公司提供一款二进制级别的语义差异工具。它使用名为REIL的元汇编语言对2个版本的二进制文件执行图论分析,并生成一个彩色编码的图表以说明它们之间的区别。我不确定价格,但我怀疑它并非免费。


二进制级别的语义差异链接:https://www.zynamics.com/bindiff.html - emallove
bindiff现在是免费的,binnavi(他们的另一个产品)是开源的。看起来REIL包含在binnavi发布中 - https://github.com/google/binnavi/tree/master/src/main/java/com/google/security/zynamics/binnavi/REIL - Mark

2

http://prettydiff.com/

Pretty Diff将每个输入都进行了缩小,以去除注释和不必要的空格,并在差异算法之前美化了代码。我想不出有什么比这更能提高代码语义的方法了。而且,它是用JavaScript编写的,因此可以直接在浏览器中运行。


7
那么你的想象力有限!如果在文件中交换两个方法的位置但不改变它们,怎么办?重构呢? - Robin Green
这种方式无法在Java中交换数据声明并保持等价,因为存在初始化器的问题;我假设C#也存在类似的困扰。如果你只是进行纯语义差异比较,那么你就在试图解决图灵机的等价性问题。在纯文本匹配和图灵机不可能之间,有很多改进的空间。 - Ira Baxter
@IraBaxter 这个工具在概念上显然只会显示实际上等价的东西。如果编码正确,它不会出现您提到的问题类型。 - Răzvan Flavius Panda
“Properly coded”的意思是,如果你想要最终的工具,需要证明算法的等效性。一般来说,算法等效性证明是图灵难题,所以实践中你不可能得到这样的工具。你可能会得到一个处理除了语法改变之外的某些等效性的工具。截至目前,我还没有看到有人尝试构建这样的工具。 - Ira Baxter

2
这个问题的解决方案应该是基于每种语言单独处理。也就是说,除非它被设计成具有插件架构,可以将代码的大部分解析和语义比较推迟到特定于语言的插件中,否则将很难支持多种语言。您希望为哪些语言提供此类工具?就我个人而言,我想要一个针对C#的工具。
对于C#,Reflector 有一个程序集差异添加组件,但它仅在 IL 上进行差异比较,而不是 C#。
您可以从这里 下载差异添加组件[zip],或者前往 codeplex 网站上的项目这里

1
请访问http://www.semdesigns.com/Products/SmartDifferencer/index.html,了解基于语法树的比较引擎,它可以与许多语言一起使用,采用完全相同的语言插件风格。尚未发布,但C#版本即将推出。 - Ira Baxter
2010年1月:发布了C#智能差异工具。 - Ira Baxter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接