Automated Code review for Apex in Salesforce – Static code analysis – Video

Using open source PMD tool to generate code quality report for Apex classes

Automated code review for apex in salesforce (static code analysis)

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

  1. We can run static code analysis standalone
  2. It can be part of ANT build to generate error reports
  3. Jenkins can use it to generate nice report around code quality
  4. 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

Sample command to run PMD from console
Sample command to run PMD from console

Below is sample code quality report generated

Apex code quality report
Apex code quality report

Youtube video

Related posts

11 thoughts on “Automated Code review for Apex in Salesforce – Static code analysis – Video”

    1. 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.

  1. 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

  2. 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?

    1. 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

  3. 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

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.