我们的CloneDR 工具通过比较来自解析器的抽象语法树来查找重复代码。 (它有多种语言的特定语言版本,包括 Java 和 JavaScript)。
这意味着尽管格式更改和克隆主体的修改,它仍然可以找到克隆的代码,这两者通常在克隆时完成。找到的克隆匹配语言概念,例如表达式、声明、语句、函数,甚至类。报告相似的克隆以及差异/变异点作为建议的参数。
它可以找到具有多个实例的克隆集(我们有一些应用程序包含数百个单个代码的克隆),并且它可以跨许多源文件查找克隆。
它生成可供人们直接阅读的 HTML 报告,以及可由其他下游工具处理的 XML 报告。 (您可以通过链接查看一些示例 HTML 报告)。
相似性很难定义,实际上你可以通过多种方式定义它。 CloneDR 将其定义为克隆集中相同元素(技术上是 AST 节点)的比率除以整个克隆集中的元素总数。该比率是一个介于 0 和 1 之间的值。它与阈值进行比较;我们发现,就报告的克隆质量而言,95% 作为阈值具有惊人的稳健性。
为有趣的克隆建立最小大小很有用。 a*b 是 x*y 的克隆(带有 2 个参数),但由于它太小,因此无法报告。 CloneDR 还使用我们称为“行数”的大小阈值,但实际上是元素中克隆的大小除以整个代码库中每行的平均元素数。这会产生通常比阈值多行的克隆,但它会为一行内的大量表达式找到克隆。我们发现 5-6 条“线”在报告的克隆质量方面也相当可靠。
此表显示了 CloneDR 的 AST 匹配方法与许多其他克隆检测工具相比的有效性(将其评为“非常好”)。唯一接近的是 CCDIML ...。这是对 CloneDR 方法的学术重新实施。还有其他方法(即基于 PDG 的方法)可以更有效地检测分散的克隆,但在实践中,根据我的个人经验,克隆代码的人通常不会将克隆的部分切割成一堆单独的部分以分散他们;他们太懒了。 YMMV。
[表格来自:Roy、Cordy、Koschke:代码克隆检测技术和工具的比较和评估:一种定性方法,计算机编程科学,第 74 卷第 7 期,2009 年 5 月。本文概述了许多不同的克隆检测方法并评估其有效性。]
[PMD 未列出,但显然使用 Rabin-Karp 字符串匹配,根据上表“基于文本”,而不是 AST 匹配。]
关于 OP 的要求:
CloneDR(实际上我不知道任何工具)不会在多个方法中找到一组相似的方法,如果这些方法在不同的类中以不同的顺序出现。在这种情况下,CloneDR 更有可能将单个方法报告为克隆;最终结果是一样的。如果成员在不同的类中以相同的顺序依次出现,它将找到这样一个集合,就像一个类主体从另一个类主体被批量复制时发生的那样。
跨多种方法的相似代码块很常见。生成的报告显示了相似代码块的相关性,包括代码的抽象版本,它本质上是方法体所需的参数化代码块。