Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gradle's PMD plugin: what are acceptable arguments?

Tags:

java

gradle

pmd

  • Java 1.7.0_40
  • Gradle 1.10

I've never used Gradle's PMD plugin and I'm running into trouble trying to add rule sets to my build.gradle. The Pmd documentation is not clear about what the valid values of ruleSets are. Their example is ruleSets = ["basic", "braces"] and they link to the "official list". There's not much to go on, unfortunately.

I was guessing the section title maps to the valid string somehow? Like,

  • "Basic (java)" -> "basic"
  • "Braces (java)" -> "braces"

But what about things like "Empty Code (java)"?

Here's a working build.gradle example:

apply plugin: 'java'
apply plugin: 'pmd'

pmd {
    ruleSets = [
            // The first two better work since it's right in the Javadoc...
            "basic",
            "braces",
            // This one does not work and other variations like 
            // "empty code", "emptycode", "empty-code", "empty_code" do not work.
            "emptyCode"
    ]
}
repositories {
    mavenCentral()
}

Gradle spits out the following error:

$ gradle check
:pmdMain FAILED                                                                  

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':pmdMain'.
> Can't find resource emptyCode.  Make sure the resource is a valid file or URL 
    or is on the CLASSPATH.  Here's the current classpath:
    /Users/kuporific/gradle/gradle-1.10/lib/gradle-launcher-1.10.jar

* Try:        
Run with --stacktrace option to get the stack trace. Run with --info or --debug 
    option to get more log output.

BUILD FAILED  

Total time: 9.907 secs

Running with --stacktrace or --debug as suggested doesn't seem to yield anything useful...

Note: create a dummy file like src/main/java/Dummy.java. Otherwise, the build will succeed.

How are ruleSets supposed to be declared?


Edit:

It ended up being easier declaring an xml rule set because it offers fine-grained control over the rules. It is included in build.gradle like so:

apply plugin: 'pmd'

pmd {
    ruleSetFiles = files('path/to/ruleSet.xml')
}

And the rule set file looks something like this:

Note: This exaple is written for Gradle 1.10. Newer versions of Gradle (circa 2.0) use a newer version of PMD; therefore, many of the rulesets paths changed. So rulesets/logging-java.xml is now found in rulesets/java/logging-java.xml, for example.

<?xml version="1.0" encoding="UTF-8"?>
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    name="Android Application Rules"
    xmlns="http://pmd.sf.net/ruleset/1.0.0"
    xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"
    xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 
                        http://pmd.sf.net/ruleset_xml_schema.xsd" >

    <rule ref="rulesets/logging-java.xml" />
    <rule ref="rulesets/basic.xml" />
    <rule ref="rulesets/braces.xml" />
    <rule ref="rulesets/codesize.xml" >
        <exclude name="TooManyMethods" />
    </rule>
    <rule ref="rulesets/controversial.xml">
        <exclude name="UseConcurrentHashMap" />
        <exclude name="AvoidLiteralsInIfCondition" />
        <exclude name="DataflowAnomalyAnalysis" />
        <exclude name="CallSuperInConstructor" />
        <exclude name="AtLeastOneConstructor" />
        <exclude name="NullAssignment" />
    </rule>
    <!-- etc... -->
</ruleset>
like image 743
kuporific Avatar asked Dec 20 '13 19:12

kuporific


People also ask

What are PMD rules?

Conceptually, PMD rules work by matching a “pattern” against the AST of a file. Rules explore the AST and find nodes that satisfy some conditions that are characteristic of the specific thing the rule is trying to flag. Rules then report a violation on these nodes.

What is PMD violations in Java?

PMD violations are assigned a priority from 1 (most severe) to 5 (least severe) according the the rule's priority. Violations at or less than this priority level are considered failures and will fail the build if failOnViolation=true and the count exceeds maxAllowedViolations .

What is gradle PMD plugin?

plugins { pmd } The plugin adds a number of tasks to the project that perform the quality checks. You can execute the checks by running gradle check . Note that PMD will run with the same Java version used to run Gradle.


2 Answers

The latest version of PMD (5.1.3 when writing this answer) is supported by gradle. The rulesets need to be prefixed by a java-

I tested this with gradle-1.12

To use PMD 5.1.3 with gradle, the following configuration defines all the possibles rulesets I could find:

pmd {
    toolVersion = '5.1.3'
    ruleSets = [
            'java-android',
            'java-basic',
            'java-braces',
            'java-clone',
            'java-codesize',
            'java-comments',
            'java-controversial',
            'java-coupling',
            'java-design',
            'java-empty',
            'java-finalizers',
            'java-imports',
            'java-j2ee',
            'java-javabeans',
            'java-junit',
            'java-logging-jakarta-commons',
            'java-logging-java',
            'java-migrating',
            'java-naming',
            'java-optimizations',
            'java-strictexception',
            'java-strings',
            'java-sunsecure',
            'java-typeresolution',
            'java-unnecessary',
            'java-unusedcode'
            ]
}

Reference: http://forums.gradle.org/gradle/topics/_pmdtest_fails_with_cant_find_resource_null_when_rulesets_include_braces_gradle_2_0_rc_1

like image 142
Tuxdude Avatar answered Sep 25 '22 07:09

Tuxdude


I realize this is a huge edit, but it's essentially a different answer. So after speaking to you and playing around with it, I've determined that the Gradle plugin uses a slightly older version of the pmd library than is published (namely, version 4.3); however, there are a few rulesets missing from the plugin since the most recent pmd version is 5.0.5 which breaks with a NullPointerException with Gradle and Java. Now, after writing possibly the most syntactically correct and painstaking Hello World Java program of my life to test all of these, I've compiled every single Java rule-set that works with the Gradle plugin at the moment:

here's the Main.java:

package william;
import java.util.logging.Logger;

public final class Main{
    private Main(){}
    public static void main(final String [ ] args){
        final Logger log = Logger.getLogger(Main.class.getName());
        log.fine("Hello World");
    }
}

here's the build.gradle:

apply plugin: 'java'
apply plugin: 'pmd'

pmd {
    ruleSets = [
            "basic",
            "braces",
            "naming",
            "android",
            "clone",
            "codesize",
            "controversial",
            "design", 
            "finalizers",
            "imports",
            "j2ee",
            "javabeans",
            "junit",
            "logging-jakarta-commons",
            "logging-java",
            "migrating",
            "optimizations",
            "strictexception",
            "strings",
            "sunsecure",
            "typeresolution",
            "unusedcode"
            ]
}
repositories {
    mavenCentral()
}

and now you might be wondering, which rulesets AREN'T supported yet? well the answer is:

  1. "comments"
  2. "empty"
  3. "unnecessary"

Trust me when I say, the rest of the rules work flawlessly. They tore me apart when writing a Hello World. So, I hope this helps, the directory that has all of the Java rulesets.xml files defined is at: link to pmd's github java ruleset directory I ignore the migrate ones, because they didn't work. I think they're for something specific.

Good luck, and I would bring up the issue of the missing rulesets on the gradle forums to petition to get them added, or update the version. Or you could custom compile the plugin and link it to the newer pmd version if you are really desperate for the missing rulesets.

like image 38
WillBD Avatar answered Sep 23 '22 07:09

WillBD