禁止来自CPD的C / C ++代码警告

时间:2016-06-03 09:08:53

标签: c++ c pmd static-code-analysis cpd

我们正在使用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, '$1$2')
} else {
  println 'No duplication found.'
}

outputFile.write xmlOutput

4 个答案:

答案 0 :(得分:3)

您可以定义自定义标记,以便通过--skip-blocks-pattern选项从分析中排除某些块。

  

- skip-blocks-pattern 模式以查找要跳过的块。开始和结束模式由|分隔。默认值为#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分隔的代码内执行复制粘贴检测。

答案 1 :(得分:2)

在GitHub上搜索PMD的代码之后,我想我可以肯定地说这个时候支持 NOT (当前版本是PMD 5.5.0)。

在其存储库中搜索CPD-START,但未在pmd-cpp目录中显示任何结果(请参阅the search results on GitHub)。

答案 2 :(得分:0)

我知道这是一个已有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,则所有文件将被忽略,直到文件结尾。

答案 3 :(得分:-1)

我对CPD没有任何帮助。一般来说,我知道这些工具;我不明白“警告”。

我们的CloneDR tool finds exact and near-miss duplicate code。恕我直言,它发现比CPD更好的克隆,因为它使用语言语法/结构作为指导。 [这个事实得到了第三方所做的研究报告的支持,你可以在网站上找到]。并且它不会发出“警告”。

如果代码,它认为该代码包含在克隆中,该工具将为所涉及的克隆生成输出报告页面。但这不是一个警告。无法抑制报告行为。显然,如果您已经看过这样一个克隆并且认为它没有意义,那么您可以使用注释标记其中一个克隆条目,表明它是一个无趣的克隆;该评论将显示在克隆报告中。 (此类)注释对CloneDR检测到的克隆没有任何影响,因此添加它们不会改变计算出的答案。