要想按照自己的需求,定义Checkstyle配置文件,需要先了解Checkstyle配置文件的构成。在《代码规范工具-Checkstyle使用手册》一文中,我提及到两个Checkstyle提供的配置文件sun_checks.xml和sun_checks_eclipse.xml,那么现在下看下这两个文件的构成吧。sun_checks.xml和sun_checks_eclipse.xml所在的路径为:将Checkstyle安装包解压,在解压目录下,进入plugins, plugins目录下面有一个net.sf.eclipsecs.core_5.5.0.201111092104安装包,将该安装包解压,大家就可以看到sun_checks.xml和sun_checks_eclipse.xml这两个配置文件了。打开这两个配置文件后,我们大概可以看到:他们其实结构上几乎是一模一样的,因为sun_checks_eclipse.xml相当于sun_checks.xml的更加严格的规范限定版本,因此,我们只需要看sun_checks.xml文件即可。
1 Checkstyle的检查原理
sun_checks.xml是由多个module节点构成,因此可以发现:Checkstyle配置是通过指定modules来应用到java文件的。modules是树状结构,以一个名为Checker的module作为root节点,一般的checker都会包括TreeWalker子module。在xml配置文件中通过module的name属性来区分module,module的Properties可以控制如何去执行这个module,每个property都有一个默认值,所有的check都有一个severity属性,用它来指定check的level。
TreeWalker为每个java文件创建一个语法树,在节点之间调用submodules的Checks。
2 standard checks中的一些具体用法
2.1 Javadoc Comments
l JavadocPackage
检查每个java package中是否有java注释文件,默认是允许一个package-info.java,也可以通过allowLegacy属性配置允许package.html。
l JavadocType
检查类和接口的javadoc。默认不检查author 和version tags。
l JavadocMethod
检查方法和构造函数的javadoc。默认不检查未使用的异常抛出。
l JavadocVariable
检查变量的javadoc。
l JavadocStyle
检查javadoc的格式。比如:javadoc的第一行是否以句号结束,javadoc除了tags外是否有description,检查javadoc中的html格式。
l WriteTag
输出javadoc中的tag。
2.2 Naming Conventions
l AbstractClassName
检查抽象类名。
l ClassTypeParameterName
检查类的Parameter名。
l ConstantName
检查常量名。
l LocalFinalVariableName
检查局部的final类型变量名,包括catch的参数。
l LocalVarableName
检查局部的非final类型的变量名,包括catch的参数。
l MemberName
检查非静态变量。
l MethodName
检查方法名。
l MethodTypeParameterName
检查方法的参数名。
l PackageName
检查包名。
l ParameterName
检查参数名。
l StaticVariableName
检查静态的,非final类型的变量名。
l TypeName
检查类名和接口名。
2.3 Imports
l AvoidStarImport
检查是否有使用*进行import。
l AvoidStaticImport
检查是否有静态import。比如是否导入了java.lang包中的内容。
l IllegalImport
检查是否import了违法的包。默认拒绝import所有sun.*包。
l RedundanImport
检查是否有重复的import。
l UnusedImports
检查是否有未使用的import。
l ImportOrder
检查import的分组和顺序。
l ImportControl
控制可import的包。在一个较大的project可限制使用过多的第三方包,通过一个依照http://www.puppycrawl.com/dtds/import_control_1_0.dtd的xml文件来指定。
2.4 Size Violations
l ExecutableStatementCount
限制可执行代码片段的长度。默认为30。
l FileLength
检查java文件的长度。默认为2000。
l LineLength
检查代码行的长度。默认为80。
l MethodLength
检查方法和构造函数的长度。默认为150。
l AnonInnerLength
检查匿名内部类的长度。默认为20。
l ParameterNumber
检查方法和构造函数的参数个数。默认为7。
2.5 Whitespace
l GenericWhitespace
检查<和>周围的空白。
l EmptyForInitializerPad
检查空的初始化位置的空白。比如for循环中的初始化。
l EmptyForIteratorPad
检查空的迭代位置的空白。
l MethodParamPad
检查方法签名之前的空白。
l NoWhitespaceAfter
检查分隔符后的空白。
l NoWhitespaceBefore
检查分隔符前的空白。
l OperatorWrap
检查操作符的空白规则。
l ParenPad
检查圆括号的空白规则。
l TypecaseParenPad
检查强制转型的圆括号的空白规则。
l TabCharacter
检查是否有Tab字符(’"t’)。
l WhitespaceAfter
检查分隔符是否在空白之后。
l WhitespaceAround
检查分隔符周围是否有空白。
2.6 ModifierOrder
l ModifierOrder
检查修饰符的顺序是否遵照java语言规范。
l RedundantModifier
检查接口和annotation中是否有重复的修饰符。
2.7 Block Checks
l EmptyBlock
检查空的代码块。
l LeftCurly
检查’{’和左边的代码块是否在同一行。
l NeedBraces
检查是否需要大括号。主要是在if,else时的情况。
l RightCurly
检查’}’。
l AvoidNestedBlocks
检查不需要的嵌套’{}’。
2.8 Coding
l ArrayTrailingComma
检查数组初始化是否以逗号结束。
l AvoidInlineConditionals
检查inline的条件操作。
l CovariantEquals
检查类是否覆盖了equals(java.lang.Object)。
l DoubleCheckedLocking
检查DCL的问题。
l EmptyStatement
检查空的代码段。
l EqualsAvoidNull
检查一个可能为null的字符串是否在equals()比较的左边。
l EqualsHashCode
检查类是否覆盖了equals()和hashCode()。
l FinalLocalVariable
检查未改变过的局部变量是否声明为final。
l HiddenField
检查局部变量或参数是否隐藏了类中的变量。
l IllegalInstantiation
检查是否使用工厂方法实例化。
l IllegalToken
检查非法的分隔符。
l IllegalTokenText
检查非法的分隔符的下个字符。
l InnerAssignment
检查子表达式中是否有赋值操作。
l MagicNumber
检查是否有“magic numbers”。
l MissingSwitchDefault
检查switch语句是否有default的clause。
l ModifiedControlVariable
检查循环控制的变量是否在代码块中被修改。
l RedundantThrows
检查是否有被重复抛出的异常。
l SimplifyBooleanExpression
检查是否有过度复杂的布尔表达式。
l SimplifyBooleanReturn
检查是否有过于复杂的布尔返回代码段。
l StringLiteralEquality
检查字符串是否有用= =或!=进行操作。
l NestedIfDepth
检查嵌套的层次深度。
l NestedTryDepth
检查try的层次深度。
l NoClone
检查是否覆盖了clone()。
l NoFinalizer
检查是否有定义finalize()。
l SuperClone
检查覆盖的clone()是否有调用super.clone()。
l SuperFinalize
检查覆盖的finalize()是否有调用super.finalize()。
l IllegalCatch
检查是否catch了不能接受的错误。
l IllegalThrows
检查是否抛出了未声明的异常。
l PackageDeclaration
检查类中是否有声明package。
l JUnitTestCase
确保setUp(), tearDown()方法签名的正确性。
l ReturnCount
限制return代码段的数量。
l IllegalType
检查未使用过的类。
l DeclarationOrder
检查类和接口中的声明顺序。
l ParameterAssignment
检查不允许的参数赋值。
l ExplicitInitialization
检查类和对象成员是否初始化为默认值。
l DefaultComesLast
检查default的clause是否在switch代码段的最后。
l MissingCtor
检查类依赖。
l FallThrough
检查switch代码的case中是否缺少break,return,throw和continue。
l MultipleStringLiterals
检查一个文件中是否有多次出现的字符串。
l MultipleVariableDeclarations
检查代码段和代码行中是否有多次变量声明。
l RequireThis
检查代码中是否有“this.”。
l UnnecessaryParentheses
检查是否有使用不需要的圆括号。
Class Design
l VisibilityModifier
检查类成员的可见度。
l FinalClass
检查只有private构造函数的类是否声明为final。
l InterfaceIsType
检查接口是否仅定义类型。
l HideUtilityClassConstructor
检查工具类是否有putblic的构造器。
l DesignForExension
检查类是否为扩展设计。
l MutableException
确保异常是不可变的。
l ThrowsCount
限制抛出异常的数量。
2.9 Duplicate Code
l StrictDuplicateCode
严格检查重复代码。
2.10 Miscellaneous
l GenericIllegalRegexp
正则表达式的模式检查。
l NewlineAtEndOfFile
检查文件是否以一个空行结束。
l TodoComment
检查TODO:注释。
l Translation
检查property文件中是否有相同的key。
l UncommentedMain
检查是否有未注释的main方法。
l UpperEll
检查long型约束是否有大写的“L”。
l ArrayTypeStyle
检查数组类型定义的样式。
l FinalParameters
检查方法名、构造函数、catch块的参数是否是final的。
l Indentation
检查代码中正确的缩进。
l TrailingComment
确保是否要代码行注释。
l RequiredRegexp
确保一个指定的正则表达式的规则已经存在代码中。
关于上述这么多检查项,大家可以参考Checkstyle的官网http://checkstyle.sourceforge.net/,官网上对于每一检查项及其配置信息都讲解得很详细。
3 定制自己的配置文件
在了解了Checkstyle提供的N多检查项以后,我们可以依据sun_checks.xml作为模板来定制复合项目需要的检查项。
我个人使用Checkstyle默认检查项后的感受是,觉得规范过于严格,一般的项目中很少花较长的时间和较多的精力去完善每一个编程缺陷的。因此,结合项目组的编码规范要求,去定制检查项是比较合理的解决方案。在此,不再一一叙述如何定制,建议大家在依据编码规范定制时,对照官网上的检查项及其配置信息,便能完成此工作。
4 启用定制的配置文件
以我定制的配置文件checkstyle_test.xml为例。
进入windows菜单,选择preference, Checkstyle一项,
在Global Check Configurattions中单击New,选中External Configuration File一项,也可以选择Internal 一项吧,貌似Internal 就是属于集成、嵌入到Checkstyle内部的意思吧。
给要导入的配置文件命个名,如Checkstyle_test,单击Import,选择定制好的配置文件导入。
导入好后,我们将该文件设置为默认的检查文件,如下图所示,点击Set as Default:至此,我们就可以使用自定制的配置文件检查代码了。