Introduction to PMD – PMD简介

最后修改: 2017年 1月 8日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Simply put, PMD is a source code analyzer to find common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and so forth.

简单地说,PMD是一个源代码分析器,用于查找常见的编程缺陷,如未使用的变量、空的捕获块、不必要的对象创建等等。

It supports Java, JavaScript, Salesforce.com Apex, PLSQL, Apache Velocity, XML, XSL.

它支持Java、JavaScript、Salesforce.com Apex、PLSQL、Apache Velocity、XML、XSL。

In this article, we’ll focus on how to use PMD to perform static analysis in a Java project.

在这篇文章中,我们将重点介绍如何使用PMD在Java项目中进行静态分析。

2. Prerequisites

2.先决条件

Let’s start with setting up PMD into a Maven project – using and configuring the maven-pmd-plugin:

让我们先在Maven项目中设置PMD–使用并配置maven-pmd-plugin

<project>
    ...
    <reporting>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-pmd-plugin</artifactId>
                <version>3.7</version>
                <configuration>
                    <rulesets>
                        <ruleset>/rulesets/java/braces.xml</ruleset>
                        <ruleset>/rulesets/java/naming.xml</ruleset>
                    </rulesets>
                </configuration>
            </plugin>
        </plugins>
    </reporting>
</project>

You can find the latest version of maven-pmd-plugin here.

您可以找到最新版本的maven-pmd-plugin 这里

Notice how we’re adding rulesets in the configuration here – these are a relative path to already define rules from the PMD core library.

注意我们是如何在这里的配置中添加规则集的–这些是已经从PMD核心库中定义的规则的相对路径。

Finally, before running everything, let’s create a simple Java class with some glaring issues – something that PMD can start reporting problems on:

最后,在运行一切之前,让我们创建一个有一些明显问题的简单Java类–PMD可以开始报告问题的东西。

public class Ct {

    public int d(int a, int b) {
        if (b == 0)
            return Integer.MAX_VALUE;
        else
            return a / b;
    }
}

3. Run PMD

3.运行PMD

With the simple PMD config and the sample code – let’s generate a report in the build target folder:

有了简单的PMD配置和示例代码–让我们在构建目标文件夹中生成一份报告。

mvn site

The generated report is called pmd.html and is located in the target/site folder:

生成的报告称为pmd.html,位于target/site文件夹中。

Files

com/baeldung/pmd/Cnt.java

Violation                                                                             Line

Avoid short class names like Cnt                                   1–10 
Avoid using short method names                                  3 
Avoid variables with short names like b                        3 
Avoid variables with short names like a                        3 
Avoid using if...else statements without curly braces 5 
Avoid using if...else statements without curly braces 7 

As you can see – we’re not getting results. The report shows violations and line numbers in your Java code, according to PMD.

正如你所看到的–我们没有得到结果。报告显示了你的Java代码中的违规行为和行数,根据PMD。

4. Rulesets

4.规则集

The PMD plugin uses five default rulesets:

PMD插件使用五个默认规则集。

  • basic.xml
  • empty.xml
  • imports.xml
  • unnecessary.xml
  • unusedcode.xml

You may use other rulesets or create your own rulesets, and configure these in the plugin:

你可以使用其他规则集或创建你自己的规则集,并在插件中配置这些规则。

<project>
    ...
    <reporting>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-pmd-plugin</artifactId>
                <version>3.7</version>
                <configuration>
                    <rulesets>
                        <ruleset>/rulesets/java/braces.xml</ruleset>
                        <ruleset>/rulesets/java/naming.xml</ruleset>
                        <ruleset>/usr/pmd/rulesets/strings.xml</ruleset>
                        <ruleset>http://localhost/design.xml</ruleset>
                    </rulesets>
                </configuration>
            </plugin>
        </plugins>
    </reporting>
</project>

Notice that we’re using either a relative address, an absolute address or even a URL – as the value of the ‘ruleset’ value in configuration.

注意,我们使用的是相对地址、绝对地址甚至是URL–作为配置中’ruleset’的值。

A clean strategy for customizing which rules to use for a project is to write a custom ruleset file. In this file, we can define which rules to use, add custom rules, and customize which rules to include/exclude from the official rulesets.

定制项目使用的规则的一个干净的策略是编写一个自定义规则集文件。在这个文件中,我们可以定义使用哪些规则,添加自定义规则,以及自定义包括/排除官方规则集的哪些规则。

5. Custom Ruleset

5.自定义规则集

Let’s now choose the specific rules we want to use from existing sets of rules in PMD – and let’s also customize them.

现在让我们从PMD中现有的规则集中选择我们要使用的具体规则–同时让我们对它们进行定制。

First, we’ll create a new ruleset.xml file. We can, of course, use one of the existing rulesets files as an example and copy and paste that into our new file, delete all the old rules from it, and change the name and description:

首先,我们将创建一个新的ruleset.xml文件。当然,我们可以使用现有的一个规则集文件作为例子,将其复制并粘贴到我们的新文件中,删除其中所有的旧规则,并更改名称和描述。

<?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 checks my code for bad stuff
    </description>
</ruleset>

Secondly, let’s add some rule references:

其次,让我们添加一些规则参考。

<!-- We'll use the entire 'strings' ruleset -->
<rule ref="rulesets/java/strings.xml"/>

Or add some specific rules:

或者增加一些具体的规则。

<rule ref="rulesets/java/unusedcode.xml/UnusedLocalVariable"/>
<rule ref="rulesets/java/unusedcode.xml/UnusedPrivateField"/>
<rule ref="rulesets/java/imports.xml/DuplicateImports"/>
<rule ref="rulesets/java/basic.xml/UnnecessaryConversionTemporary"/>

We can customize the message and priority of the rule:

我们可以自定义规则的信息和优先级。

<rule ref="rulesets/java/basic.xml/EmptyCatchBlock"
  message="Must handle exceptions">
    <priority>2</priority>
</rule>

And you also can customize a rule’s property value like this:

而且你还可以像这样定制一个规则的属性值。

<rule ref="rulesets/java/codesize.xml/CyclomaticComplexity">
    <properties>
        <property name="reportLevel" value="5"/>
    </properties>
</rule>

Notice that you can customize individual referenced rules. Everything but the class of the rule can be overridden in your custom ruleset.

请注意,你可以定制个别的引用规则。除了规则的类别,其他的都可以在你的自定义规则集中被覆盖。

Next – you can also excluding rules from a ruleset:

下一步–你也可以从一个规则集中排除规则。

<rule ref="rulesets/java/braces.xml">
    <exclude name="WhileLoopsMustUseBraces"/>
    <exclude name="IfElseStmtsMustUseBraces"/>
</rule>

Next – you can also exclude files from a ruleset using exclude patterns, with an optional overriding include pattern.

下一步–你也可以使用排除模式将文件从规则集中排除出来,并可选择覆盖包含模式。

A file will be excluded from processing when there is a matching exclude pattern, but no matching include pattern.

当有一个匹配的排除模式,但没有匹配的包含模式时,一个文件将被排除在处理之外。

Path separators in the source file path are normalized to be the ‘/’ character, so the same ruleset can be used on multiple platforms transparently.

源文件路径中的路径分隔符被规范化为’/’字符,因此同一规则集可以在多个平台上透明地使用。

Additionally, this exclude/include technique works regardless of how PMD is used (e.g. command line, IDE, Ant), making it easier to keep the application of your PMD rules consistent throughout your environment.

此外,这种排除/包括技术不管PMD是如何使用的(如命令行、IDE、Ant),都能发挥作用,使你的PMD规则的应用在你的环境中更容易保持一致。

Here’s a quick example:

这里有一个简单的例子。

<?xml version="1.0"?>
<ruleset ...>
    <description>My ruleset</description>
    <exclude-pattern>.*/some/package/.*</exclude-pattern>
    <exclude-pattern>
       .*/some/other/package/FunkyClassNamePrefix.*
    </exclude-pattern>
    <include-pattern>.*/some/package/ButNotThisClass.*</include-pattern>
    <rule>...
</ruleset>

6. Conclusion

6.结论

In this quick article, we introduced PMD – a flexible and highly configurable tool focused on static analysis of Java code

在这篇文章中,我们介绍了PMD–一个灵活且高度可配置的工具,专注于Java代码的静态分析。

As always, the full code presented in this tutorial is available over on Github.

一如既往,本教程中所介绍的完整代码可在Github上获得