質問

I'd like to use Copy/Paste Detector in my Gradle build.

This is why I've decided to translate the following Ant task (which I've found here) into Gradle syntax:

<target name="cpd">
    <taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask" />
    <cpd minimumTokenCount="100" outputFile="/home/tom/cpd.txt">
        <fileset dir="/home/tom/tmp/ant">
            <include name="**/*.java"/>
        </fileset>
    </cpd>
</target>

This is how the translation looks currently:

check << {
        ant.taskdef(name: 'cpd', classname: 'net.sourceforge.pmd.cpd.CPDTask', classpath: configurations.pmd.asPath)
        ant.cpd(minimumTokenCount: '100', outputFile: file('build/reports/pmd/copyPasteDetector.txt').toURI().toString()) {
            fileset(dir: 'src'){
                include(name: '**.java')
        }
    }
}

Unfortunately calling gradle check yields an net.sourceforge.pmd.cpd.ReportException, the stacktrace is here.

How can I scan my source code with the Copy/Paste Detector using Gradle 1.9?

Thanks!

役に立ちましたか?

解決 3

The definition of my outputFile caused the problem.

I adapted this build.gradle and I'm now happy with the following solution:

check << {
    File outDir = new File('build/reports/pmd/')
    // Make sure the output dir exists to prevent a ReportException
    outDir.mkdirs()

    ant.taskdef(name: 'cpd', classname: 'net.sourceforge.pmd.cpd.CPDTask',
                classpath: configurations.pmd.asPath)

    ant.cpd(minimumTokenCount: '100', format: 'text', 
        outputFile: new File(outDir , 'cpd.txt')) {
        fileset(dir: "src/main/java") {
            include(name: '**/*.java')
        }
    }
}

Thanks Andrey Regentov and Perryn Fowler for their input.

他のヒント

You can also use my gradle-cpd-plugin. See https://github.com/aaschmid/gradle-cpd-plugin for further informationen. Applying the cpd plugin automatically adds it the cpd as dependency of check task.

Note: I am not very happy with the name cpd for extension (see toolVersion) and task, suggestions welcome ;-)

Currently, it is version 0.1 but I am on it to switch from using CPD's ant task internally to directly call it. This will include support of all parameters etc. Here is a usage example:

apply plugin: 'cpd'

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'de.aaschmid.gradle.plugins:gradle-cpd-plugin:0.1'
    }
}

// optional - default is 5.1.0
cpd {
    toolVersion = '5.0.5'
}

tasks.cpd {
    reports {
        text.enabled = true
        xml.enabled = false
    }
    source = files('src/main/java')
}

Guys from gradle forums suggest that you use CPD in gradle like that:

task cpd(dependsOn: ':pmdSetup') {
    // Combine all source sets
    allSource = files {
        allprojects.findAll { proj ->
            proj.hasProperty("sourceSets")
        }.collect { proj ->
            proj.sourceSets.collect { ss ->
                ss.java
            }
        }
    }
    // Declare this task's inputs and outputs.
    inputs.files allSource
    outDir = file("$buildDirName/cpd")
    outputs.dir outDir
    //    outputs.files file("$outDir.path/cpd.xml")
    doLast {
        outDir.mkdirs()
        // Keep a reference to the gradle project for use inside the
        // ant closure, where "project" refers to the ant project.
        gproj = project
        ant {
            cpd(minimumTokenCount: '100', format: 'xml',
                    outputFile: outDir.path + '/cpd.xml') {
                fileset(dir: projectDir.getPath()) {
                    // Convert the gradle sourceSet to an ant
                    // fileset.
                    allSource.each { file ->
                        include(name: gproj.relativePath(file))
                    }
                }
            }
        }
    }
}

and, of course, apply plugin: 'pmd' before.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top