一.CheckStyle是什么
CheckStyle 是一款幫助開發(fā)人員編寫出遵守編碼標準的Java代碼的開發(fā)工具.它的主要任務是執(zhí)行代碼檢查(這是一項使人覺得枯燥但是又極其重要的工作.).這使其成為執(zhí)行編碼標準的絕佳工具.
CheckStyle 可以檢測源碼中的很多問題(比如類設計問題,方法設計問題),同時它還具有檢測代碼布局和格式化問題的能力,如果你想了解全能CheckStyle到底能干嘛,那么這條鏈接可能就會你想要的.
Checkstyle 是高度可配置的,幾乎支持任何的編碼標準,這里提供一個示例,支持Sun Code Conventions, Google Java Style.
道理我都懂,沒圖說JB:
你可以在這里看到一個使用CheckStyle 和Maven生成修改建議的報告.
二.CheckStyle配置
CheckStyle使用XML來管理配置項,通過xml您可以指定哪些檢測模塊要運用到java源文件的代碼檢測中.
CheckStyle許多模塊都是TreeWalker FileSetCheck模塊的子模塊挖函。TreeWalker通過將每個Java源文件單獨轉(zhuǎn)換為抽象語法樹,然后將結(jié)果傳遞給每個子模塊,以供子模塊做進一步分析.
這種情況有點類似于網(wǎng)絡數(shù)據(jù)傳輸中,數(shù)據(jù)被逐層拆包解析的過程
Module
- 一個基本的配置文件被Checker模塊所外包.
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">
<module name="Checker">
....
</module>
2.CheckStyle是通過module的name屬性標識來加載類.這個name的寫法有一些講究.
.根據(jù)包限定名稱直接加載類(這種寫法適用于導入第三方檢測模塊)
<module name="com.puppycrawl.tools.checkstyle.TreeWalker"/>
.加載一個內(nèi)置類
<module name="AvoidStarImport"/>
.當內(nèi)部類中名稱以[Check]結(jié)尾時,可以簡寫,例如我要加載"com.puppycrawl.tools.checkstyle.checks.ConstantNameCheck "這個類
<module name="ConstantName"/>
Properties
你可以在 Property Types 了解更多的屬性配置信息
Module的Properties屬性控制Module如何執(zhí)行任務,一般來說,Properties都有一個默認值,如果默認值符合您的要求,那么完全沒必要去重新為它賦值.而當Properties的默認值無法滿足您的要求時,您可要在Module內(nèi)定義屬性元素.并為其重新賦值.
<!--MethodLength模塊中的max屬性指定方法或者構(gòu)造函數(shù)中允許的最大行數(shù).默認值是150,您可以通過以下方式修改它的值-->
<module name="MethodLength">
<property name="max" value="60"/>
</module>
模塊設置的屬性可以被子模塊所繼承
<!--以下配置片段中,tabWidth=4會作用于TreeWalker及其子模塊中-->
<module name="Checker">
<module name="JavadocPackage"/>
<module name="TreeWalker">
<property name="tabWidth" value="4"/>
<module name="AvoidStarImport"/>
<module name="ConstantName"/>
...
</module>
</module>
可以使用 ${property_name}表達式來指定module的屬性值.
<module name="Header">
<property name="headerFile" value="${checkstyle.header.file}"/>
</module>
property_name 是命令行屬性或ant Checkstyle任務屬性,如此,您可以使用屬性擴展來重新指定模塊屬性值挨约,而無需更改配置文檔腰吟。
property 提供了一個可選的默認屬性,當該值中的屬性無法解析時使用
<!--當無法獲取到${checkstyle.javadoc.severity}的屬性值時,severity=error-->
<module name="JavadocMethod">
<property name="severity"
value="${checkstyle.javadoc.severity}"
default="error"/>
</module>
當設置集中式配置文件(例如整個公司的一個文件)以降低配置維護成本時糕殉,此功能非常有幫助萍摊。 對默認情況下滿意的項目可以直接使用該配置文件著觉,但具有特殊需求的單個項目可以靈活調(diào)整幾個設置以滿足其需要,而無需復制和維護整個配置。
Checker
Checker(3.0添加) 是 CheckStyle的根目錄,同樣Checker也有內(nèi)置屬性,該屬性會直接被子Module所繼承.
name | 說明 | 類型 | 默認值 | 發(fā)布版本 |
---|---|---|---|---|
basedir | string | null | 3.0 | |
cacheFile | 存放已檢測為文件信息,防止重復檢測 | string | null | 6.16 |
localeCountry | 國家信息 | string:空字符串或大寫ISO 3166 2字國家代碼 | Java虛擬機的默認區(qū)域設置國家/地區(qū) | 3.0 |
localeLanguage | 本地語言代號 | string:空字符串或小寫的ISO 639代碼 | Java虛擬機的默認語言環(huán)境語言 | 3.0 |
charset | 文件字符編碼 | String | System property "file.encoding" | 5.0 |
fileExtensions | 文件擴展名 | String Set | null | 6.3 |
severity | 所有違規(guī)的默認嚴重性級別 | Severity | error | 3.1 |
haltOnException | 如果單個文件在驗證期間產(chǎn)生任何類型的異常妻熊,是否停止Checkstyle的執(zhí)行 | Boolean | true | 7.4 |
TreeWalker
name | description | type | default value | since |
---|---|---|---|---|
tabWidth | 標簽字符('\ t')的展開空間數(shù) 用于需要標簽寬度的消息和檢查夸浅,例如LineLength | Integer | 8 | 3.0 |
fileExtensions | 文件類型擴展名來標識Java文件。 通常只有在編譯之前對Java源代碼進行預處理并且原始文件沒有擴展名.java時扔役,才需要設置此屬性帆喇。 | String Set | java | 3.0 |
TreeWalker模塊為Java源文件創(chuàng)建一個語法樹,并在樹的節(jié)點遍歷期間調(diào)用其子模塊(稱為Checks).語法樹的每個節(jié)點都有一個令牌. 在遍歷期間訪問節(jié)點會觸發(fā)為其令牌配置的所有檢查亿胸。 例如坯钦,如果MethodLength已配置為TreeWalker的子模塊,則使用方法或構(gòu)造函數(shù)定義令牌訪問節(jié)點將觸發(fā)MethodLength以檢查節(jié)點代碼塊的行數(shù)侈玄。
一些檢查婉刀,如FileLength和LineLength,直接應用于源文件序仙,不涉及語法樹的令牌突颊。 其他Checks Module與觸發(fā)檢查的可配置的令牌集相關(guān)聯(lián)。 例如:
<module name="MethodLength"/>
MethodLength Module默認的token集合是{METHOD_DEF, CTOR_DEF}(方法定義,或者構(gòu)造函數(shù)定義),而當某個節(jié)點包含METHOD_DEF或者CTOR_DEF令牌,那么TreeWalker 就會調(diào)用MethodLength 執(zhí)行檢查.
您可以使用屬性令牌指定檢查的特定的令牌.令牌的值是表示Check的令牌的子集的列表潘悼,如下面的元素律秃,配置Check MethodLength僅檢查方法的行數(shù):
<module name="MethodLength">
<!--不再包含構(gòu)造函數(shù)-->
<property name="tokens" value="METHOD_DEF"/>
</module>
如果你要將不同的屬性令牌標記應用于同一個Checks Module中,請重寫Checks Module.例如下面這樣操作.
<module name="MethodLength">
<property name="tokens" value="METHOD_DEF"/>
</module>
<module name="MethodLength">
<property name="tokens" value="CTOR_DEF"/>
<property name="max" value="60"/>
</module>
以上代碼片段代表檢查方法的長度(無配置則默認是150行),構(gòu)造方法的長度為60行.
Severity(告警級別)
每一個Checks Module都有告警級別屬性,CheckStyle給予的默認屬性是Error級別.你可以向下面的代碼片段一樣,更改它的告警級別:
<module name="Translation">
<property name="severity" value="warning"/>
</module>
將類型轉(zhuǎn)換 告警級別調(diào)至warning級別.
Custom Messages(自定義消息)
從CheckStyle5.0開始,CheckStyle的Checks Module已經(jīng)被定義成可自定義輸出消息.這個功能在檢測消息需要引用編碼樣式文檔中的相應部分或默認消息對于開發(fā)人員來說是太難以理解的情況下非常有用.
<module name="MemberName">
<property name="format" value="^m[a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member ''{0}'' must start with a lowercase ''m'' (checked pattern ''{1}'')."/>
</module>
請注意,消息模式必須是一個有效的java.text.MessageFormat樣式模式挥等,因此請注意占位符定義外的花括號友绝。
每個檢查配置元素可以具有零個或多個消息元素。 每個檢查使用一個或多個不同的消息密鑰來記錄違規(guī)肝劲。 如果要自定義某個消息迁客,則需要在消息元素的key屬性中指定消息密鑰。
Filters(過濾器)
Checker模塊具有一組過濾器子模塊辞槐,用于過濾審核事件掷漱,包括Checks發(fā)出的錯誤消息。 過濾器可以接受或拒絕審核事件榄檬。 如果所有過濾器都接受審核事件卜范,則Checker會報告事件。 如果任何Filter拒絕事件鹿榜,則Checker不會報告事件海雪。 有關(guān)更多信息,請訪問過濾器頁面舱殿。
執(zhí)行前文件過濾器(什么鬼)
檢查器模塊具有“執(zhí)行前文件過濾器”子模塊奥裸,以過濾文件被該實用程序處理。 執(zhí)行前文件過濾器可以按其名稱接受或拒絕文件沪袭。 如果所有執(zhí)行文件過濾器都接受文件湾宙,則Checker將處理并驗證文件。 如果任何執(zhí)行前文件過濾器拒絕文件,則Checker會跳過該文件侠鳄,并且行為類似于它不存在埠啃。 有關(guān)更多信息,請訪問文件過濾器頁面伟恶。
AuditListeners(審核監(jiān)聽器)
除了文本或XML輸出的審核記錄之外碴开,Checker還可以擁有處理審核事件的自定義AuditListener。 為了使用自定義偵聽器博秫,為偵聽器及其屬性添加一個Checker子模塊叹螟。 例如,要配置Checker台盯,以便它使用自定義偵聽器VerboseListener將審核消息打印到名為“audit.txt”的文件中罢绽,請在配置文件中包含以下模塊:
<module name="com.mycompany.listeners.VerboseListener">
<property name="file" value="audit.txt"/>
</module>
Packages
Checkstyle根據(jù)模塊元素的名稱加載模塊類,并在搜索可加載類時自動將預先指定的包前綴附加到該名稱静盅。 默認情況下良价,Checkstyle應用包com.puppycrawl.tools.checkstyle,com.puppycrawl.tools.checkstyle.filters和com.puppycrawl.tools.checkstyle.checks以及com.puppycrawl.tools.checkstyle的任何子包蒿叠。
要指定要應用的其他包明垢,請創(chuàng)建名為checkstyle_packages.xml的XML文件,并將該文件提供到包含您的自定義檢查的.jar的根目錄中市咽。
請注意痊银,通過命令行選項或Ant Checkstyle任務的屬性提供包命名XML文檔的支持已經(jīng)在Checkstyle 5.0版本上刪除。
包名稱XML文檔指定包名稱列表施绎。 以下是軟件包名稱XML文檔的示例程序包com.puppycrawl.tools.checkstyle和com.puppycrawl.tools.checkstyle.checks:
<checkstyle-packages>
<package name="com.puppycrawl.tools.checkstyle">
<package name="checks"/>
</package>
</checkstyle-packages>
例如溯革,要讓Checkstyle能夠使用包com.mycompany.checks中的模塊,請創(chuàng)建下面的XML文件谷醉,并將該文件放入包含自定義檢查模塊的jar文件的根目錄下致稀。 該XML文件必須完全命名為checkstyle_packages.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE checkstyle-packages PUBLIC
"-//Puppy Crawl//DTD Package Names 1.0//EN"
"http://checkstyle.sourceforge.net/dtds/packages_1_0.dtd">
<checkstyle-packages>
<package name="com.mycompany.checks"/>
</checkstyle-packages>
現(xiàn)在你可以在配置文件中配置一個包com.mycompany.checks的模塊,比如說com.mycompany.checks.MethodLimitCheck俱尼,它有一個簡化的寫法:
<module name="MethodLimit"/>
XML Structure(CheckStyle 的xml語法結(jié)構(gòu))
配置XML文檔的以下DTD指定模塊及其屬性的層次結(jié)構(gòu):
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT module (module|property)*>
<!ATTLIST module name NMTOKEN #REQUIRED>
<!ELEMENT property EMPTY>
<!ATTLIST property
name NMTOKEN #REQUIRED
value CDATA #REQUIRED
>
Checkstyle在加載文檔時驗證配置XML文檔抖单。 要根據(jù)上述配置DTD進行驗證,請在配置XML文檔中包含以下文檔類型聲明:
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">
Checkstyle還嚴格執(zhí)行XML聲明的編碼屬性遇八。 如果Checkstyle拒絕配置文檔的編碼矛绘,請更正encoding屬性的值,或者完全刪除編碼屬性刃永。
有關(guān)配置XML文檔的完整示例货矮,請檢查檢查Sun編碼約定的文檔docs / sun_checks.xml。
這是一個包名稱XML文檔的DTD:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT checkstyle-packages (package)*>
<!ELEMENT package (package)*>
<!ATTLIST package name NMTOKEN #REQUIRED>
Checkstyle還會在加載文檔時驗證包名XML文檔揽碘。 要根據(jù)上述軟件包名稱DTD進行驗證次屠,請在軟件包名稱XML文檔中包含以下文檔類型聲明:
<!DOCTYPE checkstyle-packages PUBLIC
"-//Puppy Crawl//DTD Package Names 1.1//EN"
"http://checkstyle.sourceforge.net/dtds/packages_1_1.dtd">
這是一個抑制XML文檔的DTD:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT suppressions (suppress*)>
<!ELEMENT suppress EMPTY>
<!ATTLIST suppress files CDATA #REQUIRED
checks CDATA #IMPLIED
id CDATA #IMPLIED
lines CDATA #IMPLIED
columns CDATA #IMPLIED>
您可要在這里找到所有支持的Check Module類型.
========================================================================
Demo展示:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
<!--Create by fengwenhua 2017年11月2日13:32:57-->
<!--這是CheckStyle根目錄-->
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="warning"/>
<!--該節(jié)點可以把Java源文件的內(nèi)容解析成語法樹,并將語法樹內(nèi)容分發(fā)給子Module進行進一步的檢測-->
<module name="TreeWalker">
<!--檢查[標識符名稱]中的縮寫(連續(xù)大寫字母)的長度,它也允許強制駱駝命名雳刺。(需要父Module TreeWalker 支持)-->
<module name="AbbreviationAsWordInName">
<!--當變量定義或類定義時,該檢測有效-->
<property name="tokens" value="VARIABLE_DEF,CLASS_DEF"/>
<!--一般來說,靜態(tài)常量都是大寫 忽略該檢測-->
<property name="ignoreStatic" value="true"/>
<!--最多可以連續(xù)打印1個大寫字母,MyTest正確,MyTEst錯誤-->
<property name="allowedAbbreviationLength" value="0"/>
<!--必須跳過檢查的縮寫列表劫灶。縮寫列表應該用逗號隔開掖桦,不允許有空格本昏。-->
<property name="allowedAbbreviations" value="XML,URL"/>
</module>
<!--驗證抽象類的標識符-->
<module name="AbstractClassName">
<!--抽象類以Abstract開頭-->
<property name="format" value="^Abstract.+$"/>
<!--匹配名稱的類的抽象修飾符丟失是否需要告警:默認就是false,因此可以不寫-->
<property name="ignoreModifier" value="false"/>
</module>
<!--匿名內(nèi)部類最大長度值:太過龐大的匿名內(nèi)部類在后期維護會相當困難,因此需要保證讓其短小精悍-->
<module name="AnonInnerLength">
<property name="max" value="100"/>
</module>
<!--數(shù)組定義風格:C風格(String args[])還會Java風格(String[] args)-->
<module name="ArrayTypeStyle">
<property name="javaStyle" value="true"/>
</module>
<!--
內(nèi)聯(lián)條件很難閱讀,所以使用編碼標準禁止它(比如三目運算符)
<module name="AvoidInlineConditionals"/>
-->
<!--是否允許*號導包-->
<module name="AvoidStarImport">
<!--被允許*號導包-->
<property name="excludes" value="java.io,java.net,java.lang.Math"/>
<!--是否可以import java.util.*; 這樣導包-->
<property name="allowClassImports" value="false"/>
<!--是否可以import static org.junit.Assert.*;靜態(tài)導包-->
<property name="allowStaticMemberImports" value="true"/>
</module>
<!--檢測無效導包-->
<module name="UnusedImports"/>
<!--檢測是否有不必要的括號-->
<module name="UnnecessaryParentheses"/>
<!--接口名稱定義,以I開頭-->
<module name="TypeName">
<property name="format" value="^I_[a-zA-Z0-9]*$"/>
<property name="tokens" value="INTERFACE_DEF"/>
</module>
<!--檢測TODO-->
<module name="TodoComment">
<property name="format" value="TODO"/>
</module>
</module>
</module>
參考鏈接:
CheckStyle官網(wǎng)