綜述下關鍵點,代碼規範檢查基本原理可以基於AST語法樹來進行實現;AST結合Xpath可以方便進行相關規範規則的編寫;通過 PMD-Designer 能可視化的幫助我們實現 XPath 的相關代碼規範規則以及驗證相關規則;給出了一個例子... ...
一些基本概念
在開始獨立研發公司自己的代碼規範檢查規則之前,先介紹一些相關的基本概念。阿裡巴巴代碼規範很多規則其實都是基於開源框架PMD進行的研發。PMD用官方的話語介紹來說:PMD是一個源代碼分析器。它可以發現常見的編程缺陷,如未使用的變數、空catch塊、不必要的對象創建等。它支持多種語言。它可以用自定義規則進行擴展。它使用JavaCC和Antlr將源文件解析為抽象語法樹(AST),並對其運行規則以查找衝突。規則可以用Java編寫,也可以使用XPath查詢。開源代碼庫:https://github.com/pmd/pmd
這裡涉及到一個很關鍵的概念——AST 抽象語法樹(Abstract Syntax Tree)。AST運用場景其實非常多,日常我們研發過程中錯誤提示、代碼高亮、代碼格式化、代碼轉譯等等實現的基礎都基於AST。簡單說,會通過詞法分析和語法分析將代碼轉化成一種類似樹樣層次結構來進行描述,當然這種描述可以用XML格式。文字描述比較抽象,不妨看一個“Hello world”的具體AST語法樹(Java 1.8),這樣就很容易進行理解了。
另外一個概念XPath 是一門在XML 文檔中查找信息的語言。本身和代碼解析沒有關係,但當AST通過XML格式描述時,XPath能夠很好完成對相關節點進行查找。兩者的結合就能進行違規代碼的檢查,這就是XPath規則代碼規範檢查基本原理。此外,與其配套的PMD-Designer規則可視化工具也很好用。
例如阿裡巴巴代碼規範中 PackageNamingRule 就是非常典型的XPath規則。包名只能由小寫字母、數字來組成,具體的XPath:
private static final String XPATH = "//PackageDeclaration/Name"
+ "[not (matches(@Image, '^[a-z0-9]+(\\.[a-z][a-z0-9]*)*$'))]";
下麵先寫個規則的例子來感受下自定義規則具體的操作;從檢查代碼中System.out 類似的日誌輸出開始。
Example :檢查代碼中System.out 類似的日誌輸出。
步驟一,運用PMD-Designer 來輔助編寫具體XPath的檢查規則;這個工具也可以驗證各種代碼寫法下,規則是否都能起到很好的作用。最終XPath 具體規則如下:
//Name[starts-with(@Image, 'System.out.print') or starts-with(@Image, 'System.err.print')]
步驟二,新建一個具體的規則類,繼承AbstractXpathRule ;其中AbstractXpathRule 本身是繼承 PMD 中 XPathRule,主要擴展了多語言的設計。詳細如下:
package com.alibaba.p3c.pmd.lang.java.rule.emo;
...
import static net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery.XPATH_2_0;
public class VoidSystemPrintRule extends AbstractXpathRule {
private static final String XPATH =
"//Name[starts-with(@Image, 'System.out.print') or starts-with(@Image, 'System.err.print')]";
public VoidSystemPrintRule() {
setXPath(XPATH);
setVersion(XPATH_2_0);
}
@Override
public void addViolation(Object data, Node node, String arg) {
ViolationUtils.addViolationWithPrecisePosition(this, node, data,
I18nResources.getMessage("java.naming.VoidSystemPrintRule.violation.msg", node.getImage()));
}
}
步驟三:在messages.xml 和 messages_en.xml 分別添加檢查出錯後給出相關中英文提示。
<entry key="java.naming.VoidSystemPrintRule.violation.msg">
<![CDATA[程式中避免直接使用 System 對相關日誌信息輸出]]>
</entry>
——
<entry key="java.naming.VoidSystemPrintRule.violation.msg">
<![CDATA[Avoid using system print]]>
</entry>
步驟四:新建emo-common.xml 的規則集合,並將實現的規則配置進去。
<ruleset name="AlibabaJavaNaming" xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
<description>EmoJavaCommonRule</description>
<rule name="VoidSystemPrintRule"
language="java"
since="1.6"
message="java.naming.VoidSystemPrintRule.violation.msg"
class="com.alibaba.p3c.pmd.lang.java.rule.emo.VoidSystemPrintRule">
<priority>3</priority>
<example>
<![CDATA[
System.out.println(message);
]]>
</example>
</rule>
</ruleset>
步驟五:在ali-pmd.xml 中引入我們新加的規則集合 emo-common.xml。
<rule ref="rulesets/java/emo-common.xml"/>
最後運行下修改完的代碼程式,效果如下:
綜述下關鍵點,代碼規範檢查基本原理可以基於AST語法樹來進行實現;AST結合Xpath可以方便進行相關規範規則的編寫;通過 PMD-Designer 能可視化的幫助我們實現 XPath 的相關代碼規範規則以及驗證相關規則;給出了一個例子,基於阿裡開源代碼規範插件源碼,編寫適用自己公司的代碼規範的方式。
歡迎關註附上相關代碼github鏈接:https://github.com/ariesfly/emo-coding-guardian
如有遇到問題歡迎公眾號私信留言