Writing custom XPath rules for PMD

Most Java developers find static source code analysis tools very handy, PMD, CheckStyle, FindBugs being the most popular amongst them. But all of us, at some time or the other, realise that we need to have some project specific coding conventions being enforced on the developers. This article covers this need and would discuss about writing custom rules with PMD tool.

PMD comes with a set of handy rules, which more than often are sufficient for any project. In fact in many cases we would probably need to exclude some default rules being enforced, to avoid noise in the reports. However, in real life projects you also need some custom rules.

Though custom PMD rules can be written as Java code as well, this article talks about writing them using XPath queries, which is evidently an easier way to adopt. With XPath, we simply write a rule by specifying a code sample and an XPath query to verify that the violation is indeed detected. Of course PMD doesn’t apply the query on the Java code itself but rather on the Abstract Syntax Tree, which is a tree representation of the source code. More details on the AST can be found here.

Thankfully PMD also comes with a visual editor for writing the rules. This tool can be run using the designer.bat under /bin. If you are using Eclipse and have the PMD plugin installed then the designer is accessible under Eclipse Preferences > PMD. Lets now try writing a custom PMD rule. The particular rule we plan to write to enforce the use of StringBuilder instead of StringBuffer (where there are no concurrency issues, of course). For this we first write a code snippet, as follows, in the “Source code” box of the designer.

public class SomeClass {
//Consider using StringBuilder, if there
//are no concurrency issues expected
StringBuffer sb = new StringBuffer("c");

public void someMethod(){
//Some code here
StringBuffer sb = new StringBuffer("d");
}
}

The next task is to write the XPath expression. Before we do that, we press the “Go” button under “XPath Query” section first. This will generated the corresponding AST in the box and help us write the query well. And since we haven’t written any XPath query as of now, the result section below the “XPath Query” section says “XPath Query field is empty”. Now, we want to detect the presence of a StringBuffer variable, whether at class or method level. If you see the generated AST we can easily detect that the following XPath expression will find the matching lines. We use the @Image attribute to specify the name we want to detect.

//AllocationExpression/ClassOrInterfaceType
[@Image='StringBuffer']

Exporting XPath Rule

If we press the “Go” button again, the results of running the XPath query are displayed in the box below the “XPath Query” section. In our code we should get two matches, and we should see the exact matched strings if we click on the individual lines in the result Pane. We can refine the XPath query this way till we get the exact matches.

Lets now try to write another custom rule. This particular one will report a violation if the developer writes any non static method inside a Utility class. We don’t want the Utility class to be instantiated for its methods to be used. Here, we assume that all our Utility class names end with the word “Utils”. As we did last time, we first insert the following code snippet:

public class MyUtils {
//Any Utility class name ending with "Utils"
//to be regarded as a Utility class
public static void myStaticUtilMethod(String x){
//this is a static method as expected
}

public void myNonStaticUtilMethod(){
//this method should be static and violates our rule
}
}

The XPath query in this case, as follows, is quite straight forward. We are only checking for Classes (and skipping Interfaces) that end with the suffix “Utils” and then verify if there are any non-static methods in there. Click the Go button and it should detect a violation as our class does have a non-static method. To verify, change the method signature for myNonStaticUtilMethod() to make it static and press “Go” again. PMD should not report any violation now, confirming that our rule works.

//ClassOrInterfaceDeclaration
[@Interface='false'
and (ends-with(@Image, 'Utils'))
and (count(.//MethodDeclaration) > count(.//MethodDeclaration[@Static='true']))
]

The last step in getting our custom defined rules being used by PMD is to add them to a ruleset. Details on creating your own ruleset are provided here. The designer again will help you in creating the rule XMLs that you can easily copy paste in your ruleset file.

Lets create one for the last custom rule we created. To do this click Actions > Create Rule XML on the designer. You will get a pop-up which will ask you to specify the rule name and any description that goes along. For our ruleset we use the rule name as “OnlyStaticMethodsInUtilsClass” and the message text as “In Utility (ending with ‘Utils’) classes, all methods should be declared static.” which will show up as tool-tip on the IDE with violation report. We may also specify a description. Press “Create Rule XML” button and the designer will do so for you (see the screen grab below).

Exporting XPath Rule

Note that the designer specifies the class for the rule as “net.sourceforge.pmd.rules.XPathRule” on its own. The rule priority is specified at default value of 3, but you can change that. PMD users would know that priority figures of 1 = error, high priority, 2 = error, normal priority, 3 = warning, high priority, 4 = warning, normal priority and 5 = information.

Before PMD could be used with Eclipse it must be imported in your IDE. On Eclipse Preferences under “PMD” select “Import Rule Set”, browse to the ruleset file you saved the custom rules to and you would notice them being imported. Of course, we can use the ruleset from the command line as well from our build script.

With our custom rules, our favourite code quality check tool is now even more useful.

Code Analyzers

During my search for Profilers I stumbled upon some good Java code checkers or Code Analyzers and though most of you may be already aware about them would like to share my thoughts on the same. Please feel free to correct me or add your inputs to this.

Talking of Code Review or Analysis I wonder if somebody would even think about going for the wearisome task of manually locating lapses in use of Proper Syntax, code indentation, unused variables/imports, naming convention and Javadoc comments without using any automated tool to do the task. Apart from the task of deciding about what code optimizations need be done or detecting any logical blunder rest can perhaps be safely left to these tools. Moreover more ambitious programmers can even look for these tools to operate in tight integration with their favorite IDEs. Fortunately my favorite Netbeans has many modules already available of which three are my personal favorites : PMD, Jalopy and Checkstyle, perhaps in that order.

All the three have various plugins available for various IDEs. Jalopy is a code formatter and beautifier and is highly configurable using code snippets though it does not comprehend well line spacing and tabs for files edited by other IDEs say Kawa or Textpad. Checkstyle is more about code formatting and nit-pickingly looks for white spaces, tabs, position of braces and javadocs and configuration is difficult (as far as I know certainly not configurable through Netbeans GUI). Out of these PMD deserves my high regard, here is a synopsis of what it can detect:

  • Unused local variables, parameters and private methods (very useful)
  • Empty catch blocks
  • Empty ‘if’ statements
  • Duplicate import statements
  • Classes which could be Singletons
  • Short/long variable and method names

A lesser known but very powerful code checking tool is FindBugs. Too bad it has no plugin available for Netbeans though. While the conclusions of the tool about unread fields is not very accurate, it detects what many others don’t such as:

  • Null pointer de-reference detector
  • Ignored returns from method
  • Unclosed I/O streams
  • Objecting usage of == or != for String comparison

Here are some other tools:

  • SourceMonitor: Provides size and complexity metrics for your source code.
  • JLint: A Code verifier
  • QStudio also seems pretty good to me. As per their site it is available for download with a year license at no cost.

P.S.: This post finds mention here, here, here and here.