PMD简介

2025/04/25

1. 概述

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

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

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

2. 先决条件

让我们首先将PMD设置到Maven项目中-使用和配置maven-pmd-plugin:

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

你可以在此处找到最新版本的maven-pmd-plugin。

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

最后,在运行所有内容之前,让我们创建一个包含一些明显问题的简单Java类-PMD可以开始报告问题:

public class Ct {

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

3. 运行PMD

使用简单的PMD配置和示例代码,让我们在构建目标文件夹中生成一份报告:

mvn site

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

Files

cn/tuyucheng/taketoday/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 

如你所见,我们没有得到结果,根据PMD的数据,报告显示了Java代码中的违规情况和行号。

4. 规则集

PMD插件使用5个默认规则集:

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

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

<project>
    ...
    <reporting>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-pmd-plugin</artifactId>
                <version>3.23.0</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>

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

自定义项目规则的一个简洁策略是编写自定义规则集文件,在此文件中,我们可以定义要使用的规则、添加自定义规则以及自定义在官方规则集中包含/排除哪些规则。

5. 自定义规则集

现在让我们从PMD中现有的规则集中选择我们想要使用的特定规则- 并且让我们自定义它们。

首先,我们将创建一个新的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>

其次,我们来添加一些规则引用:

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

或者添加一些具体规则:

<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"/>

我们可以自定义规则的消息和优先级:

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

你还可以像这样自定义规则的属性值:

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

请注意,你可以自定义单个引用规则。除了规则的类别之外,自定义规则集中的所有内容都可以被覆盖。

接下来,你还可以从规则集中排除规则:

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

接下来,你还可以使用排除模式从规则集中排除文件,并使用可选的覆盖包含模式。

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

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

此外,无论如何使用PMD(例如命令行、IDE、Ant),此排除/包含技术都有效,从而更容易在整个环境中保持PMD规则的应用一致。

这是一个简单的例子:

<?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. 总结

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

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章