中 ?打造企業自己代碼規范IDEA插件

一些基本概念在開始獨立研發公司自己的代碼規范檢查規則之前,先介紹一些相關的基本概念 。阿里巴巴代碼規范很多規則其實都是基于開源框架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),這樣就很容易進行理解了 。

中 ?打造企業自己代碼規范IDEA插件

文章插圖
另外一個概念XPath 是一門在XML 文檔中查找信息的語言 。本身和代碼解析沒有關系 , 但當AST通過XML格式描述時 , XPath能夠很好完成對相關節點進行查找 。兩者的結合就能進行違規代碼的檢查 , 這就是XPath規則代碼規范檢查基本原理 。此外 , 與其配套的PMD-Designer規則可視化工具也很好用 。例如阿里巴巴代碼規范中 PackageNamingRule 就是非常典型的XPath規則 。包名只能由小寫字母、數字來組成,具體的XPath:
private static final String XPATH = "http://PackageDeclaration/Name"+ "[not (matches(@Image, '^[a-z0-9]+(\\.[a-z][a-z0-9]*)*$'))]";下面先寫個規則的例子來感受下自定義規則具體的操作;從檢查代碼中System.out 類似的日志輸出開始 。
Example :檢查代碼中System.out 類似的日志輸出 。【中 ?打造企業自己代碼規范IDEA插件】步驟一,運用PMD-Designer 來輔助編寫具體XPath的檢查規則;這個工具也可以驗證各種代碼寫法下,規則是否都能起到很好的作用 。最終XPath 具體規則如下:
//Name[starts-with(@Image, 'System.out.print') or starts-with(@Image, 'System.err.print')]
中 ?打造企業自己代碼規范IDEA插件

文章插圖
步驟二,新建一個具體的規則類,繼承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 =              "http://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>

推薦閱讀