PMD is a static code analyzer for Java. Developers use PMD to comply with coding standards and deliver quality code. Team leaders and Quality Assurance folks use it to change the nature of code reviews. PMD has the potential to transform a mechanical and syntax check oriented code review into a to dynamic peer-to-peer discussion.

This article looks at PMD as an Eclipse plugin and the ways it can be used to improve the code quality and shorten the code review process. Since every organization has a unique set of coding conventions and quality metrics, it also demonstrates how to customize PMD to meet these needs.

What is PMD?

PMD works by scanning Java code and checks for violations in three major areas:

  • Compliance with coding standards such as:
    • Naming conventions - class, method, parameter and variable names
    • Class and method length
    • Existence and formatting of comments and JavaDocs
  • Coding antipatterns such as:
    • Empty try/catch/finally/switch blocks
    • Unused local variables, parameters and private methods
    • Empty if/while statements
    • Overcomplicated expressions - unnecessary if statements, for loops that could be while loops
    • Classes with high Cyclomatic Complexity measurements
  • Cut and Paste Detector (CPD) - a tool that scans files and looks for suspect code replication. CPD can be parameterized by the minimum size of the code block.

In its current version, PMD comes packaged with 149 rules in 19 rulesets. Most of these rules can be parameterized at runtime by supplying properties or parameters. The standard package offers many well-thought rules. In addition users also have the ability to add their own rules for particular coding convention or quality metrics. Here are some of the rules distributed with PMD:

  • EmptyFinalizer - If the finalize() method is empty, then it does not need to exist.
  • EmptyFinallyBlock - Avoid empty finally blocks - these can be deleted.
  • UnnecessaryReturn - Avoid unnecessary return statements
  • OnlyOneReturn - A method should have only one exit point, and that should be the last statement in the method.
  • CyclomaticComplexity - Complexity is determined by the number of decision points in a method plus one for the method entry. The decision points are 'if', 'while', 'for', and 'case labels'. Generally, 1-4 is low complexity, 5-7 indicates moderate complexity, 8-10 is high complexity, and 11+ is very high complexity.
  • TooManyFields - Classes that have too many fields could be redesigned to have fewer fields, possibly through some nested object grouping of some of the information. For example, a class with city/state/zip fields could instead have one Address field.
  • LongVariable - Detects when a field, formal or local variable is declared with a long name.
  • NoPackage - Detects when a class or interface does not have a package definition.

Where to find it?

PMD started as a standalone application and today it is an open-source project hosted under It is still distributed as a standalone application, however there is now substantial support for most popular Java IDEs. The PMD team has developed plugins for JDeveloper, Eclipse, JEdit, JBuilder, Omnicore's CodeGuide, NetBeans/Sun Java Studio Enterprise/Creator, IntelliJ IDEA, TextPad, Maven, Ant, Gel, JCreator, and Emacs. This article covers PMD's Eclipse plugin only.

PMD binaries and source files can be downloaded from PMD's Sourceforge directory. For an open-source project, PMD is relatively well-documented. Among the items in PMD's main site are topics such as installation, PMD-related products and books, best practices, licensing info, usage guides and more. There is also a section for developers interested in joining the project. The following items target the latter: compiling PMD, project info, project reports, and development process.

How to install it?

The easiest way to install PMD is by using the remote update site. Users behind firewalls should check proxy settings before going any further. If these settings are misconfigured the updater will not work. PMD also supplies a zip file for manual installation. Download the file and follow the readme. Demonstrated below is installing PMD via the Eclipse Software Updater.

  1. Launch Eclipse.
  2. Navigate to Help | Software Updates | Find and Install...
  3. Select "Search for new features to install" and click Next
  4. Click New Remote Site...
  5. Enter a name (PMD) and the URL
  6. In Sites to include in search check PMD and click Finish
  7. In the Search Results dialog check PMD for Eclipse 3 3.1.0 and click Next
  8. Accept the terms of the license agreements and click Next
  9. Click Finish.
  10. Wait for Eclipse to download the required jar files, then click Install
  11. Restart the workbench. This will load the PMD plugin.
  12. Navigate to Window | Show View | Other...
  13. Select PMD | PMD Violations
  14. PMD Violations view should appear at the bottom pane

How to use it?

Before launching Eclipse make sure you have enough memory for PMD. This is particularly important when analyzing large projects. In these situations PMD tends to be memory-hungry. Hence, make sure to start with as much memory as you can afford, for example 512M (eclipse.exe -vmargs -Xmx512M)

  1. Launch Eclipse
  2. If you have previously created a Java Project, skip to Step 6. Otherwise click File | New | Project...
  3. Select Java Project and click Next
  4. Enter a project name (QA Project) and leave everything else in the default state.
  5. Click Finish. Eclipse will ask if you want to switch to the Java Perspective. Click Yes.
  6. In the Package Explorer right-click on QA Project and select New | Class
  7. In the following dialog enter the class name as Ying and click Finish
  8. A new class Ying is created in project's default package. Paste the following code into the new class:
    public class Ying {
    	private static final String gOOD = "GOOD";
    	public void StartSomething() {
    		System.out.println("Hello PMD World!");
    	public String thisIsCutAndPaste(String pFirst, int pSecond) {
    		System.out.println("New world");
    		return "New world";
  9. Similarly, create a second class Yang and paste the following code:
    public class Yang extends Thread {
    	public Yang(String str) {
    	public void run() {
    		for (int i = 0; i < 10; i++) {
    			System.out.println(i + " " + getName());
    			try {
    				sleep((long) (Math.random() * 1000));
    			} catch (InterruptedException e) {
    		System.out.println("DONE! " + getName());
    	public void WRITE_SOMETHING(String INPUT_PARAMETER) {
    	public static void main(String[] args) {
    		new Yang("Good").start();
    		new Yang("Bad").start();
    	public String thisIsCutAndPaste(String pFirst, int pSecond) {
    		System.out.println("New world");
    		return "New world";
  10. In the Package Explorer right-click on QA Project and select PMD | Check Code With PMD
  11. Wait for PMD to scan Ying and Yang
  12. If PMD Violations view is not open navigate to Window | Show View | Other... and select PMD | PMD Violations
  13. In the PMD Violations view notice a list of 17 violations. In large projects this list could easily grow up to several thousand. This is one of the reasons PMD allows violations be filtered by priority. Priority is a configurable attribute of a PMD rule. PMD assigns priorities from 1 to 5 and each priority is represented by a colored square at the top-right corner of the view. These little squares are actually clickable on-off switches used to control the visibility of the violations they represent.
    The results table itself is well laid out and most columns are sortable. It is also possible to get more detail on a violation by simply right-clicking it and selecting Show rule. PMD pops-up a dialog with information such as rule name, implementation class, message, description and an example. This feature can be helpful when trying to makes sense of a new rule or letting inhouse developers know about a particular company rule or coding convention.
    Finally, in the PMD Violations table it is possible to add review annotations to the source where the violation occurred. This can be an effective way to mark target files for further review. Just right-click on any violation in the list and select Mark review. PMD will insert a review annotation to the Java source right above the violation line itself. The review annotation should look like this:
    // @PMD:REVIEWED:MethodNamingConventions: by Levent Gurses on 3/28/04 5:04 PM
    Review annotations can be removed anytime by right-clicking QA Project and selecting PMD | Clear violations reviews. Similarly, PMD Violations can be cleaned-up by right-clicking QA Project and selecting PMD | Clear PMD Violations..

Finding Cut and Paste Code

Repeated (Cut&Paste) code generally indicates poor planning or team coordination. Therefore, refactoring classes with repeating code should be given a high priority. PMD can help identify these classes by scanning the code in a way similar to PMD violation checks. The number of lines of similarity (the metrics used by PMD to match code patterns) is 25 by default and can be set in PMD's Preferences page.

  1. In Package Explorer right-click on QA Project and select PMD | Find Suspect Cut And Paste
  2. PMD creates a folder reports under QA Project and stores the result text file
  3. Select Window | Show View | Navigator
  4. In Navigator view click on QA Project and then on the reports folder
  5. The report file cpd-report.txt should look like this:
    Found a 8 line (25 tokens) duplication in the following files:
    Starting at line 6 of C:\temp\QA Project\
    Starting at line 23 of C:\temp\QA Project\
    		new Yang("Bad").start();
    	public String thisIsCutAndPaste(String pFirst, int pSecond) {
    		System.out.println("New world");
    		return "New world";

Generating Reports

After running a lengthy violation check it may be desirable to share the findings with peers or store them for later reference. For situations of this kind PMD provides a handy reporting tool capable of generating reports in multiple formats. Currently PMD can generate reports in HTML, XML, plain text as well as Comma Separated Value (CSV) formats.

  1. In Package Explorer right-click on QA Project and select PMD | Generate reports
  2. PMD creates a folder reports under QA Project and stores four report files
  3. Select Window | Show View | Navigator
  4. In Navigator view click on QA Project and then on the reports folder
  5. Of the four report files pmd-report.html should look like this:
    # File Line Problem
    1 8 System.out.print is used
    2 14 System.out.print is used
    3 17 Method name does not begin with a lower case character.
    4 17 Method names should not contain underscores
    5 17 Parameter 'INPUT_PARAMETER' is not assigned and could be declared final
    6 18 System.out.print is used
    7 21 Parameter 'args' is not assigned and could be declared final
    8 27 System.out.print is used
    9 1 Each class should declare at least one constructor
    10 3 Avoid unused private fields such as 'gOOD'
    11 5 Method name does not begin with a lower case character.
    12 6 System.out.print is used
    13 9 Parameter 'pFirst' is not assigned and could be declared final
    14 9 Parameter 'pSecond' is not assigned and could be declared final
    15 10 System.out.print is used

Customizing PMD

The easiest way to begin customizing PMD is by playing with existing rules. Adding new rules is also possible as well as removing unnecessary ones, however these require more knowledge. Since experimenting with existing rules is the easiest, it makes sense to start with them.

Each PMD rule has six attributes:

  • Rule name - immutable
  • Rule implementation class - immutable
  • Priority
  • Message
  • Description
  • Example

Of these six attributes the first two are immutable - they cannot be customized by users. While Message, Description and Example are text-based properties and can accept any String data, Priority is an integer field ranging from 1 to 5.

PMD stores rule configuration in a special repository referred to as the Ruleset XML file. This configuration file carries information about currently installed rules and their attributes. Changes made through the Eclipse Preferences page are also stored in this file. In addition, the PMD Preferences page allows exporting and importing Rulesets which makes them a convenient vehicle for sharing rules and coding conventions across the enterprise.

Before starting the customization it may be a good idea to back-up existing configuration.

  1. Navigate to Window | Preferences... | PMD | Rules configuration
  2. Click Export rule set...
  3. Enter a file name e.g. pmd-rules.xml and click Save
  4. Back in the Rules configuration page scroll-down and click on SystemPrintln rule
  5. With the rule selected, click the Priority column and change the priority from Error (2) to Information (5)
  6. With the rule still selected, click the Edit rule... button on the right
  7. Change the Message, Description and Example. Click OK when done
  8. Click Export rule set...
  9. Enter a new file name e.g. pmd-rules-customized.xml and click Save
  10. Compare the two XML files - they are different
  11. In Package Explorer right-click on QA Project and select PMD | Clear PMD Violations
  12. In Package Explorer right-click on QA Project and select PMD | Check Code With PMD
  13. Wait for PMD to finish the scan
  14. If PMD Violations view is not open navigate to Window | Show View | Other... and select PMD | PMD Violations
  15. Notice SystemPrintln is now priority 5

Adding New Rules

PMD allows new rules in two formats: Java-based rules where the rule is written as a Java implementation class and XPath rules where the rule is defined in an XML file. Both ways are equally applicable and the choice is probably a matter of preference. This article will demonstrate creating a new rule with both Java and XPath. The rule, ParameterNameConvention, will be a simple coding convention checker making sure all method parameters start with a lowercase "p". To accomplish its task the rule will take advantage of regular expressions and will enforce the following expression to all method parameters: [p][a-zA-Z]+. Later this expression will be made into a rule property which will allow further customization by rule users.

This is all good, but before going any further into the custom PMD rules let's see how this PMD thing actually works.

How PMD works?

PMD relies on the concept of Abstract Syntax Tree (AST), a finite, labeled tree where nodes represent the operators and the edges represent the operands of the operators. PMD creates the AST of the source file checked and executes each rule against that tree. The violations are collected and presented in a report. PMD executes the following steps when invoked from Eclipse (Based on PMD's documentation):

  1. The Eclipse PMD plugin passes a file name, a directory or a project to the core PMD engine (Also part of the Eclipse plugin, however housed in a separate package). This engine then uses the RuleSets as defined in the PMD preferences page to check the file(s) for violations. In the case of a directory or project (multiple source files) the plugin executes the following steps for each file in the set.
  2. PMD uses JavaCC to obtain a Java language parser
  3. PMD passes an InputStream of the source file to the parser
  4. The parser returns a reference of an Abstract Syntax Tree back to the PMD plugin
  5. PMD hands the AST off to the symbol table layer which builds scopes, finds declarations, and find usages
  6. If any rules need data flow analysis, PMD hands the AST over to the DFA layer for building control flow graphs and data flow nodes
  7. Each Rule in the RuleSet gets to traverse the AST and check for violations
  8. The Report is generated based on a list of RuleViolations. These are displayed in the PMD Violations view or get logged in an XML, TXT, CSV or HTML report.
Abstract Syntax Tree
In computer science, an Abstract Syntax Tree (AST) is a finite, labeled, directed tree, where the nodes are labeled by operators, and the edges represent the operands of the node operators. Thus, the leaves have nullary operators, i.e., variables or constants. In computing, it is used in a parser as an intermediate between a parse tree and a data structure, the latter which is often used as a compiler or interpreter's internal representation of a computer program while it is being optimized and from which code generation is performed. The range of all possible such structures is described by the abstract syntax. An AST differs from a parse tree by omitting nodes and edges for syntax rules that do not affect the semantics of the program. The classic example of such an omission is grouping parentheses, since in an AST the grouping of operands is explicit in the tree structure. 
Creating an AST in a parser for a language described by a context free grammar, as nearly all programming languages are, is straightforward. Most rules in the grammar create a new node with the nodes edges being the symbols in the rule. Rules that do not contribute to the AST, such as grouping rules, merely pass through the node for one of their symbols. Alternatively, a parser can create a full parse tree, and a post-pass over the parse tree can convert it to an AST by removing the nodes and edges not used in the abstract syntax.
From Wikipedia

PMD Class Hierarchy

Since PMD works on a tree data structure, its unit of operation is Node. Every construct in a Java source file examined by PMD is assigned a node in the Abstract Syntax Tree. These nodes are then visited by all rules in the ruleset and the method public Object visit(SimpleNode node, Object data) of the rule implementation class gets invoked. It is inside this method where the rule logic is defined.

In PMD every node extends net.sourceforge.pmd.ast.SimpleNode. This concrete class implementsnet.sourceforge.pmd.ast.Node and has 104 first-level children as well as an additional 8 second-level children coming from net.sourceforge.pmd.ast.AccessNode.

This screenshot captures portion of SimpleNodes children. The entire list is available with the source distribution of PMD. This class hierarchy is important for writing custom PMD because each custom rule will rely on one or more of PMD's SimpleNodes to accomplish its task.

This is a good place to see the Abstract Syntax Tree in action.

  1. In Java Perspective, go to Package Explorer and double-click on QA Project and next (default package)
  2. Right-click on and select PMD | Generate Abstract Syntax Tree
  3. Click on Window | Show View | Navigator
  4. In Navigator view click on QA Project
  5. The Abstract Syntax Tree file Ying.ast is located in the root level. It should look like this:
    <?xml version="1.0" encoding="UTF-8"?>
    <CompilationUnit beginColumn="1" beginLine="13" endColumn="3" endLine="13">
        <TypeDeclaration beginColumn="1" beginLine="1" endColumn="1" endLine="13">
            <ClassOrInterfaceDeclaration abstract="false" beginColumn="8" beginLine="1" endColumn="1" endLine="13" final="false" image="Ying" interface="false">
    		<MethodDeclarator beginColumn="23" beginLine="9" endColumn="67" endLine="9" image="thisIsCutAndPaste" parameterCount="2">
    		    <FormalParameters beginColumn="40" beginLine="9" endColumn="67" endLine="9" parameterCount="2">
    			<FormalParameter abstract="false" array="false" arrayDepth="0" beginColumn="41" beginLine="9" endColumn="53" endLine="9" final="false">
    			    <Type array="false" arrayDepth="0" beginColumn="41" beginLine="9" endColumn="46" endLine="9">
    				<ReferenceType array="false" arrayDepth="0" beginColumn="41" beginLine="9" endColumn="46" endLine="9">
    				    <ClassOrInterfaceType beginColumn="41" beginLine="9" endColumn="46" endLine="9" image="String"/>
    			    <VariableDeclaratorId array="false" arrayDepth="0" beginColumn="48" beginLine="9" endColumn="53" endLine="9" exceptionBlockParameter="false" image="pFirst" typeNameNode="ReferenceType" typeNode="Type"/>
    			<FormalParameter abstract="false" array="false" arrayDepth="0" beginColumn="56" beginLine="9" endColumn="66" endLine="9" final="false">
    			    <Type array="false" arrayDepth="0" beginColumn="56" beginLine="9" endColumn="58" endLine="9">
    				<PrimitiveType array="false" arrayDepth="0" beginColumn="56" beginLine="9" boolean="false" endColumn="58" endLine="9" image="int"/>
    			    <VariableDeclaratorId array="false" arrayDepth="0" beginColumn="60" beginLine="9" endColumn="66" endLine="9" exceptionBlockParameter="false" image="pSecond" typeNameNode="PrimitiveType" typeNode="Type"/>

This AST report gives a full synopsis of the examinee, in this case It is possible for example to gain insight about the method parameter pFirst by expanding the FormalParameter node. Studying this Abstract Syntax Tree can contribute to a better understanding of how a Java source file is examined and what variables play role in the process. This in turn could prove useful when crafting custom rules.

Writing Custom PMD Java Rules

Now, going back to ParameterNameConvention it is time to crank some code. This article will create a Java class for the rule implementation and package it as a plugin fragment. A fragment is an extension of a plug-in and all the classes and resource files it contains are automatically added to the main plug-in classpath. Since PMD searches main plugins classpath for rule implementation classes the fragment will be automatically available. In addition, this structure will allow for faster development and easier distribution.

Creating the plugin fragment in Eclipse

  1. In Eclipse Navigate to Window | Open Perspective | Other...
  2. Select Plug-in Development
  3. In Package Explorer right-click and select New | Project...
  4. In the New Project wizard select Plug-in Development | Fragment Project and click Next
  5. Enter a project name of your liking, e.g. com.jacoozi.pmd.rules and click Next
  6. In the Fragment Content dialog enter details for the fragment and the host plug-in. Click Browse... to locate the host plugin.
  7. In the Plug-in Selection dialog type net.sourceforge.pmd.eclipse then select the only item in the list. Click OK
  8. Back in the Fragment Content dialog select Greater or Equal for Match Rule. This will ensure that future upgrades to the host PMD plug-in do not affect the fragment. The dialog should look like the following:
  9. Click Finish

Implementing the rule class

  1. In Package Explorer right-click on the source folder src and select New | Class
  2. Enter a package name of liking, e.g. com.jacoozi.pmd.rules
  3. Enter the class name ParameterNameConvention
  4. Click Finish
  5. Paste the following code into the new Java class:
    package com.jacoozi.pmd.rules;
    import java.util.Iterator;
    import net.sourceforge.pmd.AbstractRule;
    import net.sourceforge.pmd.RuleContext;
    import net.sourceforge.pmd.RuleViolation;
    import net.sourceforge.pmd.ast.ASTFormalParameter;
    import net.sourceforge.pmd.ast.ASTMethodDeclaration;
    import net.sourceforge.pmd.ast.ASTVariableDeclaratorId;
     * @author Levent Gurses
     * Copyright 2005 Jacoozi
    public class ParameterNameConvention extends AbstractRule {
    	private final static String PATTERN = "[p][a-zA-Z]+";
    	public Object visit(ASTMethodDeclaration node, Object data) {
    		RuleContext result = (RuleContext) data;
    		String rulePattern = (!getStringProperty("rulePattern").equalsIgnoreCase("")) ? getStringProperty("rulePattern") : PATTERN;
    		if (node.containsChildOfType(ASTFormalParameter.class)) {
    			Iterator iterator = node.findChildrenOfType(ASTFormalParameter.class).iterator();
    			while (iterator.hasNext()) {
    				ASTFormalParameter element = (ASTFormalParameter);
    				Iterator decIdIterator = element.findChildrenOfType(ASTVariableDeclaratorId.class).iterator();
    				while (decIdIterator.hasNext()) {
    					ASTVariableDeclaratorId decElement = (ASTVariableDeclaratorId);
    					if (!decElement.getImage().matches(rulePattern)) {
    						result.getReport().addRuleViolation(new RuleViolation(this,
    								node.getBeginLine(), "Parameter '" + decElement.getImage() + "' should match regular expression pattern '" +
    								rulePattern + "'", result));
    		return result;

    Couple of points here. First, notice it extends import net.sourceforge.pmd.AbstractRule. All custom rules must extend this class. Second, notice the AST traversal starts from the method declaration. It then iterates through its children and looks for ASTFormalParameter. Finally, it compares thenode.getImage() against the rule regular expression. Notice that a mismatch causes the creation of a new RuleViolation. As a side note, notice also the regular expression is fed into the rule as a property.

Testing the new rule

The rule class is now complete and there are no compilation errors (red Xs). This means it is ready for testing.

  1. In Plug-in Package Explorer right-click on com.jacoozi.pmd.rules and select Run As | Eclipse Application (Alt+Shift+X,E). Alternatively, to launch a Debug session click on Run | Debug As | Eclipse Application (Alt+Shift+D,E)
  2. Eclipse will launch a fresh instance to test the new PMD rule. In Package Explorer right-click and selectImport... | Existing Project into Workspace. Click Next
  3. In Import Projects click Browse to locate the QA Project. Navigate to C:\Documents and Settings\[Your name]\workspace and click OK. This assumes you created the QA Project in Eclipse's default workspace. If not, locate the project in your custom workspace.
  4. Check the QA Project and click Finish
  5. Select Window | Preferences... | PMD | Rules configuration
  6. Click Add rule..., fill the form with the following and click OK
    Rule name: ParameterNameConvention
    Rule implementation class: com.jacoozi.pmd.rules.ParameterNameConvention
    Message: Method parameters should begin with a lowercase "p"
    Description: Method parameters should always begin with a "p". This is equivalent to the parameters complying with regular expression [p][a-zA-Z]+. This expression can be changed the preferences page by adding a property "rulePattern".
    public void bringItHome( String pName, int pNumber, boolean pDoneThat, List pTr)
  7. Change rule priority to Error high
  8. Click on Add property... and enter rulePattern as name and [p][a-zA-Z]+ as value.
  9. Click on OK and agree to rebuild.
  10. In Package Explorer right-click on QA Project and select PMD | Check Code with PMD. Open the PMD Violations view. It should display three ParameterNameConvention violations in

Packaging and distributing the new rule

What happens if you want to share a rule with colleagues or make it a common convention for the team? Simple. The fragment project can be exported as a zip file making it easy to distribute. First, export the fragment project; next unzip the file into Eclipse's plugins folder and it's done.

  1. In Plug-in Package Explorer right-click on com.jacoozi.pmd.rules and select Export... | Deployable plug-ins and fragments
  2. Enter a name for the zip file, e.g. com.jacoozi.pmd.rules and click Finish. Eclipse will export the fragment classes into a new archive
  3. Export ruleset. In PMD Preferences page Click Export rule set.... Zip this file and the fragment zip from previous step together. The portable plugin fragment is now ready for distribution.

Installing the new rule

What happens if you want to share a rule with colleagues or make it a common convention for the team? Simple. The fragment project can be exported as a zip file making it easy to distribute. First, export the fragment project; next unzip the file into Eclipse's plugins folder. That's pretty much it.

  1. Unzip the archive to the target machine. If the target environment uses default Eclipse settings, unzip the file under C:\eclipse (The zip file contains a folder plugins)
  2. Navigate to PMD Preferences page and click Import rule set.... Select the ruleset file from previous step and click OK
  3. Click OK to close the Preferences page.

The new rule is now ready for use.

Writing Custom PMD XPath Rules

The second way to add custom rules to PMD requires some XPath knowledge. XPath has been out for some time now and has proven to be an effective query language for DOM-based XML. Detailed XPath would fill an entire book, therefore for the sake of time and space it is left out. The following Wikipedia definition provides a basic idea of what the language is all about.

XPath (XML Path Language) is a terse (non-XML) syntax for addressing portions of an XML document.

Originally motivated by a desire to provide a common syntax and behavior model between XPointer and XSL, XPath has rapidly been adopted by developers as a small query language.

The most common kind of XPath expression (and the one which gave the language its name) is a path expression. A path expression is written as a sequence of steps to get from one set of nodes to another set of nodes. The steps are separated by "/" (i.e. path) characters. Each step has three components:
  • Axis Specifier
  • Node Test
  • Predicate
The notation is compact, allowing many defaults and abbreviations for common cases. 

The simplest kind of path expression takes a form such as /A/B/C, which selects C elements that are children of B elements that are children of the A element that forms the outermost element of the document. 

XPath syntax is designed to mimic URI (Uniform Resource Identifier) syntax or file name syntax. More complex expressions can be constructed by specifying an axis other than the default child axis, a node test, other than a simple name, or predicates, which can be written in square brackets after each step. For example, the expression /A/B/following-sibling::*[1] selects all elements (whatever their name) that immediately follow a B element that is a child of the outermost A element.
From Wikipedia

What is needed here is a way to implement ParameterNameConvention as an XPath rule. The chief advantage of XPath rules in PMD is the power, elegance and simplicity of XPath compared to Java. The main disadvantage is that not many people are familiar with XPath. With that being said, let's see how much time XPath can actually save.

  1. To save confusion, first remove the Java ParameterNameConvention from Eclipse. Navigate toWindow | Preferences... | PMD | Rules configuration
  2. Scroll-down the list and select ParameterNameConvention. Click Remove rule
  3. Now, create the new XPath rule. In PMD Rules configuration dialog click Add rule...
  4. This time check XPath rule. The rule implementation class will automatically change tonet.sourceforge.pmd.rules.XPathRule. Fill the rest of the form with the following:
    Rule name: ParameterNameConvention
    Message: Method parameters should begin with a lowercase "p"
    Description: Method parameters should always begin with a "p".
    public void bringItHome( String pName, int pNumber, boolean pDoneThat, List pTr)
  5. Change rule priority to Error high
  6. Click on Add property... and enter xpath as name and //FormalParameter/VariableDeclaratorId[not (starts-with(@Image, 'p'))] as value.
  7. Click on OK and agree to rebuild.
  8. In Package Explorer right-click on QA Project and select PMD | Check Code with PMD. Open the PMD Violations view. It should display three ParameterNameConvention violations in

That's it. The whole rule takes a single line:

//FormalParameter/VariableDeclaratorId[not (starts-with(@Image, 'p'))]

This one-line XPath rule tells PMD to watch for method parameters whose VariableDeclaratorId name ('Image') does not start with a "p". Very elegant.

XPath-based PMD rules offer an efficient alternative to Java-based rules. As more development tools become XPath-compatible it is likely that an investment in this powerful query language will prove valuable for Java developers.

Wish List

I must admit, I am impressed by PMD's capabilities. It has proven itself as a production grade tool, capable of handling large volumes of Java source files. There are couple of things I wish PMD had. The list below is dedicated to what's missing or can be improved.

  • Add better filtering capabilities to the PMD Violations view. For example add pagination, an important feature when working on large projects. Similarly, improve memory management - large projects may cause the environment to run out of memory.
  • Improve code checking capability by adding advanced query options. For example, add ability to check for a specific rule violation. Support by generating reports for specific rule violation or other more advanced search queries.
  • Move the report generation context menu from the project menu into the PMD Violations view. Support this functionality with advanced filters so that generated could reports include a subset of the violations and not be limited to the entire set.
  • Simplify the rule addition process. Today, Java rules are a bit of a complication to add. Create a WEB-INF-type folder under the core plugin where the classloader would monitor for custom rule implementation classes. This would free developers from having to create plugin fragment projects and a single rule class would be sufficient.
  • Since XPath is such a powerful and efficient way to add custom rules, use AST trees generated from source files to visually guide developers while creating XPath queries. This would help people with little or no XPath experience to begin writing custom rules faster. Alternatively, create an XPath based visual AST editor for Eclipse.
  • Improve the PMD Preferences page. Add multi-line support for Rule properties - important when adding XPath rules.


There is little doubt that code quality is becoming a prime factor in today's software economy. Many companies are taking real steps to transform old-fashioned, paper-based and in many cases simply ineffective QA practices into modern, efficient, value-added software lifecycle practices. In this path, they are realizing the power of software as a tool to check, correct and improve itself. And a new breed of automated code analyzers is slowly emerging. Designed to free developers from repetitive and error-prone manual code checks, these software "robocops" take the burden from developers, thus enabling them to spend more time on real design and performance issues such as patterns and multithreaded execution.

Automated code analyzers are not meant to replace manual QA. Instead, they should be used in tandem with well-designed manual review processes. Research shows that companies using automated QA tools with paperless, manual QA gain competitive advantage by considerably reducing software maintenance costs. This reduction comes mainly from lower number of defects and less time spent on each defect.

PMD and Eclipse are two great tools for improving personal code quality as well as implementing a consistent company-wide coding convention. PMD operates by applying a set of rules to source files. It comes with a rich suite of rules which can be extended in two ways. The traditional way of adding new rules to PMD is by implementing the rule class in Java and then adding it to the plugin's classpath. PMD has recently added XPath support for custom rules. XPath helps PMD take advantage of the fact it operates on an XML-based Abstract Syntax Tree. Compared to Java rules, XPath rules are much shorter and look way cooler. XPath is a powerful XML query language capable of small wonders. The elegance and beauty of XPath makes it a great choice for developing custom PMD rules.


System Information

  • Windows 2000
  • Eclipse 3.1.0
  • JDK 1.4.2_04
  • PMD - pmd-eclipse-3.1
  • XPath 2.0

'Code Inspection' 카테고리의 다른 글

PMD eclipse  (0) 2013.06.24  (0) 2013.05.22
checkstyle rule  (0) 2013.05.22

요새 산출물로 자바 도큐먼트를 만드는 경우가 많다.

개발하기도 바뿐데 코딩하면서 주석도 달기 귀찮긴 하지만 

워드로 산출물을 만드는것보다 훨씬 경제적이고 덜 노가다? 가 필요해서 좋은것 같다.

기본적으로 자바문서를 만들면 패키지 까지는 주석이 달려나올 수가 없다.

어느정도 노가다가 좀 필요한데 방법을 설명 해보기로 한다.

참고로 자바문서를 위해 주석은 

/**  이것은 클래스 **/

class Sample{

/** 변수 */

private String name;


 이런식으로 클래스나 메소드 변수명 위에 써주면 된다.

이제 부터 문서도구 만드는 예제를 설명하겠다.

1.자바 프로젝트 생성

3개의 패키지를 만들고 각각의 패키지에 클래스를 만든다.

2.패키지 설명 파일 생성

각각의 패키지에서 일반 파일을 생성하고 이름을 로 만든다.

패키지 우클릭 - New - File - 생성.

3.패키지 수석달기

패키지 마다 파일을 열고 아래와 같이 해당 패키지명을 입력한다. 

각각의 파일들에 다 입력한다.


패키지 단위로 설명이 나오는것을 확인 할 수 있다.

질문은 댓글 환영합니다~

'Code Inspection' 카테고리의 다른 글

PMD eclipse  (0) 2013.06.24  (0) 2013.05.22
checkstyle rule  (0) 2013.05.22

사내의 코드 품질 평가를 위해서 static analysis 방법을 조사하면서 항목에 대해서 list up을 할 필요성이 발견되어 조사한 내용들을 공유합니다. 







모든 method, class에는 help 존재해야지 된다.

시간상 힘들고, 관리되지 않는 주석은 더욱 혼란을 가지고 온다. method 이름 규칙으로 대신하기로 한다.



java code 가장 마지막 줄은 빈공백열로 마쳐져야지 된다.

마지막 line에는 항시 빈공백을 넣는다.



Properties file 이용한 경우, 국가별 번역이 모두 존재해야지 된다.

국가별 번역 파일을 따로 만들거나 default 문자열만을 이용한다.



java file length 2000 line 넘지 않도록 작성한다.

2000 line 넘어가는 경우, 설계상의 문제가 있기 때문에 class 재정의한다.



java file 내부에 tab 문자열이 있으면 안된다.

tab 모두 space 치환해서 사용하도록 한다.



1 line에는 한개의 method만이 존재해야지 된다.

1 line 대한 설정을 명확하게 해서 사용하도록 한다.


ConstantName, LocalFinalVariableName, LocalVariableName, MemberName, MethodName, PackageName

상수, class, method, parameter, package 대한 naming 규칙이 틀릴 경우 발생한다.

naming 규칙에 맞는 명명법을 사용한다.



package안에 있는 모든 객체들을 import할때 발생한다.

package안에서 사용되는 객체만을 import 한다.


테스트 코드 작성시에는 예외로 한다.


package안에 사용하지 않는 객체를 import하면 발생한다.

package안에 사용되지 않는 객체들은 import 하지 않는다.


테스트 코드 작성시에는 예외로 한다.


Line 길이가 80자가 넘는 경우 발생한다.

Line 길이를 120자로 수정해서 사용한다.


80 -> 120


Method 길이는 150자가 넘는 경우 발생한다.

Method 길이를 150 이내로 사용한다.



Method parameter 7개가 넘지 않도록 한다.

Method안의 input parameter 갯수를 제한한다.



Method 앞에 붙는 order 다음과 같은 순서를 갖는다. (public, abstract, static, final, transient, volatile, synchronized, native, strictfp)

순서를 따르도록 한다.



내부 {} 사용하지 않는다. - switch 구문 제외

내부 {} 사용하지 않는다.



{}안에 아무런 구문이 없는 경우에 발생한다.

{}안에 구문이 없는 경우, 제거한다.



'{' interface method 구현문 끝에 넣어준다.

이집트 표기법을 사용하도록 한다.



code안의 {} 반드시 짝이 맞아야지 된다.

Compile error 발생하지 않도록 만들어준다.



'}' 뒤에는 반드시 CRLF만이 존재해야지 된다.

이집트 표기법을 사용하도록 한다.



1 line에서 if 문을 이용해서 처리하지 않는다.

condition 제거하도록 한다.


1 line에서 가독성이 높은 경우가 존재한다.


for loop문에서 무한 loop 발생시킬 있는 empty statement 존재한다.

반드시 for loop 경우에는 statement 존재한다. loop 안에서 조건이 걸리는 경우, while문을 사용하도록 한다.



equals(), hashCode() 어느하나 override 경우, 둘다 재정의 되어야지 된다.

반드시 method 쌍으로 재정의 하도록 한다.



boolean, String 같이 java 기본 type 재정의하는 경우 발생

java 기본 type 그대로 사용하도록 한다.



if문이나 toString() 같은 내부에서 변수에 값을 할당한다.

값의 할당은 따로 line 잡아서 사용하도록 한다.



상수값을 사용하는 경우 발생한다.

상수값을 static final 이름을 지정해서 사용한다.



switch 문에 default case 없는 경우에 발생한다.

switch문은 반드시 default case 넣어서 작성한다.



try-catch 시에 throws 순서로 인하여 실행될 없는 catch문이 존재한다.

catch 만들때, exception 상속 상태를 확인하고 구성하도록 한다.



if문내에서 1 line으로 return한다.

if 문안에서 return 하지 않고, return값에 대한 명명을 정확히 한다.



if문의 결과를 그대로 return 한다.

if문의 로직 자체를 return 값으로 변경한다.



객체는 확장 가능하도록 되어야지 되고, public문은 반드시 final 재정의 되는 것을 막아줘야지 된다.

spring 사용하는 경우 Proxy aspectJ 의해서 재정의 되는 method 다음 규칙에서 에러를 발생시킬 있기 때문에 사용하지 않는다.



final class 생성자가 private 되어있는 경우 발생한다.

final class 경우에는 특별한 경우를 제외하고 사용하지 않는다.


spring 이용하는 경우에는 특히 사용할 필요가 없는 구성이다.


public static method만이 존재하는 class 생성자가 protected, private 되어 있다.

UtilityClass 경우에는 모두 public modifier 이용한다.



interface type만이 존재하고, method 존재하지 않는다.

type descript interface 사용하지 않는다.



getter/setter 사용하지 않고, 내부 변수에 접근 가능하다.

getter/setter 이용해서 property 처리를 하도록 한다.



java style input array parameter 이용한다. (java style : main(String[] args), C style : main(String args[])

java style 사용하도록 한다.



input parameter 내부에서 참조만 하는 경우, final 선언한다.

모든 input parameter final 사용하는 것을 기본 원칙으로 갖는다.


coding style 밀접한 연관이 있다.


"TODO: " 정확히 사용하지 않는 경우에 발생한다. (대소문자, 공백위치)

TODO 정확히 사용한다.



'L', '1', 'I', 'i' 명확히 구분할 있도록 method 이름과 객체이름을 짓는다.

명명규칙에 따라 이름을 작성하도록 한다.



'Code Inspection' 카테고리의 다른 글

PMD eclipse  (0) 2013.06.24  (0) 2013.05.22
checkstyle rule  (0) 2013.05.22

+ Recent posts