在 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>
這樣,這條規則就可以使用了。