内容
Checkstyle简介
Checkstyle是一个帮助程序员写出标准格式代码的开发辅助工具。使用它会让代码更加简洁、漂亮。
Checkstyle是高可配的并且支持多种代码风格。使用它可以帮你找出Class\Method设计中的问题,同时也可以帮你找出代码布局和格式上的问题。
下载
有两种方式下载:
https://sourceforge.net/projects/checkstyle/files/checkstyle/
使用Maven下载:
<dependency> <groupId>com.puppycrawl.tools</groupId> <artifactId>checkstyle</artifactId> <version>6.16.1</version> </dependency> |
Checkstyle的几种使用方式
Checkstyle有多种使用方式:
1) 与Ant结合使用
2) 通过CLI来使用
3) 作为Maven插件来使用
4) Hudson集成
下面就针对这几种方式分别说明:
1)与Ant结合使用
相关文档:
http://checkstyle.sourceforge.net/anttask.html
2)通过CLI上使用Checkstyle
http://checkstyle.sourceforge.net/cmdline.html
命令行使用方式:
java -D<property>=<value> \ com.puppycrawl.tools.checkstyle.Main \ -c <configurationFile> \ [-f <format>] [-p <propertiesFile>] [-o <file>] \ [-t | --tree] [-T | --treeWithComments] [-v] \ file... |
3)Checkstyle作为Eclipse插件使用
插件下载地址:
https://sourceforge.net/projects/eclipse-cs/files/latest/download
下载安装后,重启Eclipse。
在文件夹右键菜单中可以看到:
使用Check Code with Checkstyle就可以进行代码检查了。查检后会在代码中不合理的地址标出来。使用Clear Checkstyle就可以将这些标识去掉。
在Preferences下可以对checkstyle进行配置:Eclipse插件下默认使用的是google的checkstyle配置。
4) 通过maven插件使用
插件的基本配置是:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-checkstyle-plugin</artifactId> <version>2.17</version> </plugin> |
2.17版本的checkstyle插件使用了Checkstyle-6.11.2.jar,对JDK的要求是JDK7。
在jar包中内置了google、sun的checks.xml
插件包含3个goal,分别是:
·chechstyle :这是一个report goal。用于执行对代码分析检查。会生成一个分析检查的报告。
·checkstyle-aggregate:这是一个report goal。用于执行对代码分析检查,并将结果汇总,最后产生一个HTML报告。
·check这是一个build goal。用于对代码分析检查,并在console上输出检查结果。
例如:
Checkstyle 配置
Checkstyle如何对代码进行检查,全部都要依赖于它的配置文件,所以如何配置才能检查出代码中的不合格的地方,也不能让它过多的报一些不认为是错误的格式,这些就非常的重要了。所以需要对它的配置文件要非常的了解才可以。
配置文件的结构
Module是一个XML文件,必须遵守一定的格式:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd"> <module name=”Checker”> <module .../> <module .../> …. </module> |
这个配置文件在使用Checkstyle执行代码检查时会加载使用。Checkstyle在设计上分模块设计的。它的配置文件中,也是由一系列的module元素组成的,每个module都有一个name属性,用于对module进行区分。所以name是唯一标识。其中根元素的name属性值是Checker,是第一级。
<module/>的name属性其实一个类的名称。在配置name属性时,可以是类全名,也可以是类名。
可以为module指定相应的property。这些property都是有默认值的。Property的定义要通过为<module />元素指定子元素<property /> 来完成。<property />可以配置name,value那个attribute。例如:
<module name="MethodLength"> <property name="max" value="60"/> </module> |
此外,父module的property可以被子module继承。
Property值分类
之前说了可以为<module />指定<property />,因为每种<module />的设计是不一样的,所以它的不同的<property/>的值可以不同类型的。根据属性值的不同,可以将<property>的值类型分为下列几类:
·Integer :属性是一个整数
例如:<property name=”name1” value=”3”/>
·String:属性是一个字符串
例如:<property name="severity" value="warning"/>
·Boolean:属性是一个布尔值
它的值如果是:yes,true,on时,表示为true;反之no,false,off表示false。
·StringSet:属性值是一个字符串集合
在设置值时,用,分隔。例如:
<property name="tokens" value="DIV_ASSIGN,PLUS_ASSIGN"/> |
也可以用下面的替换:
<property name="tokens" value="DIV_ASSIGN"/> <property name="tokens" value="PLUS_ASSIGN"/> |
·IntSet:属性值是一个整数集合
在设置值时,用,分隔。例如:
<property name="tokens" value="42,666"/> |
也可以用下面的替换:
<property name="tokens" value="42"/> <property name="tokens" value="666"/> |
·Regexp:值是一个正则表达式
正则表达式的取值,可以参考java.util.Pattern的javadoc。
·ParenPad:代码与()的内间距
有两个值:
nospace 表示没有内间距。例如: method(a, b)
space:表示有内间距。例如:method( a, b )
·WrapOp:换行处的操作符位置
Option |
Definition |
nl |
The token must be on a new line. For example: someVariable = aBigVariableNameToMakeThings + "this may work" + lookVeryInteresting; |
eol |
The token must be at the end of the line. For example: someVariable = aBigVariableNameToMakeThings + "this may work" + lookVeryInteresting; |
·Block:对代码块的要求
|
·Lcurly :左花括号的位置
Option |
Definition |
eol |
The brace must always be on the end of the line. For example: if (condition) { ... |
nl |
The brace must always be on a new line. For example: if (condition) { ... |
nlow |
If the brace will fit on the first line of the statement, then apply eol rule. Otherwise apply the nl rule. nlow is a mnemonic for "new line on wrap". For the example above Checkstyle will enforce: if (condition) { ... But for a statement spanning multiple lines, Checkstyle will enforce: if (condition1 && condition2 && condition3 && condition4) { ... |
·Rcurly:右花括号的位置。
same |
The brace should be on the same line as the next part of a multi-block statement (one that directly contains multiple blocks: if/else-if/else or try/catch/finally). Examples: // try-catch-finally blocks try { ... } catch (Exception ex) { // this is OK ... } finally { // this is OK ... } try { ... } // this is NOT OK, not on the same line as the next part of a multi-block statement catch (Exception ex) { ... } // this is NOT OK, not on the same line as the next part of a multi-block statement finally { ... } |
alone |
The brace must be alone on the line. For example: try { ... } finally { ... } |
alone_or_singleline |
The brace must be alone on the line, yet single-line format of block is allowed. For example: // Brace is alone on the line try { ... } finally { ... } // Single-line format of block public long getId() { return id; } |
·Serverity 检查结果级别控制
可取值有:ignore、info、warning、error。
Ignore表示忽略,即不会被report。
·ImportOrder import语句的顺序
Option |
Definition |
top |
All static imports are at the top. For example: import static a.b.C.*; import static x.y.Z.*; import a.b.D; import x.y.Z; |
above |
All static imports are above the local group. For example: import static a.b.C.*; import a.b.D; import static x.y.Z.*; import x.y.Z; |
inflow |
All static imports are processed like non static imports. For example: import static a.b.C.*; import a.b.D; import x.y.Z; import static x.y.Z.*; |
under |
All static imports are under the local group. For example: import a.b.D; import static a.b.C.*; import x.y.Z; import static x.y.Z.*; |
bottom |
All static imports are at the bottom. For example: import a.b.D; import x.y.Z; import static a.b.C.*; import static x.y.Z.*; |
·AnnotationStyle 注解元素的风格
可能取值:
Option |
Definition |
expanded |
The expanded version is sometimes referred to as "named parameters" in other languages. Example: @SuppressWarnings(value={"unchecked","unused",}) |
compact |
This style can only be used when there is an element called 'value' which is either the sole element or all other elements have default values. Examples: @SuppressWarnings({"unchecked","unused",}) and: @SuppressWarnings("unchecked") |
compact_no_array |
It is similar to the compact style but single value arrays are flagged. With annotations a single value array does not need to be placed in an array initializer. This style can only be used when there is an element called 'value' which is either the sole element or all other elements have default values. Example: @SuppressWarnings("unchecked") |
ignore |
Anything goes. |
注解中的括号:
Option |
Definition |
always |
Example: @Deprecated() |
never |
Example: @Deprecated |
ignore |
Anything goes. |
注解中的逗号:
Option |
Definition |
always |
Example: @SuppressWarnings(value={"unchecked","unused",}) |
never |
Example: @SuppressWarnings(value={"unchecked","unused"}) |
ignore |
Anything goes. |
Module分类
二级元素所代表的那些modules,主要分为三类:
·FileSetChecks 这些modules用于对file进行检查,发现问题后会报出错误消息。
·Filters 这些模块用于过滤审核事件和错误消息。
·AuditListeners 报告可接收的事件。
示例:
<module name="Checker"> <module name="JavadocPackage"/> <module name="TreeWalker"> <module name="AvoidStarImport"/> <module name="ConstantName"/> <module name="EmptyBlock"/> </module> </module> |
在这个典型的配置文件中,根moudle Checker 有2个FileSetChecker类别的module: JavadocPackage, TreeWalker。
其中JavadocPackage是要求指定的java package下必须得有package-info.java文件。通常这是没有必要的,所以这个规则一般不会使用。
而ThreeWalker下面有三个module,这三个module的作用是:
·AvoidStarImport import语句中不能出现.*
·ConstantName 常量名称检查
·EmptyBlock 检查是否有空的代码块。
Checker的属性
name |
description |
type |
default value |
basedir |
base directory name; stripped off in messages about files |
null |
|
cacheFile |
caches information about files that have checked OK; used to avoid repeated checks of the same files |
null (no cache file) |
|
localeCountry |
locale country for messages |
string: either the empty string or an uppercase ISO 3166 2-letter code |
default locale country for the Java Virtual Machine |
localeLanguage |
locale language for messages |
string: either the empty string or a lowercase ISO 639 code |
default locale language for the Java Virtual Machine |
charset |
name of the file charset |
System property "file.encoding" |
|
fileExtensions |
file extensions that are accepted |
<module name="Checker"> <property name="basedir" value="src/checkstyle"/> <property name="cacheFile" value="target/cachefile"/> <property name="localeCountry" value="DE"/> <property name="localeLanguage" value="de"/> <property name="charset" value="UTF-8"/> <module name="JavadocPackage"/> <module name="TreeWalker"> ... </module> </module> |
Serverity属性
每个checker都会有一个serverity属性。用于指定当代码违反相关module指定的规则时,给出哪种级别的错误。默认值是error,通常我们会将其改为warning。
例如:
<module name="Checker"> <property name="severity" value="warning"/> <module name="JavadocPackage"/> </module> |
Message 自定义消息
之前已经说了,当检查到不符合规则时,有错误消息的。所以Checkstyle为每一种检查都指定了默认的消息。有时我们希望使用的是自定义的消息,Checkstyle也提供了为种功能。
Message的自定义可以通过在每个checker module下指定<message>属性元素来完成。例如:
<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> |
TreeWalker
FileSetChecker moudle中的许多module都是TreeWalker module的子模块。
TreeWalker的工作原理是:将每个java source 文件转换成一个抽象的语法树,然后使用TreeWalker下的子modules轮流对这个语法树进行检查。
但是TreeWalker下也有一些checker module是不会调用语法树的。例如FileLength,LineLength。
name |
description |
type |
default value |
tabWidth |
number of expanded spaces for a tab character ('\t'); used in messages and Checks that require a tab width, such as LineLength |
8 |
|
fileExtensions |
file type extension to identify Java files. Setting this property is typically only required if your Java source code is preprocessed before compilation and the original files do not have the extension .java |
java |
<module name="Checker"> <module name="TreeWalker"> <property name="tabWidth" value="4"/> <property name="fileExtensions" value="java"/> ... </module> </module> |
Filters
每个Filter都会有一个Filters集合,用于对Check的审计事件(也可以说是检查不合格事件)进行过滤。如果filter接受了这个事件,应会报告出来,如果不接受这个事件,就不会报出来。Filter的配置是在每个check module下的子module。
·ServerityMatchFilter
根据每个check module的Serverity属性来判断是否接受。
name |
description |
type |
default value |
severity |
the severity level of this filter |
error |
|
acceptOnMatch |
If acceptOnMatch is true, then the filter accepts an audit event if and only if there is a match between the event's severity level and property severity. If acceptOnMatch is false, then the filter accepts an audit event if and only if there is not a match between the event's severity level and property severity. |
true |
默认情况下,当filter中指定的serverity与checker的serverity匹配(值相同)时,接收这个检查结果。
例如:
<module name="SeverityMatchFilter"> <property name="severity" value="warning"/> <property name="acceptOnMatch" value="true"/> </module> |
这个例子就是,当出现warning时,就报告敬告信息。
name |
description |
type |
default value |
offCommentFormat |
comment pattern to trigger filter to begin suppression |
CHECKSTYLE\:OFF |
|
onCommentFormat |
comment pattern to trigger filter to end suppression |
CHECKSTYLE\:ON |
|
checkFormat |
check pattern to suppress |
.* (all checks) |
|
messageFormat |
message pattern to suppress |
none |
|
checkCPP |
whether to check C++ style comments (//) |
true |
|
checkC |
whether to check C style comments (/* ... */) |
true |
Checker分类说明
可以把Checker分为下面几个类别:
·Annotations
·Block Checks
·Coding
·Headers
·Imports
·Javadoc Comments
·Metrics
·Miscellaneous
·Modifiers
·Naming
·Regexp
·Size Violations
·Whitespace
具体内容参考:http://checkstyle.sourceforge.net/checks.html