语义差异实用程序


105

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

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

我认为这种类型的语义信息实际上是用户在比较代码时要寻找的信息,应该成为下一代编程工具的目标。可用工具中是否有此示例?


3
似乎已经对树的编辑距离进行了一些研究。将其应用于AST似乎是要尝试的第一件事。(如果有人想尝试写这种东西。)
Jay Kominek,2009年

2
我不确定这是否真的有用。像你提到的差异更容易看出不是阅读,特别是如果你有一个工具,突出差异的线路。恕我直言,识别某些代码是否只是在未更改的情况下移动的功能将变得更加容易和有用。
UncleZeiv

2
@UncleZeiv我希望该功能自然可以从该工具的性质中获得。此外,它能够检测到有没有变化,如果有人经历,改变了大括号或缩进风格,例如,或重新安排文件,以便静态方法进行分组等。
jasonmray

8
我现在在Visual Studio中需要它。强迫团队中的开发人员使用相同的格式结构来促进差异是一种倒退的思维。该代码应在签到时格式化为某种标准,并且每当开发人员打开文件时,都应按照自己的喜好对其进行格式化。我很震惊,这种想法目前还没有广泛传播。
兰登

3
恕我直言,这是一个很好的主题。如果您同意,请投票“重新开放”
Ira Baxter

Answers:


37

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

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

在此处输入图片说明

由于它首先进行解析,因此不会与要移动的文本块产生混淆,而是能够基于每个方法(实际上是每个元素)显示冲突。像以前那样的情况甚至没有人为解决的冲突。

在此处输入图片说明

这是一种可识别语言的合并工具,很高兴终于能够回答这个SO问题:-)


是否可以将其与SVN集成?
回顾

1
但是,Linux和Mac版本是古老的。
Michael Piefel '18

29

拥有此功能已有很长时间了。它被称为“结构比较”,非常好。这是Java的示例屏幕截图,然后是XML文件的屏幕截图:

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

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


3
使用“结构比较”是否可以像其他源代码管理合并编辑器一样合并更改?即将此方法从此版本复制到另一个版本。
乔纳森·帕克

1
是的,当您选择更改或差异时(在上部或下部窗格中),工具栏按钮(如屏幕截图所示)使您可以选择从左向右复制更改,反之亦然。
Hosam Aly

1
不幸的是,您的(最高投票和接受的!)答案中不再显示这些屏幕截图。您可以再提交一次吗?
blubb

@blubb感谢您通知我。我已使用Java比较器图像更正了该错误。我将尝试尽快添加XML结构比较器的屏幕截图。
Hosam Aly

1
这对Java以外的语言是否有效?
einpoklum

14

为了更好地进行“语义比较”,您需要比较语言的语法树,并考虑符号的含义。一个真正好的语义差异将理解语言的语义,并实现一个代码块在功能上等同于另一个代码块。要走得太远,需要一个定理证明者,虽然它非常可爱,但是目前对于实际工具并不实用。

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

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

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

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

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

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


2
嗨,艾拉(Ira),您是否发表了有关diff算法的论文?我在查找树编辑距离差异文献时遇到了麻烦。谢谢,特伦斯。
Terence Parr 2010年

更具体地说,寻找diff3不是普通的diff2
Terence Parr 2010年

2
@Terence:我们的diff算法尚无任何出版物。这是Levenstein最小距离计算,使用后缀树来标识相等的子树,并带有一些操作方法来处理重命名。在IIRC上,Yang在“软件实践和经验”中对此进行了研究。我们和杨的是diff2,而不是diff3。
艾拉·巴克斯特

@IraBaxter从Google链接打开时,链接当前已断开,站点似乎已关闭。
拉兹万·弗拉维斯·熊猫

网站已备份,链接应该可以。
伊拉·巴克斯特

12

您正在寻找的是“ tree diff”。事实证明,这比简单的面向行的文本差异要难得多,后者实际上只是两个平面序列的比较。

细粒度的XML结构比较方法 ”部分总结为:

我们的理论研究和实验评估表明,相对于现有替代方法,该方法在结构上具有相似性,同时具有相同的时间复杂度(O(N ^ 2))

(强调我的)

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


感谢您的链接。我可以想到几种实现语义差异工具的方法,您是正确的-大多数可以抽象为“树差异”。甚至可能需要将更复杂的情况抽象为“图形差异”。
贾森梅里2009年

是的 IBM的Rational Modeler(基于eclipse构建)试图使用UML模型来做到这一点(以图形方式显示两个模型之间的差异)。由于使用的次数很少,因此我无法评论结果的实用性。
bentin

我同意XML是一个很好的起点,因为您可以简单地提出表示其他结构的模式(例如Java代码),并使用基于XML的tree-diff来实现代码diff。
贾森姆雷,2009年

“执行此操作” =>执行类似于“图形差异”的操作。

1
有关适用多种语言的基于语法树的比较引擎,请参见semdesigns.com/Products/SmartDifferencer/index.html
Ira Baxter,2009年


2

解决方案将基于每种语言。也就是说,除非它设计的插件体系结构将许多代码解析成一棵树,并将语义与特定于语言的插件进行比较,否则将很难支持多种语言。您对使用这种工具感兴趣的语言是什么。就个人而言,我会喜欢C#。

对于C#,在Reflector中有一个程序集差异加载项,但它仅对IL而不是C#进行差异。

您也可以下载差异外接这里 [拉链]或前往项目在CodePlex上的网站在这里


1
请参阅semdesigns.com/Products/SmartDifferencer/index.html,以获取基于语法树的比较引擎,该引擎可使用多种语言,并且完全使用语言插件样式。尚未发布,但是C#版本非常接近。
伊拉·巴克斯特

2010年1月:发布了C#Smart Differencer。
艾拉·巴克斯特

2

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


链接到二进制级别的语义差异:zynamics.com/bindiff.html
emallove

2

http://prettydiff.com/

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


5
那你的想象力就有限了!交换文件中两个方法的位置同时保持不变,该怎么办?重构呢?
罗宾·格林

(由于初始化程序的原因,您不能以这种方式在Java中交换数据声明,并且仍然具有等效性;我认为C#也有类似的麻烦)。如果您寻求纯语义差异,那么您正在尝试解决图灵机对等问题。有很多方面可以做得比纯文本更好,而比图灵还差。
艾拉·巴克斯特

@IraBaxter该工具在概念上显然只会显示为实际上是等效的等效对象。如果编码正确,它将不会出现您提到的问题类型。
的Răzvan弗拉菲乌斯熊猫

如果您想要最终的工具,“正确编码”表示证明算法等效。一般来说,算法等效性证明是图灵硬的,因此您在实践中不会获得这样的工具。您可能会得到一个处理一些等同功能的工具,而不仅仅是语法更改。迄今为止,我还没有看到有人尝试构建这样的工具。
伊拉·巴克斯特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.