After I began to use PMD and tried to write my first custom XPath rules, I realised that there aren’t very much information about it. So I needed to figure out almost everything by myself. Here I’ll try to explain what I’ve figured out.
I use Eclipse 3.5 to run the rules, by the way.
1. Create a new ruleset file as described here.
2. Check if you need a special encoding for the language you are going to use. I was using a norwegian language, so I needed to add encoding=”ISO-8859-1″ to xml header:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?> ...
3.Begin writing a custom rule:
<rule name="MoreThanOneLoggUtil" message="You are using more that one LoggUtil instance. Only one is legal." class="net.sourceforge.pmd.rules.XPathRule" externalInfoUrl=""> <description> You are using more that one LoggUtil instance. Only one is legal. </description> <priority>4</priority> <properties> <property name="xpath"> <value> ... (some XPath code here) ... </value> </property> </properties> <example> <![CDATA[ public class Foo private LoggUtil log = new LoggUtil(Foo.class); private LoggUtil log2 = new LoggUtil(Foo.class); ]]> </example> </rule>
4. Fill inn XPath code.
XPath code starts with CDATA-tag:
<![CDATA[ ... ]]>
Then you fill inn the main identifier, f.ex.:
<![CDATA[ //ClassOrInterfaceBodyDeclaration [ ... ] ]]>
The most important thing here is that it’s legal to use only ONE main identifier with annotation “//”. If you want to implement a complex logic you need to write it within [] braces.
Here we are going to count how many LoggUtil instances does the class have, så vi use a count() function and “VariableDeclarator”-identifier::
count(//VariableDeclarator[../Type/ReferenceType/ClassOrInterfaceType[@Image='LoggUtil']])>1
So the end custom rule here will look like this:
<rule name="MoreThanOneLoggUtil" message="You are using more that one LoggUtil instance. Only one is legal." class="net.sourceforge.pmd.rules.XPathRule" externalInfoUrl=""> <description> You are using more that one LoggUtil instance. Only one is legal. </description> <priority>4</priority> <properties> <property name="xpath"> <value> <![CDATA[ //ClassOrInterfaceBodyDeclaration [ count(//VariableDeclarator[../Type/ReferenceType/ClassOrInterfaceType[@Image='LoggUtil']])>1 ] ]]> </value> </property> </properties> <example> <![CDATA[ public class Foo private LoggUtil log = new LoggUtil(Fooclass); private LoggUtil log2 = new LoggUtil(Foo.class); ]]> </example> </rule>
Look here for more examples.
Senior Software Engineer developing all kinds of stuff.