我们有一个相当大的代码库,400K LOC 的 C++,代码重复是个问题。是否有任何工具可以有效地检测重复的代码块?
理想情况下,这将是开发人员可以在开发过程中使用的东西,而不是偶尔运行以查看问题所在。如果我们可以将这样的工具与 CruiseControl 集成,以便在每次签到后提供报告,那也很好。
前段时间我看过Duploc,它显示了一个很好的图表,但需要一个 smalltalk 环境才能使用它,这使得自动运行它相当困难。
免费工具会很好,但如果有一些好的商业工具我也会感兴趣。
我们有一个相当大的代码库,400K LOC 的 C++,代码重复是个问题。是否有任何工具可以有效地检测重复的代码块?
理想情况下,这将是开发人员可以在开发过程中使用的东西,而不是偶尔运行以查看问题所在。如果我们可以将这样的工具与 CruiseControl 集成,以便在每次签到后提供报告,那也很好。
前段时间我看过Duploc,它显示了一个很好的图表,但需要一个 smalltalk 环境才能使用它,这使得自动运行它相当困难。
免费工具会很好,但如果有一些好的商业工具我也会感兴趣。
Simian检测 C++ 项目中的重复代码。
更新:也适用于 Java、C#、C、COBOL、Ruby、JSP、ASP、HTML、XML、Visual Basic、Groovy 源代码甚至纯文本文件
我使用了 PMD 的 Copy-and-Paste-Detector并通过使用以下包装脚本将其集成到 CruiseControl 中(确保在类路径中有 pmd jar)。
我们的支票每晚运行一次。如果您希望将输出限制为仅列出当前更改集中的文件,则可能需要一些自定义编程(想法:检查全部并仅列出涉及已更改文件之一的重复项。您必须检查所有文件,因为更改可以使用来自未更改文件的一些代码)。应该可以通过使用 XML 输出并解析结果来实现。完成后不要忘记发布该脚本;)
对于初学者,“文本”输出应该没问题,但您会希望以用户友好的方式显示结果,为此我使用 perl 脚本从 CPD 的“xml”输出生成 HTML 文件。这些可以通过将它们发布到 Cruise 的报告 jsp 所在的 tomcat 来访问。开发人员可以从那里查看它们并查看其肮脏的黑客攻击的结果:)
它运行得非常快,在 150 KLoc 代码上不到 2 秒(空行和注释不计入该数字)。
重复检查.xml:
<project name="duplicatecheck" default="cpd">
<property name="files.dir" value="dir containing your sources"/>
<property name="output.dir" value="dir containing results for publishing"/>
<target name="cpd">
<taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask"/>
<cpd minimumTokenCount="100"
language="cpp"
outputFile="${output.dir}/duplicates.txt"
ignoreLiterals="false"
ignoreIdentifiers="false"
format="text">
<fileset dir="${files.dir}/">
<include name="**/*.h"/>
<include name="**/*.cpp"/>
<!-- exclude third-party stuff -->
<exclude name="boost/"/>
<exclude name="cppunit/"/>
</fileset>
</cpd>
</target>
duplo似乎是 Duploc 中使用的算法的 C 实现。编译和安装很简单,虽然选项有限,但它似乎或多或少是开箱即用的。
这些 Debian 软件包似乎做了以下事情:
PS 对于所有与查找 [near] 重复相关的工具,都应该有一个debtags标签。(但它会叫什么?)
查看PMD 项目。
我从来没有用过,但一直想用。
好吧,你可以每晚在你的源代码库上运行一个克隆检测器。
许多克隆检测器通过比较源代码行来工作,并且只能找到完全相同的重复代码。
上面的 CCFinder 通过比较语言标记来工作,因此它对空白更改不敏感。如果只有单个标记更改(例如,将克隆中的变量 X 更改为 Y),它可以检测作为原始代码变体的克隆。
理想情况下,您想要的是上述内容,但能够找到允许变化相对任意的克隆,例如,用表达式替换变量,用块替换语句等。
我们的 CloneDR 克隆检测器针对 Java、C#、C++、COBOL、VB.net、VB6、Fortran 和各种其他语言执行此操作。可见: http ://www.semdesigns.com/Products/Clone/index.html
除了能够处理多种语言之外,CloneDR 引擎还能够处理各种输入编码样式,包括 ASCII、ISO-8859-1、UTF8、UTF16、EBCDIC、许多 Microsoft 编码和(日语)Shift-日标。
该站点有多个克隆检测运行示例报告,包括一份针对 C++ 的报告。
编辑 2014 年 2 月:现在处理所有 C++14。
CCFinderX是一个免费的(供内部使用)克隆代码检测器,支持多种编程语言(Java、C、C++、COBOL、VB、C#)。
ConQAT是一个很棒的工具,它支持 C++ 代码分析。可以找到忽略空格的重复项。具有非常方便的 gui 和控制台界面。由于它的灵活性,它不容易设置。我发现这篇博文对于设置 c++ 项目非常有用。
Same ( http://sourceforge.net/projects/same/ ) 非常简单,但它适用于文本行而不是标记,如果您使用的语言不受更高级的克隆之一支持,这很有用发现者。
您可以使用我们的SourceMeter工具来检测代码重复。它是一个命令行工具(与编译器非常相似),因此您可以轻松地将其集成到持续集成工具中,例如您提到的CruiseControl或Jenkins。
查找“相同”的代码片段相对容易,现有的工具已经可以做到这一点(参见其他答案)。
有时这是一件好事,有时不是;如果在“级别”太精细,它可能会拖慢开发时间;即试图重构这么多代码,你会失去你的目标(并且可能破坏你的里程碑和时间表)。
更难的是在没有适当文档的情况下找到多个功能/方法,它们做同样的事情但具有不同(但相似)的输入和/或算法。
如果您必须使用两种或不同的方法来做同样的事情,而程序员尝试修复一个实例但忘记(或不知道它们存在)修复其他实例,您将增加软件的风险。
TeamCity有一个强大的 .NET 和 java 代码复制引擎,可以毫不费力地作为构建系统的一部分运行。