Preparatory work
First download the latest version of the file on the PMD website, currently the latest version is 5.4.1.
After downloading Pmd-bin-5.4.1.zip and Pmd-src-5.4.1.zip, unzip the backup.
pmd-src-5.4.1 is the PMD source package, it cannot be executed directly.
pmd-bin-5.4.1 is the PMD executable package
Catalog Introduction
pmd-src-5.4.1In addition pmd-core to the core of PMD execution scheduling module, the other folders are the various language check rules of the module.
The pmd-bin-5.4.1\lib directory in which the execution is dependent on the jar package.
pmd-bin-5.4.1\binDescription of the file in the directory:
pmd.batAnd the run.sh files are run under Windows and Linux platforms, respectively.
Examples of Use:
c:\tmp\pmd-bin-5.4.1\pmd\bin>pmd-d c:\data\pmd\pmd\test-data\Unused1.java-f Xml-r Rulesets/java/unusedcode.xml<?xml version= "1.0", < PMD ; <file Span class= "Hljs-attribute" >name = "C:\data\pmd\pmd\test-data\Unused1.java" ; <violation line = "5" rule = "unusedlocalvariable" ; Avoid unused local variables such as ' FR ' Span class= "Hljs-tag" ></violation ; </< Span class= "Hljs-title" >file ; </PMD
bgastviewer.batAnd designer.bat is an interface tool that transforms source code into an AST (abstract syntax tree), which is designer.bat more commonly used.
cpd.batAnd cpdgui.bat is a tool for finding duplicate code (cpd:copy/paste Detector).
Custom rule Implementation Ideas
- Define the rules you want to customize.
- Enumerate all the different ways in which this rule will be violated.
- Use Designer.bat to analyze the characteristics of all abstract syntax trees.
- Write rule code to capture this feature.
- Create your own XML rule file that includes information about the rule.
- Run the PMD scan error code to verify that the custom rule can be triggered.
The following is a simple example of the rules, detailed elaboration of the implementation of the rules of the specific steps. Java or XPath?
Here are two ways to write rules:
1. Writing with Java
2. Using an XPath expression
Want to know what you're looking for
Let's find out the problem we want to locate. The following is the code for the problem sample, with the "while loop must use parentheses" rule as an example. Without parentheses it is easy to confuse the code structure.
void bar() { while (baz) buz.doSomething(); }}
Figuring out what the sample code looks like, it's half done.
To write an example of a test data, view the AST
The
PMD scan does not use the source code directly; it uses the JavaCC build parser to parse the source and generate the AST (Abstract syntax tree). The above code is parsed into an abstract syntax tree as follows:
compilationunit typedeclaration classdeclaration: (package private ) Unmodifiedclassdeclaration (Example) classbody classbodydeclaration methoddeclaration: (package private ) resulttype Method Declarator (bar) formalparameters Block blockstatement Statement whilestatement Expression primaryexpression primaryprefix Name:baz Statement Statementexpression:null primaryexpression Primaryprefi X Name:buz.doSomething primarysuffix Arguments
You can use the designer tools from PMD to parse the code.
directory where the tool is located: Pmd-bin-5.4.1/bin/designer.bat
After double-clicking Designer.bat, an interface appears, fill in source code, and click the Go button:
The position of abstract Syntax Tree/xpath/symbol table in the picture is the tree structure after abstraction, and the tree structure is related to the source code.
Where we need to focus on the WhileStatement abstract tree structure is as follows:
Expression Statement StatementExpression
This is the abstract tree structure of the wrong code example, and if the while loop is enclosed in parentheses, the structure of the abstract tree becomes:
Expression Statement Block BlockStatement Statement StatementExpression
Ha ha! This can obviously see more than before Block and BlockStatement these two nodes.
In this way we only need to write a rule check WhileStatement under no Block node, only Statement when the alarm can be notified here is a problem.
By the way, all structural information, such as one followed by Statement one Block , is defined in EBNF grammar. For example, in this syntax definition, one Statement of the definitions is this:
void Statement() :{}{ LOOKAHEAD( { isNextTokenAnAssert() } ) AssertStatement()| LOOKAHEAD(2";"| SwitchStatement()| IfStatement()| WhileStatement()| DoStatement()| ForStatement()| BreakStatement()| ContinueStatement()| ReturnStatement()| ThrowStatement()| SynchronizedStatement()| TryStatement()}
The above code lists Statement all the possible behind.
Write a rule class
Write a new Java class inheritance net.sourceforge.pmd.lang.java.rule.AbstractJavaRule :
import net.sourceforge.pmd.lang.java.rule.*;publicclass WhileLoopsMustUseBracesRule extends AbstractJavaRule {}
PMD works by recursively iterating through the resulting abstract syntax tree until the target is found and the result is returned.
The next goal is to find the nodes in the abstract syntax tree WhileStatement :
import net.sourceforge.pmd.lang.java.rule.*;import net.sourceforge.pmd.lang.java.ast.*;publicclass WhileLoopsMustUseBracesRule extends AbstractJavaRule { publicvisit(ASTWhileStatement node, Object data) { System.out.println("hello world"); return data; }}
The printout of "Hello World" is the time when the rules we define are executed.
Put the Whileloopsmustusebracesrule rule in the XML ruleset file
Now that the rules have been written, we need to tell the PMD runtime to execute this rule by putting the relevant information for the rule file in the XML ruleset file. For example: pmd-java/src/main/resources/rulesets/java/basic.xml There are many definitions of rules, copy and paste, and change to a new ruleset file: Fill in the mycustomrules.xml elements and attributes yourself.
Name-whileloopsmustusebracesrule
Message-use braces for while loops
Class-Put it anywhere. Note that there is no need to put it in the net.sourceforge.pmd directory and can be placed in com.yourcompany.util.pmd
Description-use braces for while loops
Example-show violated rules through code snippets
<?xml version= "1.0"?><ruleset name =< Span class= "Hljs-value" > "My Custom 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="Whileloopsmustusebracesrule"message="Avoid using" While ' statements without curly braces 'class=' Whileloopsmustusebracesrule '> <description>Avoid using ' while ' statements without using curly braces</Description> <priority >3</priority > <example><! [cdata[public void dosomething () {while (true) x + +; }]]> </Example> </rule></ruleset>
Use PMD to execute your new rules
pmd.bat -d c:\path\to\my\src -f xml -R c:\path\to\mycustomrules.xml
You will see the previous "Hello World" output in the command line.
Create Ruleviolation
Want your test results to be shown in the report, you need to createRuleViolation
Importnet.sourceforge.pmd.lang.ast.*;Importnet.sourceforge.pmd.lang.java.ast.*;Importnet.sourceforge.pmd.lang.java.rule.*; Public class whileloopsmustusebracesrule extends abstractjavarule { PublicObjectVisit(astwhilestatement node, Object data) {Node firststmt = Node.jjtgetchild (1);if(!hasblockasfirstchild (FIRSTSTMT)) {addviolation (data, node); }return Super. Visit (Node,data); }Private Boolean Hasblockasfirstchild(Node node) {return(Node.jjtgetnumchildren ()! =0&& (Node.jjtgetchild (0)instanceofAstblock)); }}
Use this file to execute again
pmd.bat -d c:\path\to\my\src -f xml -R c:\path\to\mycustomrules.xml
You can view the results in the command line interface.
Reference documents
PMD site. How to write a PMD rule
How to use PMD to customize rules