PMD 源码阅读(1)— 简介与使用

这段时间在做代码分析相关的工作,所以想要了解一下相关工具的原理。PMD 是一个 Java 静态代码分析工具,主要包括重复代码检测和代码规则检查两个部分。

PMD 简介

PMD 官网 http://pmd.github.io
GitHub https://github.com/pmd/pmd

1. 主要功能

  • 通过其内置的编码规则对 代码进行静态检查,主要包括对潜在的 bug、未使用的代码、重复的代码、循环体创建新对象等问题的检验。支持的语言包括 Java 、JavaScript 、PLSQL 、 XML 、XSL 等。
  • 支持开发人员对代码检查规范进行自定义配置。
  • 发现重复的代码(CPD , the copy-paste-detector),支持的语言包括 Java 、C 、C++ 、C# 、Groovy 、PHP 、Ruby 、Fortran 、 JavaScript 、PLSQL 、Ruby 、Scala 、Objective C 、Matlab 、Python 、Go 、Swift 等。

2. 内置编程规范

  • 可能的 Bugs:检查潜在代码错误,如空 try/catch/finally/switch 语句
  • 未使用代码(Dead code):检查未使用的变量、参数、方法
  • 复杂的表达式:检查不必要的 if 语句,可被 while 替代的 for 循环
  • 重复的代码:检查重复的代码
  • 循环体创建新对象:检查在循环体内实例化新对象
  • 资源关闭:检查 Connect 、Result 、Statement 等资源使用之后是否被关闭掉

     官方文档中的 Rule Set 对这些规则进行了分类,提供了更详细的说明。

使用 PMD

1. 目录结构

从 PMD 官网上下载 Release 版本(本文使用的版本是 5.5.2 ),解压后的目录结构如下:

  • 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. 基本使用

图形界面
cpdgui.bat 、designer.bat 等工具带有界面,打开就知道怎么用了。

命令行
官网上有详细的使用说明: Command line usage

例: pmd -d d:/code/Example.java -f xml -R rulesets/java/MyRuleSet.xml

输出:

CMD_Output.png

3. 自定义规则

除了使用 PMD 内置的规则外,我们还可以自己编写规则,让 PMD 按照自定义的规则对代码进行检查。

例:我们自定义一个规则,规定 While 循环必须使用括号。

我们可以使用 Java 代码XPath 查询 这两种方式自定义规则。

Java 代码实现

  1. 在官网上下载 PMD 源码包并解压,解压后目录为 pmd-src-5.5.2
  2. 编写 WhileLoopsMustUseBracesRule.java 文件,并放到 pmd-src-5.5.2\pmd-java\src\main\java\net\sourceforge\pmd\lang\java\rule 目录下。

Rule_MyJavaRule.png

  1. 编写 MyRuleSet.xml 文件,并放到 pmd-src-5.5.2\pmd-java\src\main\resources\rulesets\java 目录下。

Rule_MyRuleSet.png

  1. 在 pmd-src-5.5.2\pmd-java 目录下执行 mvn clean package -Dmaven.test.skip=true 以重新打包,并用新的 pmd-java-5.5.2.jar 替换 pmd-bin-5.5.2\lib 下的原有 jar 包。

执行命令 pmd -d d:/code/Example.java -f xml -R rulesets/java/MyRuleSet.xml 以使用该规则检查代码。

XPath 查询实现

XPath 表达式 //WhileStatement[not(Statement/Block)] 可以匹配抽象语法树中所有不存在 Statement/Block 子结构的 WhileStatement 节点。

编写 MyRuleSet.xml,将其放到放到 pmd-bin-5.5.2\lib\pmd-java-5.5.2.jar 中的 rulesets\java 目录下。

Rule_XPath.png

执行命令 pmd -d d:/code/Example.java -f xml -R rulesets/java/MyRuleSet.xml 以使用该规则检查代码。

评论

后继续评论需要管理员审核后可见

暂无评论,来发表第一条评论吧