PMD插件

添加PMD插件掃描潛在的bug

目錄

什麼是PMD
在gradle中使用
在maven中使用
idea插件
Ruleset default內容
參考

上一節使用checkstyle來規範你的項目主要解決了代碼編碼規範問題,比如縮進換行等。這次繼續代碼健康工具類PMD。

什麼是PMD

PMD真的不像checkstyle這樣的東西所見即所得啊,去官網找了半天也沒有找到解釋。官網都直接說是PMD。

We've been trying to find the meaning of the letters PMD - because frankly, we don't really know. We just think the letters sound good together.

簡單來說,PMD是一個代號,是一個靜態代碼檢測工具。它可以用來檢查

  • 潛在的bug:空的try/catch/finally/switch語句
  • 未使用的代碼:未使用的局部變量、參數、私有方法等
  • 可選的代碼:String/StringBuffer的濫用
  • 複雜的表達式:不必須的if語句、可以使用while循環完成的for循環
  • 重複的代碼:拷貝/粘貼代碼意味着拷貝/粘貼bugs

總之,這是一個輔助我們檢測潛在bug的工具,大大減少了人工審查成本,提高編碼效率。

在gradle中使用

gradle還是一貫的簡單,新建pmd.gradle

/**
 * The PMD Plugin
 *
 * Gradle plugin that performs quality checks on your project’s Java source files using PMD
 * and generates reports from these checks.
 *
 * Tasks:
 * Run PMD against {rootDir}/src/main/java: ./gradlew pmdMain
 * Run PMD against {rootDir}/src/test/java: ./gradlew pmdTest
 *
 * Reports:
 * PMD reports can be found in {project.buildDir}/build/reports/pmd
 *
 * Configuration:
 * PMD is very configurable. The configuration file is located at {rootDir}/config/pmd/pmd-ruleset.xml
 *
 * Additional Documentation:
 * https://docs.gradle.org/current/userguide/pmd_plugin.html
 */

apply plugin: 'pmd'

pmd {
    // The version of the code quality tool to be used.
    // The most recent version of PMD can be found at https://pmd.github.io
    toolVersion = "5.8.1"

    // The source sets to be analyzed as part of the check and build tasks.
    // Use 'sourceSets = []' to remove PMD from the check and build tasks.
    sourceSets = [project.sourceSets.main]

    // The directory where reports will be generated.
    reportsDir = file("$project.buildDir/reports/pmd")

    // Whether to allow the build to continue if there are warnings.
    ignoreFailures = false

    // Whether or not rule violations are to be displayed on the console.
    consoleOutput = true

    // The custom rule set files to be used.
    ruleSetConfig = resources.text.fromFile("$rootProject.projectDir/config/pmd/pmd-ruleset.xml")
}

添加我們的pmd-ruleset.xml配置文件, 這個ruleset有很多種,我們可以先把所有的加上,然後在開發中調整,直到找到最合適的配置方案。因爲全部的規則太多,會導致你花費大量的時間解決PMD問題。

ruleset內容可以在https://maven.apache.org/plugins/maven-pmd-plugin/examples/usingRuleSets.html 這裏找到

然後在build.gradle中添加

apply from: 'pmd.gradle'

執行

./gradlew check  或者 ./gradlew build

報告位置:

build/reports/pmd/main.html

在maven中使用

maven需要把ruleset放到resources下讀取,如果是單moudle項目,直接就可以。如果是多模塊項目,需要額外做一些工作。

我們來新建一個項目來單獨存儲配置文件,build-tools. 在resources下放置ruleset。名字叫做pmd-ruleset.xml, 內容見https://maven.apache.org/plugins/maven-pmd-plugin/examples/usingRuleSets.html

然後maven install把這個子模塊給安裝到本地倉庫。

接着修改parent pom

<build>

    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-pmd-plugin</artifactId>
          <version>3.10.0</version>
          <dependencies>
            <dependency>
              <groupId>com.shuwei</groupId>
              <artifactId>build-tools</artifactId>
              <version>0.0.1</version>
            </dependency>
          </dependencies>
          <configuration>
            <sourceEncoding>utf-8</sourceEncoding>
            <minimumTokens>100</minimumTokens>
            <targetJdk>${java.version}</targetJdk>
            <excludes>
              <exclude>**/message/*.java</exclude>
              <exclude>**/generated/*.java</exclude>
            </excludes>
            <excludeRoots>
              <excludeRoot>target/generated-sources</excludeRoot>
            </excludeRoots>
            <rulesets>
              <ruleset>pmd-ruleset.xml</ruleset>
            </rulesets>
            <printFailingErrors>true</printFailingErrors>
          </configuration>
          <executions>
            <execution>
              <id>install</id>
              <phase>install</phase>
              <goals>
                <goal>pmd</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </pluginManagement>


    <!--所有子模塊都要執行的plugin-->
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-pmd-plugin</artifactId>
      </plugin>
    </plugins>

  </build>


  <reporting>
    <!--所有子模塊都要執行的報告-->
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-pmd-plugin</artifactId>
      </plugin>
    </plugins>
  </reporting>

和上一節checkstyle不同的時候,這裏的plugin下新增了dependency節點。這個節點負責加載一些資源過來,比如我們的配置文件ruleset。所以,這個dependency要先於項目存在,所以纔要先單獨install一下。當然,也可以把這個項目放到maven私服上,這樣更簡單了。

依舊把pmd的運行綁定到install命令上,這樣,我們運行maven install的時候就可以進行pmd檢查了。

檢查報告在

j-context/target/site/pmd.html

也可以單獨運行pmd

mvn pmd:pmd

idea插件

搜索安裝idea pmd插件,導入我們的ruleset, 然後在項目上右鍵,run pmd即可。

Ruleset default內容

可以在maven官網看到: https://maven.apache.org/plugins/maven-pmd-plugin/examples/usingRuleSets.html

PMD 包含 16 個規則集,涵蓋了 Java 的各種常見問題,其中一些規則要比其他規則更有爭議:

基本(rulesets/basic.xml)—— 規則的一個基本合集,可能大多數開發人員都不認同它: catch 塊不該爲空,無論何時重寫 equals(),都要重寫 hashCode(),等等。

命名(rulesets/naming.xml)—— 對標準 Java 命令規範的測試:變量名稱不應太短;方法名稱不應過長;類名稱應當以小寫字母開頭;方法和字段名應當以小寫字母開頭,等等。

未使用的代碼(rulesets/unusedcode.xml)—— 查找從未使用的私有字段和本地變量、執行不到的語句、從未調用的私有方法,等等。

設計(rulesets/design.xml)—— 檢查各種設計良好的原則,例如: switch 語句應當有 default 塊,應當避免深度嵌套的 if 塊,不應當給參數重新賦值,不應該對 double 值進行相等比較。

導入語句(rulesets/imports.xml)—— 檢查 import 語句的問題,比如同一個類被導入兩次或者被導入 java.lang 的類中。

JUnit 測試(rulesets/junit.xml)—— 查找測試用例和測試方法的特定問題,例如方法名稱的正確拼寫,以及 suite() 方法是不是 static 和 public。

字符串(rulesets/string.xml)—— 找出處理字符串時遇到的常見問題,例如重複的字符串標量,調用 String 構造函數,對 String 變量調用 toString() 方法。

括號(rulesets/braces.xml)—— 檢查 for、 if、 while 和 else 語句是否使用了括號。

代碼尺寸(rulesets/codesize.xml)—— 測試過長的方法、有太多方法的類以及重構方面的類似問題。

Javabean(rulesets/javabeans.xml)—— 查看 JavaBean 組件是否違反 JavaBean 編碼規範,比如沒有序列化的 bean 類。

終結函數(finalizer)—— 因爲在 Java 語言中, finalize() 方法不是那麼普遍(我上次編寫這個代碼也經是好多年前的事了),所以它們的使用規則雖然很詳細,但是人們對它們相對不是很熟悉。這類檢查查找 finalize() 方法的各種問題,例如空的終結函數,調用其他方法的 finalize() 方法,對 finalize() 的顯式調用,等等。

克隆(rulesets/clone.xml)—— 用於 clone() 方法的新規則。凡是重寫 clone() 方法的類都必須實現 Cloneable, clone() 方法應該調用 super.clone(),而 clone() 方法應該聲明拋出 CloneNotSupportedException 異常,即使實際上沒有拋出異常,也要如此。

耦合(rulesets/coupling.xml)—— 查找類之間過度耦合的跡象,比如導入內容太多;在超類型或接口就已經夠用的時候使用子類的類型;類中的字段、變量和返回類型過多等。

嚴格的異常(rulesets/strictexception.xml)—— 針對異常的測試:不應該聲明該方法而拋出 java.lang.Exception 異常,不應當將異常用於流控制,不應該捕獲 Throwable,等等。

有爭議的(rulesets/controversial.xml)—— PMD 的有些規則是有能力的 Java 程序員可以接受的。但還是有一些爭議。這個規則集包含一些更有問題的檢驗,其中包括把 null 賦值給變量、方法中有多個返回點,以及從 sun 包導入等。

日誌(rulesets/logging-java.xml)—— 查找 java.util.logging.Logger 的不當使用,包括非終狀態(nonfinal)、非靜態的記錄器,以及在一個類中有多個記錄器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章