抑制 CPD 对 C/C++ 代码的警告
Suppress warnings from CPD for C/C++ code
我们正在使用 PMD 复制粘贴检测器 (CPD) 来分析我们的 C 和 C++ 代码。
但是,代码中有几部分非常相似,但有充分的理由,我们希望抑制这些部分的警告。
documentation of PMD CPD 只提到了一些关于注释的东西,但这对我们这些语言不起作用。
如何仍然忽略特定部分的警告?
是否有评论可以这样做?
[更新] 我正在使用以下 Groovy 脚本来 运行 CPD:
@GrabResolver(name = 'jcenter', root = 'https://jcenter.bintray.com/')
@Grab('net.sourceforge.pmd:pmd-core:5.4.+')
@Grab('net.sourceforge.pmd:pmd-cpp:5.4.+')
import net.sourceforge.pmd.cpd.CPD
import net.sourceforge.pmd.cpd.CPDConfiguration
import java.util.regex.Pattern
def tokens = 60
def scanDirs = ['./path/to/scan', './scan/this/too']
def ignores = [
'./ignore/this/path',
'./this/must/be/ignored/too'
].collect({ it.replace('/', File.separator) })
def rootDir = new File('.')
def outputDir = new File('./reports/analysis/')
def filename_date_format = 'yyyyMMdd'
def encoding = System.getProperty('file.encoding')
def language_converter = new CPDConfiguration.LanguageConverter()
def config = new CPDConfiguration()
config.language = new CPDConfiguration.LanguageConverter().convert('c')
config.minimumTileSize = tokens
config.renderer = config.getRendererFromString 'xml', 'UTF-8'
config.skipBlocksPattern = '//DUPSTOP|//DUPSTART'
config.skipLexicalErrors = true
def cpd = new CPD(config)
scanDirs.each { path ->
def dir = new File(path);
dir.eachFileRecurse(groovy.io.FileType.FILES) {
// Ignore file?
def doIgnore = false
ignores.each { ignore ->
if(it.path.startsWith(ignore)) {
doIgnore = true
}
}
if(doIgnore) {
return
}
// Other checks
def lowerCaseName = it.name.toLowerCase()
if(lowerCaseName.endsWith('.c') || lowerCaseName.endsWith('.cpp') || lowerCaseName.endsWith('.h')) {
cpd.add it
}
}
}
cpd.go();
def duplicationFound = cpd.matches.hasNext()
def now = new Date().format(filename_date_format)
def outputFile = new File(outputDir.canonicalFile, "cpd_report_${now}.xml")
println "Saving report to ${outputFile.absolutePath}"
def absoluteRootDir = rootDir.canonicalPath
if(absoluteRootDir[-1] != File.separator) {
absoluteRootDir += File.separator
}
outputFile.parentFile.mkdirs()
def xmlOutput = config.renderer.render(cpd.matches);
if(duplicationFound) {
def filePattern = "(<file\s+line=\"\d+\"\s+path=\")${Pattern.quote(absoluteRootDir)}([^\"]+\"\s*/>)"
xmlOutput = xmlOutput.replaceAll(filePattern, '')
} else {
println 'No duplication found.'
}
outputFile.write xmlOutput
在 GitHub 上搜索 PMD 的代码后,我想我可以有把握地说,目前不支持(当前版本是 PMD 5.5.0).
在他们的存储库中搜索 CPD-START
,在 pmd-cpp
目录中没有显示任何结果(参见 the search results on GitHub)。
您可以通过 --skip-blocks-pattern
选项定义自定义标记以将某些块排除在分析之外。
--skip-blocks-pattern Pattern to find the blocks to skip. Start and End pattern separated by |. Default is #if 0|#endif
.
例如,以下将忽略 /* SUPPRESS CPD START */
和 /* SUPPRESS CPD END */
注释之间的块(注释必须单独占一行):
$ ./run.sh cpd --minimum-tokens 100 --files /path/to/c/source --language cpp ----skip-blocks-pattern '/* SUPPRESS CPD START */|/* SUPPRESS CPD END */'
但是请注意,这将导致该工具在由 #if 0
/#endif
.
分隔的代码内执行复制粘贴检测
我对 CPD 没有任何帮助。总的来说,我知道这些工具;我不明白 "warnings".
我们的CloneDR tool finds exact and near-miss duplicate code。恕我直言,它找到了比 CPD 更好的克隆,因为它使用语言语法/结构作为指导。 [这个事实得到了第三方所做的研究报告的支持,您可以在网站上找到]。而且它不会发出 "warnings".
如果它认为是 代码涉及克隆,该工具将为涉及的克隆生成输出报告页面。但这不是警告。没有办法抑制报告行为。显然,如果您已经看到这样的克隆并认为它不有趣,您可以用注释标记其中一个克隆条目,说明它是一个无趣的克隆;该评论将显示在克隆报告中。 (这样的)评论对 CloneDR 检测到的克隆没有任何影响,因此添加它们不会改变计算出的答案。
我知道这是一个 ~3 年前的问题,但为了完整起见,CPD 在 Java 的 PMD 5.6.0(2017 年 4 月)中开始支持这个问题,并且从 6.3.0(2018 年 4 月)开始已扩展到许多其他语言,例如 C/C++。如今,几乎所有 CPD 支持的语言都允许基于评论的抑制。
有关基于评论的抑制的完整(当前)文档可在 https://pmd.github.io/pmd-6.13.0/pmd_userdocs_cpd.html#suppression
获得
值得注意的是,如果文件有 // CPD-OFF
注释,但没有匹配的 // CPD-ON
,所有内容都将被忽略,直到文件结束。
我们正在使用 PMD 复制粘贴检测器 (CPD) 来分析我们的 C 和 C++ 代码。 但是,代码中有几部分非常相似,但有充分的理由,我们希望抑制这些部分的警告。
documentation of PMD CPD 只提到了一些关于注释的东西,但这对我们这些语言不起作用。
如何仍然忽略特定部分的警告?
是否有评论可以这样做?
[更新] 我正在使用以下 Groovy 脚本来 运行 CPD:
@GrabResolver(name = 'jcenter', root = 'https://jcenter.bintray.com/')
@Grab('net.sourceforge.pmd:pmd-core:5.4.+')
@Grab('net.sourceforge.pmd:pmd-cpp:5.4.+')
import net.sourceforge.pmd.cpd.CPD
import net.sourceforge.pmd.cpd.CPDConfiguration
import java.util.regex.Pattern
def tokens = 60
def scanDirs = ['./path/to/scan', './scan/this/too']
def ignores = [
'./ignore/this/path',
'./this/must/be/ignored/too'
].collect({ it.replace('/', File.separator) })
def rootDir = new File('.')
def outputDir = new File('./reports/analysis/')
def filename_date_format = 'yyyyMMdd'
def encoding = System.getProperty('file.encoding')
def language_converter = new CPDConfiguration.LanguageConverter()
def config = new CPDConfiguration()
config.language = new CPDConfiguration.LanguageConverter().convert('c')
config.minimumTileSize = tokens
config.renderer = config.getRendererFromString 'xml', 'UTF-8'
config.skipBlocksPattern = '//DUPSTOP|//DUPSTART'
config.skipLexicalErrors = true
def cpd = new CPD(config)
scanDirs.each { path ->
def dir = new File(path);
dir.eachFileRecurse(groovy.io.FileType.FILES) {
// Ignore file?
def doIgnore = false
ignores.each { ignore ->
if(it.path.startsWith(ignore)) {
doIgnore = true
}
}
if(doIgnore) {
return
}
// Other checks
def lowerCaseName = it.name.toLowerCase()
if(lowerCaseName.endsWith('.c') || lowerCaseName.endsWith('.cpp') || lowerCaseName.endsWith('.h')) {
cpd.add it
}
}
}
cpd.go();
def duplicationFound = cpd.matches.hasNext()
def now = new Date().format(filename_date_format)
def outputFile = new File(outputDir.canonicalFile, "cpd_report_${now}.xml")
println "Saving report to ${outputFile.absolutePath}"
def absoluteRootDir = rootDir.canonicalPath
if(absoluteRootDir[-1] != File.separator) {
absoluteRootDir += File.separator
}
outputFile.parentFile.mkdirs()
def xmlOutput = config.renderer.render(cpd.matches);
if(duplicationFound) {
def filePattern = "(<file\s+line=\"\d+\"\s+path=\")${Pattern.quote(absoluteRootDir)}([^\"]+\"\s*/>)"
xmlOutput = xmlOutput.replaceAll(filePattern, '')
} else {
println 'No duplication found.'
}
outputFile.write xmlOutput
在 GitHub 上搜索 PMD 的代码后,我想我可以有把握地说,目前不支持(当前版本是 PMD 5.5.0).
在他们的存储库中搜索 CPD-START
,在 pmd-cpp
目录中没有显示任何结果(参见 the search results on GitHub)。
您可以通过 --skip-blocks-pattern
选项定义自定义标记以将某些块排除在分析之外。
--skip-blocks-pattern Pattern to find the blocks to skip. Start and End pattern separated by |. Default is
#if 0|#endif
.
例如,以下将忽略 /* SUPPRESS CPD START */
和 /* SUPPRESS CPD END */
注释之间的块(注释必须单独占一行):
$ ./run.sh cpd --minimum-tokens 100 --files /path/to/c/source --language cpp ----skip-blocks-pattern '/* SUPPRESS CPD START */|/* SUPPRESS CPD END */'
但是请注意,这将导致该工具在由 #if 0
/#endif
.
我对 CPD 没有任何帮助。总的来说,我知道这些工具;我不明白 "warnings".
我们的CloneDR tool finds exact and near-miss duplicate code。恕我直言,它找到了比 CPD 更好的克隆,因为它使用语言语法/结构作为指导。 [这个事实得到了第三方所做的研究报告的支持,您可以在网站上找到]。而且它不会发出 "warnings".
如果它认为是 代码涉及克隆,该工具将为涉及的克隆生成输出报告页面。但这不是警告。没有办法抑制报告行为。显然,如果您已经看到这样的克隆并认为它不有趣,您可以用注释标记其中一个克隆条目,说明它是一个无趣的克隆;该评论将显示在克隆报告中。 (这样的)评论对 CloneDR 检测到的克隆没有任何影响,因此添加它们不会改变计算出的答案。
我知道这是一个 ~3 年前的问题,但为了完整起见,CPD 在 Java 的 PMD 5.6.0(2017 年 4 月)中开始支持这个问题,并且从 6.3.0(2018 年 4 月)开始已扩展到许多其他语言,例如 C/C++。如今,几乎所有 CPD 支持的语言都允许基于评论的抑制。
有关基于评论的抑制的完整(当前)文档可在 https://pmd.github.io/pmd-6.13.0/pmd_userdocs_cpd.html#suppression
获得值得注意的是,如果文件有 // CPD-OFF
注释,但没有匹配的 // CPD-ON
,所有内容都将被忽略,直到文件结束。