您好,登錄后才能下訂單哦!
一 PMD簡(jiǎn)介
PMD是一款代碼靜態(tài)檢查工具,可以檢查出很多代碼中潛在的bug以及讓人感到疑惑的代碼,具體大家可以百度下。
二 PMD源代碼下載
下載地址:
https://github.com/pmd/pmd/tree/pmd/5.5.x
需要注意的是注意選擇branch,一般選擇最新的branch;然后可以用git clone下來(lái),或者直接下載zip壓縮包。
如下:
從上圖也可以看到,pmd支持的語(yǔ)言有很多,java的檢測(cè)那就是在pmd-java里面。
三 maven下載和環(huán)境變量配置
參考網(wǎng)址:
http://blog.csdn.net/jiuqiyuliang/article/details/45390313
下載maven
地址:maven下載
配置MAVEN_HOME和path
檢測(cè)maven環(huán)境:開(kāi)始菜單->運(yùn)行->cmd->mvn -v
如下圖:
四 配置JDK
這個(gè)網(wǎng)上資料太多了,就不細(xì)說(shuō)了, 比如:
http://www.cnblogs.com/smyhvae/p/3788534.html
五 編譯PMD
在home目錄配置 ~/.m2/toolchains.xml 這里我發(fā)現(xiàn)分兩種情況:
第一種,我在本地裝了git bash,所以打開(kāi)git bash后,敲入cd ~,如下圖:
那這種的話直接在c/users/rongwei.huang目錄創(chuàng)建./m2/toolchains.xml文件
可以把PMD源代碼目錄下example-toolchains.xml文件拷貝過(guò)去,改成toolchains.xml
如下:
修改toolchains.xml,主要就是配置JDK版本和路徑,我使用JDK1.8編譯,所以配置如下:
<?xml version="1.0" encoding="UTF8"?> <toolchains> <!-- place this file in ${user.home}/.m2/toolchains.xml --> <!-- adjust the paths to jdkhome --> <toolchain> <type>jdk</type> <provides> <version>1.8</version> </provides> <configuration> <jdkHome>/path/to/jdk/1.8</jdkHome> <!-- Linux --> <jdkHome>/Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home</jdkHome> <!-- MacOSX --> <jdkHome>h:\\Android\\jdk1.8.0_25</jdkHome> <!-- Windows --> </configuration> </toolchain> </toolchains>
第二種,就是沒(méi)有安裝類似git bash這種linux環(huán)境軟件,這種我沒(méi)有試過(guò),別的帖子有介紹:
PMD編譯
2. 編譯PMD源代碼
配置完toolchains.xml之后,在PMD源代碼目錄打開(kāi)命令行,執(zhí)行
mvn clean package
如下圖:
3. 編譯遇到問(wèn)題
在編譯的時(shí)候,我遇到下面兩個(gè)問(wèn)題:
a. java doc 編譯失敗
可以參考這篇帖子解決方法: PMD Java doc '->'編譯失敗
b. 測(cè)試項(xiàng)EcmascriptTokenizerTest沒(méi)有通過(guò)
我直接把它注釋掉了
4. 編譯成功,查看結(jié)果
在PMD源代碼pmd-dist目錄,target文件夾查看zip文件
5. 解壓PMD
拷貝pmd-bin-5.5.8-SNAPSHOT.zip到一個(gè)沒(méi)有中文字符的路徑,然后解壓。
解壓后,主要包括bin和lib兩個(gè)文件夾
bin是可執(zhí)行程序,下面我們會(huì)用里面的程序編寫(xiě)自定義規(guī)則。
lib包含很多jar包,jar包里面包含規(guī)則的實(shí)現(xiàn)以及描述的xml文件。
六 自定義PMD規(guī)則
可以參考這篇帖子: 自定義PMD規(guī)則, 不過(guò)也說(shuō)說(shuō)自己的操作方法
eclipse打開(kāi)PMD源代碼工程
為了寫(xiě)代碼方便一點(diǎn),可以用Eclipse來(lái)打開(kāi),具體是:
File->New->Java Project->去掉Use default location->選擇PMD的源代碼路徑->finish
2. 創(chuàng)建規(guī)則檢測(cè)類
在java規(guī)則里面創(chuàng)建一個(gè)新的規(guī)則類WhileLoopMustUseBracesRule.java,繼承自AbstractJavaRule.java
路徑:
pmd-source\pmd-java\src\main\java\net\sourceforge\pmd\lang\java\rule\
如上面那個(gè)帖子說(shuō)的,我們要?jiǎng)?chuàng)建一個(gè)規(guī)則檢測(cè)java代碼while循環(huán)必須有{}
也就是這種寫(xiě)法是錯(cuò)誤的:
while(condition)
i++;
需要改成這樣
while(condition) {
i++;
}
所以,我們需要一個(gè)類來(lái)檢測(cè)它。
如下:
這個(gè)類主要重寫(xiě)了檢測(cè)方法visit,至于為什么這么寫(xiě),可以參考上面這個(gè)帖子:自定義PMD規(guī)則
3. 創(chuàng)建描述性xml
在pmd-source\pmd-java\src\main\resources\rulesets\java\目錄下創(chuàng)建自定義規(guī)則的描述性xml,在這個(gè)目錄可以看到很多已經(jīng)有的xml,比如:
其中android.xml表示的是針對(duì)android的檢測(cè),basic.xml表示基本通用的檢測(cè)。
那我們也可以把basic.xml拷貝一份,改成自定義的xml,比如mycustomrules.xml
如下:
<?xml version="1.0"?> <ruleset name="mycustomrule" 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>custom rule</description> <rule name="WhileLoopsMustUseBracesRule" language="java" since="5.6" message="while loop must has braces as first element you are in error!!!" class="net.sourceforge.pmd.lang.java.rule.WhileLoopMustUseBracesRule" externalInfoUrl="${pmd.website.baseurl}/rules/java/basic.html#JumbledIncrementer"> <description>while loop must has braces as first element</description> <priority>3</priority> <example> <![CDATA[ class Example { void bar() { while(baz) //need has {} buz.doSomething(); } } ]]> </example> </rule> </ruleset>
上面有幾個(gè)描述性信息:
description: 自定義規(guī)則描述
rule name: 名稱
language: java
since: 表示從哪個(gè)pmd版本開(kāi)始有這個(gè)規(guī)則
message: 用來(lái)提示用戶出錯(cuò)的描述性信息
class: 表示具體用來(lái)檢測(cè)的類,也就是我們自定義的那個(gè)類
externalInfoUrl: 在生成的html報(bào)告中,用來(lái)給用戶點(diǎn)擊跳轉(zhuǎn)到幫助頁(yè)面的鏈接。在幫助頁(yè)面有這個(gè)錯(cuò)誤的更詳細(xì)的描述信息;
description: 出錯(cuò)描述
priority: 優(yōu)先級(jí)
example: 出錯(cuò)示例
4. 編譯打包
在PMD源代碼下面的pmd-java目錄,打開(kāi)命令行,執(zhí)行
mvn clean package
在編譯目錄pmd-source\pmd-java\target\下查看編譯結(jié)果
pmd-java-5.5.8-SNAPSHOT.jar
可以用壓縮工具查看這個(gè)jar是否包含了我們自定義的xml和java文件
5. 拷貝生成的jar到PMD-bin解壓目錄
在上面第五步,我們編譯了PMD源代碼,并且生成了pmd bin壓縮包。然后拷貝到了一個(gè)沒(méi)有中文字符的目錄。
那我們現(xiàn)在繼續(xù)把java編譯的jar包,拷貝過(guò)去,路徑是pmd-bin的lib下面,如下:
6. 利用自定義規(guī)則檢測(cè)java代碼
在pmd-bin目錄打開(kāi)命令行,執(zhí)行
pmd.bat -d e:\work_space\Android-Prototype\app\src\main -f html -R java-mycustomrules
解釋下參數(shù):
-d: 表示你要檢查的java源代碼目錄
-f: 表示輸出的內(nèi)容格式是html
-R: 表示要使用的規(guī)則,上面表示的是java里面的mycustomrules規(guī)則
其中hello pmd使我們打印的log:
System.out.println("hello pmd");
上面檢測(cè)到一個(gè)錯(cuò)誤BaseActivity.java 78行有個(gè)while循環(huán)沒(méi)有用{}
代碼如下:
七 用xpath語(yǔ)法自定義規(guī)則
這個(gè)可以參考帖子 xpath自定義規(guī)則
八 在AndroidStudio中配置PMD
增加配置模塊
可以新建一個(gè)module為config,在config module的quality.gradle里面配置pmd的task,如下:
apply plugin: 'pmd'
check.dependsOn 'pmd' task pmd(type: Pmd) { ruleSetFiles = files("${project.rootDir}/config/quality/pmd/java/basic.xml", //基本代碼規(guī)范 "${project.rootDir}/config/quality/pmd/java/android.xml") //android相關(guān) ruleSets = [] ignoreFailures = true source 'src' include '**/*.java' exclude '**/gen/**' reports { xml.enabled = true html.enabled = true xml { destination "${project.buildDir}/reports/pmd/pmd.xml" } html { destination "${project.buildDir}/reports/pmd/pmd.html" } } }
簡(jiǎn)單描述下這幾個(gè)屬性:
ruleSetFiles: 自定義的檢測(cè)文件集合
ruleSets=[]: 表示不用默認(rèn)的檢測(cè)xml,使用自定義的
如果沒(méi)有自定義規(guī)則,可以用系統(tǒng)的,那么ruleSets可以這樣寫(xiě):
ruleSets = ["java-unusedcode", "java-basic"]
中括號(hào)表示要檢測(cè)的類型,不過(guò)這樣有個(gè)缺點(diǎn),如果我想去除java-basic里面一項(xiàng)檢查,很難做到,不如自定義規(guī)則方便。
ignoreFailures=true: 表示如果有錯(cuò)誤,那么編譯報(bào)錯(cuò);如果是false,則只是輸出錯(cuò)誤報(bào)表,并不會(huì)中斷編譯。
source:目錄
include: 包含文件
exclude: 不包含的文件
reports:輸出報(bào)表的路徑, xml.enabled表示是否輸出xml。
在app的build.gradle增加對(duì)這個(gè)模塊gradle的引用
apply from: '../config/quality.gradle'
執(zhí)行編譯
可以右擊AndroidStudio的gradle里面pmd這個(gè)task(如果沒(méi)有的話,可以build->rebuild project,在右邊Gradle Projects里面刷新下)
或者在項(xiàng)目根目錄,執(zhí)行gradle pmd
7. 在Android Studio里面點(diǎn)擊pmd和在命令行執(zhí)行 gradle pmd的區(qū)別
上面介紹了兩種啟動(dòng)pmd檢查的方法: Android Stdudio中點(diǎn)擊pmd和命令行中興gradle pmd
我發(fā)現(xiàn)這種方法的檢查結(jié)果不盡相同,經(jīng)過(guò)仔細(xì)檢查,終于發(fā)現(xiàn)了原因:
所用的pmd版本不同
a. Android Studio中點(diǎn)擊pmd按鈕執(zhí)行的的pmd版本路徑如下:
File->Settings->搜索gradle,如下圖:
那我的Android Studio編譯pmd使用的pmd路徑就是 D:/gradle_jar_cache
這個(gè)路徑是我自己配置的。
如果這個(gè)路徑下沒(méi)有pmd,那么它會(huì)去下載,下載的路徑在項(xiàng)目下面的build.gradle中配置,也即是maven服務(wù)器地址。
allprojects { repositories { // jcenter() maven { url ' } mavenCentral() } }
b. 命令行執(zhí)行g(shù)radle pmd
說(shuō)下這種方法的pmd路徑,因?yàn)樽约涸贕radle里面找了好久也沒(méi)有找到,后面突然想到了默認(rèn)路徑,也就是"c:\Users\rongwei.huang\.gradle\"
自己就把這個(gè)文件夾備份后刪除,再在命令行執(zhí)行g(shù)radle pmd,果然它首先就去進(jìn)行了下載jar包操作。
在這個(gè)目錄搜索pmd,發(fā)現(xiàn)它的版本是5.2.3與Android Studio里面用的5.5.4不一樣,所以兩者會(huì)有不同的檢查結(jié)果。
因?yàn)槲业氖荱nusedPrivateMethod 檢查不同,也就是沒(méi)有被使用的私有方法檢查,5.2.3會(huì)誤報(bào);所以我對(duì)比了下源代碼。
5.2.3的源代碼沒(méi)有找到,拿5.0版本和5.5.4版本對(duì)比,發(fā)現(xiàn)它們的實(shí)現(xiàn)不一樣:
c. 疑問(wèn)
1. Gradle在哪里配置pmd版本的呢?比如我的會(huì)自動(dòng)下載5.2.3,那這個(gè)是在哪里配置的呢?
2. Gradle是在哪里配置默認(rèn)pmd路徑的呢?也就是"c:\Users\rongwei.huang\.gradle\"
這兩點(diǎn)沒(méi)有找到。
如果有找到的同學(xué),可以留言告訴我,謝謝~
````分割線````
已經(jīng)找到了Gradle為什么會(huì)下載到c:\Users\rongwei.huang\.gradle\, 這個(gè)是當(dāng)前用戶根目錄。
如果要修改的話,可以添加環(huán)境變量“GRADLE_USER_HOME”,為它設(shè)置一個(gè)目錄即可。
詳見(jiàn)gradle-wrapper.properties
#Mon Sep 12 15:17:35 CEST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-rc-1-bin.zip
附錄:
下面是pmd的一些相關(guān)網(wǎng)址
PMD github源代碼 下載時(shí)注意branch
PMD介紹 包括大部分PMD檢查分類的介紹,比如basic是干什么
PMD自定義規(guī)則的實(shí)現(xiàn)
PMD官網(wǎng)
安裝maven
PMD java doc編譯失敗
謝謝上面的博主。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。