天天看點

全面剖析PMD靜态代碼掃描工具

PMD是使用JavaCC生成解析器來解析源代碼并生成AST(抽象文法樹)的,這兩天對PMD及自定義規則做了調研及實驗,部分說明來自官方說明文檔,做了大部分參數的較長的描述及測試,少數幾個參數不明白含義,有了解的朋友歡迎讨論。

1     調研對象

pmd-bin-6.4.0【PMD可執行版本】

·      bin

·      designer.bat【界面工具,能将java源代碼轉化為AST(抽象文法樹),個人推薦使用】

·      bgastviewer.bat【界面工具,與designer.bat功能相似】

·      cpd.bat【用來查找重複代碼的工具,指令行版】

·      cpdgui.bat【用來查找重複代碼的工具,GUI版】

·      pmd.bat【Window平台下運作PMD需要使用的檔案】

·      run.sh【Linux平台下運作PMD需要使用的檔案】

·      lib【該目錄存放PMD運作依賴的jar包,包括第三方jar包和各種語言的子產品jar包】

2 基本使用

格式:pmd -d [filename|jar or zip file containing source code|directory]-f [report format] -R [ruleset file]

示例:E:\pmd-bin-6.4.0>bin\pmd.bat -d E:\name -f html -R java-basic,java-design

如果要将生成的結果儲存出來可以使用指令行重定向儲存到指定路徑——

E:\pmd-bin-6.4.0>bin\pmd.bat -d E:\name -f html -R java-basic,java-design>report.html

Option

Description

Required

Applies for language

-rulesets / -R

Comma separated list of ruleset names to use

yes

-dir / -d

Root directory for sources

-format / -f

Report format type. Default format is `text`.

no

-auxclasspath

Specifies the classpath for libraries used by the source code. This is used by the type resolution. Alternatively a `file://` URL to a text file containing path elements on consecutive lines can be specified.

-uri / -u

Database URI for sources. If this is given, then you don't need to provide `-dir`.

plsql

-filelist

Path to file containing a comma delimited list of files to analyze. If this is given, then you don't need to provide `-dir`.

-debug / -verbose / -D / -V

Debug mode. Prints more log output.

-help / -h / -H

Display help on usage.

-encoding / -e

Specifies the character set encoding of the source code files PMD is reading (i.e. UTF-8). Default is `UTF-8`.

-threads / -t

Sets the number of threads used by PMD. Default is `1`. Set threads to '0' to disable multi-threading processing.

-benchmark / -b

Benchmark mode - output a benchmark report upon completion; defaults to System.err

-stress / -S

Performs a stress test.

-shortnames

Prints shortened filenames in the report.

-showsuppressed

Report should show suppressed rule violations.

-suppressmarker

Specifies the string that marks the line which PMD should ignore; default is `NOPMD`.

-minimumpriority / -min

Rule priority threshold; rules with lower priority than configured here won't be used. Default is `5` - which is the lowest priority.

-property / -P

`{name}={value}`: Define a property for a report format.

-reportfile / -r

Send report output to a file; default to System.out

-version / -v

Specify version of a language PMD should use.

-language / -l

Specify a language PMD should use.

-failOnViolation {true|false}

By default PMD exits with status 4 if violations are found. Disable this option with '-failOnViolation false' to exit with 0 instead and just write the report.

-cache

Specify a location for the analysis cache file to use. This can greatly improve analysis performance and is highly recommended.

-no-cache

Explicitly disable incremental analysis. This switch turns off suggestions to use Incremental Analysis, and causes the -cacheoption to be discarded if it is provided.

2 規則

2.1規則集

RuleCategories

PMD 自帶了很多規則集合,并且分類寫入不同的 ruleset 檔案,如

Basic 包含每人都必須遵守的代碼最佳實踐,如EmptyCatchBlock

Braces 關于條件分支的規則,如IfStmtsMustUseBraces

Code Size 關于代碼大小的規則,如方法的長度,參數的長度,屬性的個數等

Clone 克隆實作的規則,如是否有super.clone()

Controversial 一些有争議的規則,如UnnecessaryConstructor不必要的構造器

Coupling 對象連接配接有關的規則

Design 可以檢查有問題的設計,如SwitchStmtsShouldHaveDefault

Finalizers 使用finalizers時需遵循的規則,如FinalizeOnlyCallsSuperFinalize

Import Statements 和import有關的規則,如DuplicateImports重複import

J2EE 唯一規則UseProperClassLoader,class.getClassLoader()可能不正确,用

Thread.currentThread().getContextClassLoader() 代替

Javabeans 和javabean規範有關的規則,有BeanMembersShouldSerialize屬性必須

序列化和MissingSerialVersionUID缺少序列化ID

JUnit Tests 和JUnit測試有關的,如JUnitSpelling拼寫檢查等

Logging (Java) 檢查Logger的一些錯誤用法,如MoreThanOneLogger多個Logger

Logging (Jakarta) 使用Jakarta Logger的一些規則,有UseCorrectExceptionLogging

異常處理不當和ProperLogger是否正确定義Logger

Migrating JDK 版本移植的規則,如ReplaceVectorWithList用List代替Vector

Naming 和命名有關的規則,名稱太短或太長,命名的約定等

2.2參數詳情

● -dir/-d掃描目錄

● -format/-f報告格式,有xml、xslt、html、text,預設為text

● -rulesets/R使用的規則集

● -auxclasspath

● -uri/-u源檔案的資料庫uri,使用它就不需要提供-dir

● -filelist一個包含逗号分隔的路徑清單的檔案,使用它就不需要提供-dir

示例:

指令:E:\pmd-bin-6.4.0>bin\pmd.bat -filelist E:\team-goblin\demo1\list.txt -f html -R myRule.xml

結果:

●    -debug / -verbose / -D / -V 列印更詳細的日志

●    –help 顯示用法幫助資訊

●    -encoding / -e 字元集編碼,預設為utf-8

●    -threads / -t 設定PMD使用的線程數。預設值是“1”。将線程設定為“0”以禁用多線程處理。

●    -benchmark / -b 基準模式-完成後輸出基準測試報告

●    -stress / -S 進行壓力測試

●    –shortnames 報告中列印縮短的檔案名,隻有在檔案隻有一個目錄時是奏效

使用 –shortnames後:

●    –suppressmarker 指定一個字元串使得PMD忽略某行,預設為“NOPMD”。

示例1:

示例2:pmd.bat -d E:\team-goblin\demo1 -f html -RmyRule.xml -showsuppressed -suppressmarker allowint

●    – showsuppressesd 報告顯示被忽略的違規行為

示例:bin\pmd.bat -d E:\team-goblin\demo1 -f html –R myRule.xml-showsuppressesd>report.html

●    –minimumpriority/-min

規則最小優先級門檻值,預設為5,規則優先級低于它就不會被使用

pmd.bat-d E:\team-goblin\demo1 -f html -R myRule.xml -min 4

● –property/-P 為報告格式定義一個屬性

● –language/-l 指定pmd使用的語言

【對掃描結果沒有任何影響】

● - version 指定PMD使用的語言版本

● – failOnViolation {true|false} PMD預設會在發現違規情況時以狀态4退出。使用“-failOnViolation false”禁用此選項,以0退出并且隻寫報告。

Everything is fine, no violations found

1

Couldn't understand command line parameters or PMD exited with an exception

4

At least one violation has been detected

● -cache指定要使用的分析緩存檔案的位置。這可以大大提高分析性能,并被強烈推薦。

● –no-cache顯式禁用增量分析。這個開關關閉了使用增量分析的建議,并導緻-cache選項使用時無效

2.3 自定義規則

編寫pmd規則有兩種方法:

(1)用xpath,參考産生的AST樹寫xml

(2)用java code,需要深入了解pmd api,用于一些比較複雜的規則

2.3.1xpath自定義規則

使用PMD自帶的designer.bat工具可以快速生成一個xpath rule xml。

(1)打開designer界面工具,輸入源代碼,輸入XPath表達式,點選Go按鈕,确認右下方的結果輸出正确。

(2)點選左上方File->ExportXpath to rule

(3)在新的頁面輸入Rulename,Rule msg,Rule desc後,點選Create rule XML按鈕,檢視輸出的結果。

判斷非Integer的引用類型//Type/ReferenceType/ClassOrInterfaceType[@Image!="Integer"]

判斷使用Int的基本類型

//Type/PrimitiveType[@Image="int"]

3 擴充

3.1 cpd.bat 重複代碼檢測

cpd.bat --minimum-tokens 100 --filesE:\team-goblin

--minimum-tokens 大于該值則認為代碼重複

--files 掃描檔案路徑

SupportedLanguages

Apex

C#

C/C++

EcmaScript (JavaScript)

Fortran

Go

Groovy

Java

Jsp

Matlab

Objective-C

Perl

PHP

PL/SQL

Python

Ruby

Scala

Swift

Visualforce

Availableformats

text : Default format

xml

csv

csv_with_linecount_per_file

vs