【工利其器】必會工具之(八)PMD篇——程式碼分析工具基本使用

  • 2019 年 11 月 10 日
  • 筆記

       如今,使用程式碼分析工具來代替人工進行程式碼審查,已經是大勢所趨了。用於Java程式碼檢測的工具中,不乏許許多多的佼佼者,其中PMD就是其中一款。PMD既可以獨立運行,也可以以命令行的形式運行,還可以作為插件在IDE中運行,本文將基於在Android Studio中的使用來介紹PMD的基本使用。

 

一、PMD簡介

       對於PMD名稱含義,有個有趣的現象,PMD不存在一個準確的名稱,在官網上你可以發現很有有趣的名稱 ,比如:Pretty Much Done,Project Meets Deadline等。PMD是一款程式程式碼檢查工具(可以支援多種語言,以Java為例),通過靜態分析Java源文件來獲知程式碼錯誤,也就是說在不運行不編譯Java程式的情況下直接掃描Java源文件,報告錯誤 。該軟體功能強大,掃描效率高,是Java程式設計師debug的好幫手。它附帶了許多可以直接使用的規則,利用這些規則可以找出Java源程式的許多問題,比如:

  • 可能的 Bugs:檢查潛在程式碼錯誤,如空 try/catch/finally/switch 語句
  • 未使用程式碼(Dead code):檢查未使用的變數,參數,方法
  • 複雜的表達式:檢查不必要的 if 語句,可被 while 替代的 for 循環
  • 重複的程式碼:檢查重複的程式碼
  • 循環體創建新對象:檢查在循環體內實例化新對象
  • 資源關閉:檢查 Connect,Result,Statement 等資源使用之後是否被關閉掉

       用戶還可以自己定義規則,檢查Java程式碼是否符合某些特定的編碼規範。例如,你可以編寫一個規則,要求PMD找出所有創建Thread對象的操作。

       PMD支援的編輯器包括:JDeveloper、Eclipse、JEdit、JBuilder、BlueJ、CodeGuide、NetBeans/Sun Java Studio Enterprise/Creator、IntelliJ IDEA(Android Studio是基於此編輯器)、TextPad、Maven、Ant、Gel、JCreator和Emacs。

 

二、PMD的安裝 

       通過File > Settings > Plugins > Browse repositories 搜索 “PMD”,找到“PMDPlugin”這一項,按照提示進行安裝,然後重啟即可。

 

三、使用PMD檢測程式碼

  1、啟動PMD檢測功能

    (1)從Tools菜單中啟動

       通過Tools > Run PMD可以看到如下的介面。從運行結果來看,如果通過該方式啟動,掃描的範圍就是整個個項目中的文件了。

        Pre Defined:表示預定義的規則,也就是該插件自帶的檢測規則。後面展開的列表中列處了所有的規則列表,想掃描哪一種類型的問題,點擊即可。其中“All”表示使用所有的規則。

        Custom Rules:自定的檢測規則。該插件允許用戶根據自己的需要自定義檢查規則,默認這裡是不可點擊的,需要在設置中導入自定義規則文件後方可選擇。

    (2)從右鍵菜單中啟動

       在文件或者編輯器中點擊右鍵,也可以看到“Run PMD”選項,和從“Tools”菜單中啟動一樣,這裡不贅述了。通過該方式啟動, 檢測範圍取決於滑鼠或游標當前所選中的區域。

  2、運行結果

       運行後會出現如下面板:

   

       左邊工具欄,滑鼠停留在上面會提示其功能,比較簡單就不啰嗦了。右邊顯示了檢測結果,這裡顯示的結果類別取決於我們運行的時候在“Pre Defined”中選擇的規則類型,因為前面選擇的“All”,所以所有的規則都顯示了。當點擊具體某一問題項時,會跳轉到對應的源碼中。

 

四、配置檢測規則

       通過File > Settings > Other Settings > PMD可以打開檢測規則的設置介面:

        在“RuleSets(規則設置)”介面可以管理自定義的檢測規則。因為在實際工作中,可能有些團隊需要根據實際情況自定義檢測規則,就可以通過這裡導入。如果要使用它,需要在啟動PMD進行檢測時選擇該自定義規則。

       點擊“Options”選項卡,在其中可以配置一些檢測規則選項

其中重點需要留意的是“Skip TestSource”這一項,因為在項目中有不少Android Studio自動生成的測試程式碼,如下所示,選擇上述選項後可以將其過濾掉。

 

五、PMD的高級使用

       本文主要介紹PMD的基本使用,同時限於筆者的水平有限,這裡僅簡單介紹一下它的高級使用。

       PMD功能非常強大,僅僅是針對Java的檢測就附帶了讓人眾多的規則,這裡提供一份《PMD插件分析程式碼規則(中文).xls》文檔,有興趣的可以下載深入了解:

       鏈接:https://pan.baidu.com/s/189OTD_k-RbEX4ABJbAMlIg

       提取碼:90f4

       對於自定義規則,這裡提供一個自定義模板(pmd_custom_rule.xml,可以直接導入使用),可以通過這個模板學習一下PMD的規則定義:

 1 <?xml version="1.0"?>   2 <ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="Android Application Rules"   3     xmlns="http://pmd.sf.net/ruleset/1.0.0"   4     xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"   5     xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd">   6   7     <description>Custom ruleset for ribot Android application</description>   8   9     <exclude-pattern>.*/R.java</exclude-pattern>  10     <exclude-pattern>.*/gen/.*</exclude-pattern>  11  12     <rule ref="rulesets/java/android.xml" />  13     <rule ref="rulesets/java/clone.xml" />  14     <rule ref="rulesets/java/finalizers.xml" />  15     <rule ref="rulesets/java/imports.xml">  16         <!-- Espresso is designed this way !-->  17         <exclude name="TooManyStaticImports" />  18     </rule>  19     <rule ref="rulesets/java/logging-java.xml">  20         <!-- This rule wasn't working properly and given errors in every var call info -->  21         <exclude name="GuardLogStatementJavaUtil" />  22     </rule>  23     <rule ref="rulesets/java/braces.xml">  24         <!-- We allow single line if's without braces -->  25         <exclude name="IfStmtsMustUseBraces" />  26     </rule>  27     <rule ref="rulesets/java/strings.xml" >  28         <!-- Exclude because causes problems with SQL Strings that usually require duplication -->  29         <exclude name="AvoidDuplicateLiterals"/>  30     </rule>  31     <rule ref="rulesets/java/basic.xml" />  32     <rule ref="rulesets/java/naming.xml">  33         <exclude name="AbstractNaming" />  34         <exclude name="LongVariable" />  35         <exclude name="ShortMethodName" />  36         <exclude name="ShortVariable" />  37         <exclude name="ShortClassName" />  38         <exclude name="VariableNamingConventions" />  39     </rule>  40 </ruleset>

 

友情鏈接:

       PMD Java rules官方文檔介紹:https://pmd.github.io/pmd-6.19.0/pmd_rules_java.html

       PMD 官網:https://pmd.github.io