Today I would throw some questions related to writing clean code, automation, static code analysis and see if you are with me in this exciting journey:
Today we would discuss about PMD, an open source cross language static code analyzer tool.
In this article, we would discuss below points regarding PMD:
1. Overview
2. Configuring PMD for a Maven Project
3. Rule sets Overview
4. Running PMD
5. Example
5. Conclusion
Let's start our journey to explore PMD in some details!!
PMD is an open source cross language static code analyzer tool to find common programming flaws like dead code, duplicate code, over complicated expression etc. It's primarily focuses on the bad practices used in the code and reports accordingly as per the defined rule sets. PMD not only has large number of built-in rule sets but it also supports the ability to write custom rules. It supports Java, JavaScript, Salesforce.com Apex and Visualforce, PLSQL, Apache Velocity, XML, XSL.
Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code in Java, C, C++, C#, Groovy, PHP, Ruby, Fortran, JavaScript, PLSQL, Apache Velocity, Scala, Objective C, Matlab, Python, Go, Swift and Salesforce.com Apex and Visualforce.
Note: In this tutorial, we would elaborate on how to use PMD for static code analysis in a Java based project. We would discuss CPD related functionality, usages and it's significance in our next article.
We will use Apache Maven PMD Plugin to generate the PMD & CMD reports using the PMD tool. One need to add the maven-pmd-plugin in <reporting> section of the POM and accordingly configure it to use the default rule sets or the customized rule sets. For example:
The PMD plugin uses five default rule sets:
That's it. Nothing else. But when one will starts writing custom rule sets then they will come across below scenarios like:
Now what to do ? Don't worry!! We got you covered here. Just follow the below examples:
There are mainly two ways to run PMD:
Note: If there are no violations, then by default no reports will be created and the entire PMD or CPD section is not rendered in the site. If one wants to change this behavior then set the skipEmptyReport for PMD or skipEmptyReport for CPD to false.
Without an example this journey can't be completed. Therefore here it is:
Corresponding PMD report when we use command mvn pmd:pmd
Corresponding PMD report when we use command mvn site
- Is it practically possible to remember each and every code convention rules , best practices, bad practices, basic design principles while writing codes ?
- Is it possible for code reviewers to inspect every lines of code to find code flaws ?
- Is it smart thing for code reviewers to waste their time, effort and energy to find code flaws related to conventions, bad practices, potential bugs, dead code, unused code and so forth when they could do so much more on the front of finding architecture, design, performance related issues ?
- Is it good to find small bugs in UAT or QA instead of finding at development phase?
- Is it not a smart move to use open source tools to automate the process of reports generation based on customized rule sets?
Today we would discuss about PMD, an open source cross language static code analyzer tool.
In this article, we would discuss below points regarding PMD:
1. Overview
2. Configuring PMD for a Maven Project
3. Rule sets Overview
4. Running PMD
5. Example
5. Conclusion
Let's start our journey to explore PMD in some details!!
1. Overview
PMD is an open source cross language static code analyzer tool to find common programming flaws like dead code, duplicate code, over complicated expression etc. It's primarily focuses on the bad practices used in the code and reports accordingly as per the defined rule sets. PMD not only has large number of built-in rule sets but it also supports the ability to write custom rules. It supports Java, JavaScript, Salesforce.com Apex and Visualforce, PLSQL, Apache Velocity, XML, XSL.
Additionally it includes CPD, the copy-paste-detector. CPD finds duplicated code in Java, C, C++, C#, Groovy, PHP, Ruby, Fortran, JavaScript, PLSQL, Apache Velocity, Scala, Objective C, Matlab, Python, Go, Swift and Salesforce.com Apex and Visualforce.
Note: In this tutorial, we would elaborate on how to use PMD for static code analysis in a Java based project. We would discuss CPD related functionality, usages and it's significance in our next article.
2. Configuring PMD for a Maven Project
We will use Apache Maven PMD Plugin to generate the PMD & CMD reports using the PMD tool. One need to add the maven-pmd-plugin in <reporting> section of the POM and accordingly configure it to use the default rule sets or the customized rule sets. For example:
With default rule sets and configuration:
<project> ... <reporting> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-pmd-plugin</artifactId> <version>3.8</version> </plugin> </plugins> </reporting> ... </project>
With customized rule sets and configuration:
<project> ... <reporting> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-pmd-plugin</artifactId> <version>3.8</version> <configuration> <linkXref>true</linkXref> <sourceEncoding>utf-8</sourceEncoding> <minimumTokens>100</minimumTokens> <targetJdk>1.8</targetJdk> <rulesets> <!-- Relative path, built-in rule sets --> <ruleset>/rulesets/java/braces.xml</ruleset> <ruleset>/rulesets/java/naming.xml</ruleset> <!-- Absolute path, custom local file system rule set --> <ruleset>D:\rulesets\ruleset.xml</ruleset> <!-- URL, could be custom or built-in rule sets --> <ruleset>http://localhost/design.xml</ruleset> </rulesets> <excludes> <exclude>**/*Bean.java</exclude> <exclude>**/generated/*.java</exclude> </excludes> <excludeRoots> <excludeRoot>target/generated-sources/stubs</excludeRoot> </excludeRoots> </configuration> </plugin> </plugins> </reporting> ... </project>
Some Pointer:
- linkXref: if enabled, report will link directly to the cross-referenced source, provided one also have entry for JXR plugin in their POM
- sourceEncoding: tell Maven which encoding to use when reading the java source
- exclude: exclude source which one wants to ignore
- targetJDK: specify which java version to use
- ruleset: specify the built-in rule sets or your own customized rule sets, supports relative address, an absolute address and even a URL
- One can also explicitly execute the PMD plugin and generate the same report by setting the plugin in the <build> section of your POM.
3. Rule Sets Overview
The PMD plugin uses five default rule sets:
- basic.xml
- empty.xml
- imports.xml
- unnecessary.xml
- unusedcode.xml
Let's create our own customized rule sets
It's very simple to create our own rule sets. Just follow the below steps:
- Create a new ruleset.xml file (using the below template)
Don't forget to change name & description accordingly.
<?xml version="1.0"?> <ruleset name="Custom ruleset" 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"> <description> This ruleset is customized according to my needs and checks my code flaws </description> </ruleset>
- Pick the rules that are right for you
<!-- used the entire 'strings' ruleset --> <rule ref="rulesets/java/strings.xml"/>
- Sometime wants to use the entire rule sets
- Sometimes wants to use only specific rules from a rule sets
- Sometimes wants to customize the rule a bit, change the message and raise the priority
- Sometimes wants to customize a rule's property value
- Sometimes wants to use the entire rule sets except one or two
- Sometimes wants to exclude certain files from processing by a rule sets
Now what to do ? Don't worry!! We got you covered here. Just follow the below examples:
<?xml version="1.0"?> <ruleset name="Custom ruleset" 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"> <description> Start your Journet to write your custom rule sets. This examples shows various scenarios on how to add various rule sets. </description> <!-- Sometimes wants to exclude certain files from processing by a rule sets --> <exclude-pattern>.*/some/package/.*</exclude-pattern> <exclude-pattern>.*/some/other/package/FunkyClassNamePrefix.*</exclude-pattern> <include-pattern>.*/some/package/ButNotThisClass.*</include-pattern> <!-- Sometime wants to use the entire rule sets --> <rule ref="rulesets/java/strings.xml"/> <!-- Sometimes wants to use only specific rules from a rule sets --> <rule ref="rulesets/java/unusedcode.xml/UnusedLocalVariable"/> <rule ref="rulesets/java/imports.xml/DuplicateImports"/> <!-- Sometimes wants to customize the rule a bit, change the message and raise the priority --> <rule ref="rulesets/java/basic.xml/EmptyCatchBlock" message="Must handle exceptions"> <priority>2</priority> </rule> <!-- Sometimes wants to customize a rule's property value --> <rule ref="rulesets/java/codesize.xml/CyclomaticComplexity"> <properties> <property name="reportLevel" value="5"/> </properties> </rule> <!-- Sometimes wants to use the entire rule sets except one or two --> <rule ref="rulesets/java/braces.xml"> <exclude name="WhileLoopsMustUseBraces"/> </rule> </ruleset>
4. Running PMD
There are mainly two ways to run PMD:
- Don't add an entry in a ‘project reports’ section with the PMD report
mvn pmd:pmd
- Add an entry in the ‘project reports’ section with the PMD report
mvn site
Note: If there are no violations, then by default no reports will be created and the entire PMD or CPD section is not rendered in the site. If one wants to change this behavior then set the skipEmptyReport for PMD or skipEmptyReport for CPD to false.
5. Example
Without an example this journey can't be completed. Therefore here it is:
import java.lang.String; import java.lang.*; public class App { private String name; {} public void bar() { try { } catch (Exception e) { e.printStackTrace(); } } ... }
Corresponding PMD report when we use command mvn pmd:pmd
PMD Results The following document contains the results of PMD 5.6.1. Files com/anshulsblog/pmd/App.java Violation Line Avoid importing anything from the package java.lang 3 Avoid importing anything from the package java.lang 4 Avoid unused private fields such as 'name'. 11 Empty initializer was found 13 Avoid empty try blocks 18–19
Corresponding PMD report when we use command mvn site
5. Conclusion
PMD is a flexible and highly configurable static analyzer tool. One should use this "code review automation tool" for static code analysis so that bugs can fixed at development time only.
Thank you for reading this article. Feel free to connect with me for any queries and suggestion and don't forget to share your comments. Happy Learning!!
Completely agree... I found very important and useful information on code reviews and static code analyzers. Thanks for sharing the importance of clean codes.
ReplyDeleteThank you Rowell. I am glad you liked it.
Delete