在 PMD 的使用过程中,可以用 Java 或 XPath 来开发代码规则。
本文讲述如何使用 Java 来开发。
AST 对应的 Java 类库
PMD 使用抽象语法树(AST)来分析代码。它本身已经创建了一系列的 Java 类库来操作不同的语法元素。
在使用 Java 开发规则时,我们主要就是利用这些类来分析代码,从而找出违反规则的情况。
比如:
- ASTAnnotation:对应的是注解,比如 @IsTest
- ASTBreakStatement:对应的是 break 语句
- ASTWhileLoopStatement:对应的是 while 循环
- ASTLiteralExpression:对应的是字符串赋值语句
实现步骤
- 建立新的 Java 类
- 重写 visit() 函数,在函数中分析代码,找到违反规则的部分
- 将规则注册到规则集文件中
在 GitHub 中可以参考现有规则的 Java 实现。
举例
规则:代码中不能出现 System.debug() 函数。
建立新的 Java 类
建立一个新的类,名叫 SystemDebugShouldBeAvoidedRule,并且扩展 AbstractApexRule 类。
import java.util.List;
import net.sourceforge.pmd.lang.apex.ast.*;
import net.sourceforge.pmd.lang.apex.rule.*;
public class SystemDebugShouldBeAvoidedRule extends AbstractApexRule {
}
重写 visit() 函数
在新的类中重写 visit() 函数。
因为规则检测的入口是函数,所以参数是 ASTMethod 类型。
AST 类库中定义了很多方法,比如 findDescendantsOfType() 可以得到某个代码块下面的所有特定类型的元素。
import java.util.List;
import net.sourceforge.pmd.lang.apex.ast.*;
import net.sourceforge.pmd.lang.apex.rule.*;
public class SystemDebugShouldBeAvoidedRule extends AbstractApexRule {
@Override
public Object visit(ASTMethod node, Object data) {
boolean hasSystemDebug = false;
// 得到所有的调用函数的代码
List<ASTMethodCallExpression> methodCallList = node.findDescendantsOfType(ASTMethodCallExpression.class);
for (ASTMethodCallExpression methodCall : methodCallList) {
// 得到函数名
String assertMethodName = methodCall.getFullMethodName();
// 和 "system.debug" 比较
if ("system.debug".equalsIgnoreCase(assertMethodName)) {
hasSystemDebug = true;
break;
}
}
if (hasSystemDebug) {
// addViolationWithMessage() 函数会生成警告
addViolationWithMessage(data, node, "''{0}'' method should not have System.Debug function.", new Object[] { node.getImage() });
}
// 返回 data,其中会包含警告信息
return data;
}
}
将规则注册到规则集文件中
每个规则集都是以 XML 形式出现的。我们将新的规则注册进去:
<rule name="SystemDebugShouldBeAvoided"
since="6.23.0"
language="apex"
message="System Debug should be avoided"
class="<Java类的路径>.SystemDebugShouldBeAvoidedRule">
<description>
System Debug should be avoided
</description>
<priority>4</priority> <!-- 优先级从 1 到 5,表示从最严重到最轻微的规则-->
<example>
<![CDATA[
public void doSomething() {
System.debug('test');
}
]]>
</example>
</rule>
这样,这条规则就可以使用了。