PMD is very well known source code analyzer for Java, android and many more languages. Good news for us (Salesforce developers) is , that it supports now Apex. You might be thinking how can we make PMD as part of our daily life ?
There are multiple ways
- We can run static code analysis standalone
- It can be part of ANT build to generate error reports
- Jenkins can use it to generate nice report around code quality
- Eclipse can use it as a plugin to generate report
In this blog post, we will discuss option 1, that is running it as a standalone application to generate code quality report.
First Step is to download jar file of latest PMD distribution from here.
Next step is to define some rules for your code base. Sample rules can be seen here. We can also create our own rule as per need. For this blog post, I would be using below rules.
Apex Rules.xml
<?xml version="1.0"?> <ruleset name="Apex Rules" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd"> <rule name="AvoidDeeplyNestedIfStmts" message="Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain." class="net.sourceforge.pmd.lang.apex.rule.complexity.AvoidDeeplyNestedIfStmtsRule"> <description> Avoid creating deeply nested if-then statements since they are harder to read and error-prone to maintain. </description> <priority>3</priority> <example> <![CDATA[ public class Foo { public void bar(Integer x, Integer y, Integer z) { if (x>y) { if (y>z) { if (z==x) { // !! too deep } } } } } ]]> </example> </rule> <rule name="ExcessiveParameterList" message="Methods with numerous parameters are a challenge to maintain, especially if most of them share the same datatype. These situations usually denote the need for new objects to wrap the numerous parameters." class="net.sourceforge.pmd.lang.apex.rule.complexity.ExcessiveParameterListRule"> <description> Methods with numerous parameters are a challenge to maintain, especially if most of them share the same datatype. These situations usually denote the need for new objects to wrap the numerous parameters. </description> <priority>3</priority> <example> <![CDATA[ // too many arguments liable to be mixed up public void addPerson(int birthYear, int birthMonth, int birthDate, int height, int weight, int ssn) { ... } // preferred approach public void addPerson(Date birthdate, BodyMeasurements measurements, int ssn) { ... } ]]> </example> </rule> <rule name="ExcessiveClassLength" message="Excessive class file lengths are usually indications that the class may be burdened with excessive responsibilities that could be provided by external classes or functions. In breaking these methods apart the code becomes more managable and ripe for reuse." class="net.sourceforge.pmd.lang.apex.rule.complexity.ExcessiveClassLengthRule"> <description> Excessive class file lengths are usually indications that the class may be burdened with excessive responsibilities that could be provided by external classes or functions. In breaking these methods apart the code becomes more managable and ripe for reuse. </description> <priority>3</priority> <example> <![CDATA[ public class Foo { public void bar(Integer x, Integer y, Integer z) { if (x>y) { if (y>z) { if (z==x) { // !! too deep } } } } } ]]> </example> </rule> <rule name="NcssMethodCount" message="This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one." class="net.sourceforge.pmd.lang.apex.rule.complexity.NcssMethodCountRule"> <description> This rule uses the NCSS (Non-Commenting Source Statements) algorithm to determine the number of lines of code for a given method. NCSS ignores comments, and counts actual statements. Using this algorithm, lines of code that are split are counted as one. </description> <priority>3</priority> <example> <![CDATA[ public class Foo extends Bar { //this method only has 1 NCSS lines public Integer methd() { super.methd(); return 1; } } ]]> </example> </rule> </ruleset>
In above sample rule file, if we observe carefully, each rule is represented by rule tag. we can give it any name and then message to be displayed in report. class represents respective rule written in Java class by PMD and this information would be available here.
priority can set level of violations and this would differ as per your project. We can categorize level of violations for each rule and it helps us in reporting code quality of developer team.
Final step is to run below command from shell / command prompt. This documentation will help to understand all parameters needed to run PMD from command prompt.
pmd -d "path of folder where all apex files exists" -f html -R "path of rule file in our case above file ApexRules.xml" -reportfile "path of report to be generated"
Following image shows sample command run

Below is sample code quality report generated

Youtube video
Hi,
How to install the PMD distribution tool in windows machine??
First, you need to install Java 1.7 or above and have it added to the PATH. Later, you need to download binary distribution and run pmd.bat from bin folder providing parameters described in the article.
Hi Jitendra,
I gone through ur video.I have done all the things through referring ur video, but when requesting a preview it gives a blank page.Would you know what might be the reason.please feref the below screenhttps://uploads.disquscdn.com/images/1fb83d956a90b828180fa4786f09ec412f3575606f381ffbbb59a3a8deee1fc2.png
Hi Jitendra,
First of all your posts help me a lot,I have only one doubt how can you show example in a report.
Hi Jitendra,
First of all your posts help me a lot,I have only one doubt how can you show example in a report.
Hi Naved,
Did you get any idea to get output in report format in Salesforce?
The PMD link lists a lot of rules, but I don’t see xml rulesets I can use.
For instance, is there a ruleset that includes all the Apex complexity and style rules?
The xml rules linked by the ruleset.xml are hosted by the PMD sourceforge web site, therefore you need to be connected to internet to run the tool. Moreover, to define any new rules you need a depp knowledge both of Java and the AST preprocessor
Hi Jitendra ,
I have followed same as you mentioned in the blog.
but still i am getting below error.
Usage: pmd [options]
Options:
-failOnViolation, –failOnViolation
By default PMD exits with status 4 if violations are found. Disable this
option with ‘-failOnViolation false’ to exit with 0 instead and just write the
report.
Default: true
-auxclasspath
Specifies the classpath for libraries used by the source code. This is
used by the type resolution. Alternatively, a ‘file://’ URL to a text file
containing path elements on consecutive lines can be specified.
-benchmark, -b
Benchmark mode – output a benchmark report upon completion; default to
System.err.
Default: false
-cache
Specify the location of the cache file for incremental analysis. This
should be the full path to the file, including the desired file name (not just
the parent directory). If the file doesn’t exist, it will be created on the
first run. The file will be overwritten on each run with the most up-to-date
rule violations.
-dir, -d
Root directory for sources.
-encoding, -e
Specifies the character set encoding of the source code files PMD is
reading (i.e., UTF-8).
Default: UTF-8
-filelist
Path to a file containing a list of files to analyze.
-format, -f
Report format type.
Default: text
-help, -h, -H
Display help on usage.
Default: false
-ignorelist
Path to a file containing a list of files to ignore.
-language, -l
Specify a language PMD should use.
-minimumpriority, -min
Rule priority threshold; rules with lower priority than configured here
won’t be used. Valid values are integers between 1 and 5 (inclusive), with 5
being the lowest priority.
Default: 5
-no-cache
Explicitly disable incremental analysis. The ‘-cache’ option is ignored
if this switch is present in the command line.
Default: false
-norulesetcompatibility
Disable the ruleset compatibility filter. The filter is active by default
and tries automatically ‘fix’ old ruleset files with old rule names
Default: false
-property, -P
{name}={value}: Define a property for the report format.
Default: []
-reportfile, -r
Sends report output to a file; default to System.out.
* -rulesets, -R
Comma separated list of ruleset names to use.
-shortnames
Prints shortened filenames in the report.
Default: false
-showsuppressed
Report should show suppressed rule violations.
Default: false
-stress, -S
Performs a stress test.
Default: false
-suppressmarker
Specifies the string that marks a line which PMD should ignore; default
is NOPMD.
Default: NOPMD
-threads, -t
Sets the number of threads used by PMD.
Default: 1
-uri, -u
Database URI for sources.
-debug, -verbose, -D, -V
Debug mode.
Default: false
-version, -v
Specify version of a language PMD should use.
Mandatory arguments:
1) A java source code filename or directory
2) A report format
3) A ruleset filename or a comma-delimited string of ruleset filenames
For example:
C:\>pmd-bin-6.9.0\bin\pmd.bat -d c:\my\source\code -f html -R java-unusedcode
Languages and version suported:
apex, ecmascript, java, jsp, plsql, pom, vf, vm, wsdl, xml, xsl
Available report formats and their configuration properties are:
codeclimate: Code Climate integration.
csv: Comma-separated values tabular format.
problem – Include Problem column default: true
package – Include Package column default: true
file – Include File column default: true
priority – Include Priority column default: true
line – Include Line column default: true
desc – Include Description column default: true
ruleSet – Include Rule set column default: true
rule – Include Rule column default: true
emacs: GNU Emacs integration.
empty: Empty, nothing.
html: HTML format
linePrefix – Prefix for line number anchor in the source file.
linkPrefix – Path to HTML source.
ideaj: IntelliJ IDEA integration.
classAndMethodName – Class and Method name, pass ‘.method’ when processing a directory. default:
sourcePath – Source path. default:
fileName – File name. default:
summaryhtml: Summary HTML format.
linePrefix – Prefix for line number anchor in the source file.
linkPrefix – Path to HTML source.
text: Text format.
textcolor: Text format, with color support (requires ANSI console support, e.g. xterm, rxvt, etc.).
color – Enables colors with anything other than ‘false’ or ‘0’. default: yes
textpad: TextPad integration.
vbhtml: Vladimir Bossicard HTML format.
xml: XML format.
encoding – XML encoding format, defaults to UTF-8. default: UTF-8
xslt: XML with a XSL Transformation applied.
encoding – XML encoding format, defaults to UTF-8. default: UTF-8
xsltFilename – The XSLT file name.
yahtml: Yet Another HTML format.
outputDir – Output directory.
For example on windows:
C:\>pmd-bin-6.9.0\bin\pmd.bat -dir c:\my\source\code -format text -R rulesets/java/quickstart.xml -version 1.5 -language java -debug
C:\>pmd-bin-6.9.0\bin\pmd.bat -dir c:\my\source\code -f xml -rulesets rulesets/java/quickstart.xml,category/java/codestyle.xml -encoding UTF-8
C:\>pmd-bin-6.9.0\bin\pmd.bat -d c:\my\source\code -rulesets rulesets/java/quickstart.xml -auxclasspath lib\commons-collections.jar;lib\derby.jar
C:\>pmd-bin-6.9.0\bin\pmd.bat -d c:\my\source\code -f html -R rulesets/java/quickstart.xml -auxclasspath file:///C:/my/classpathfile
For example on *nix:
$ pmd-bin-6.9.0/bin/run.sh pmd -dir /home/workspace/src/main/java/code -f html -rulesets rulesets/java/quickstart.xml,category/java/codestyle.xml
$ pmd-bin-6.9.0/bin/run.sh pmd -d ./src/main/java/code -R rulesets/java/quickstart.xml -f xslt -property xsltFilename=my-own.xsl
$ pmd-bin-6.9.0/bin/run.sh pmd -d ./src/main/java/code -f html -R rulesets/java/quickstart.xml -auxclasspath commons-collections.jar:derby.jar
Can only specify option -format once.
Please suggest where i need to do change.
Thanks,
Jolly
same error as mentioned earlier