添加PMD插件掃描潛在的bug
- 本文作者:@Ryan Miao
- 本文鏈接:https://www.cnblogs.com/woshimrf/p/using-pmd.html
- 版權聲明: 本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 許可協議。轉載請註明出處!
目錄
什麼是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)、非靜態的記錄器,以及在一個類中有多個記錄器。