Перейти к основному содержимому

Введение в PMD

· 4 мин. чтения

1. Обзор

Проще говоря, PMD — это анализатор исходного кода для поиска распространенных ошибок программирования, таких как неиспользуемые переменные, пустые блоки catch, создание ненужных объектов и т. д.

Он поддерживает 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.7</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

com/foreach/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 использует пять наборов правил по умолчанию:

  • базовый.xml
  • пустой.xml
  • импорт.xml
  • ненужный.xml
  • неиспользованный код.xml

Вы можете использовать другие наборы правил или создавать свои собственные наборы правил и настраивать их в плагине:

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

Обратите внимание, что мы используем либо относительный адрес, либо абсолютный адрес, либо даже URL — в качестве значения параметра «набор правил» в конфигурации.

Чистой стратегией настройки правил, которые следует использовать в проекте, является написание пользовательского файла набора правил . В этом файле мы можем определить, какие правила использовать, добавить пользовательские правила и настроить, какие правила включать или исключать из официальных наборов правил.

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.

Как всегда, полный код, представленный в этом руководстве, доступен на Github .