CheckStyle使用手册

Checkstyle SourceForge 下的一个项目,如名所示,是检查 java 程序源代码编码风格的,是 java 程序员不可或缺的工具,用以检查自己的编码习惯是否符合公司的要求或 Sun 的约定。 Checkstyle 是目前最广泛使用的代码检查工具 , 功能强大,操作简单,可以和 Ant 结合使用,最重要的是其是 Open Source 的。提供了一个帮助 JAVA 开发人员遵守某些编码规范的工具。

 

CheckStyle 默认提供一些主要检查内容:
  · Javadoc 注释
  ·命名约定
  ·标题
  · Import 语句
  ·体积大小
  ·空白
  ·修饰符
  ·块
  ·代码问题
  ·类设计
  ·混合检查(包括一些有用的,非必须的 System.out printstackTrace

 

从上面可以看出, CheckStyle 提供的大部分功能都是对于代码规范的检查,而没有提供象 PMD Jalopy 那样的增强代码质量和修改代码的功能。但是,对于团队开发,尤其是强调代码规范的公司来说,它的功能已经足够强大。 CheckStyle 默认提供了对 Sun 编程规范的支持。通过编写配置文件,可以增加自己的检查规范。

 

CheckStyle 的配置文件是基于 XML 而非 Properties 文件。它提供了两种运行的方式: 命令行工具和 ANT 任务。另外 CheckStyle 目前有很多针对流行 IDE 的插件,例如 Eclipse IntelliJ IDEA JBuilder 等。

 

1、 Ant 配合使用

http://sourceforge.net/project/showfiles.php?group_id=29721 下载最新版本的 CheckStyle ,目前的版本是 4.3 。把解压后目录复制到项目的 lib 目录下,然后就可以和 Ant 配合使用了。

Ant 脚本中,首先定义 CheckStyle 的解压目录位置:

<path id= "checkstyle.path" >     

    <fileset dir= "${lib.home}/checkstyle-4.3" >

          <include name= "**/*.jar" />

    </fileset>

</path>

接着声明 CheckStyle 任务:

<taskdef resource= "checkstyletask.properties" classpathref= "checkstyle.path" />

然后建立 CheckStyle 任务:

<target name= "checkstyle" >

<!-- 指明 checkstyle 的分析所需的规则文件 -->

     <checkstyle config= "${lib.home}/checkstyle-4.3/sun_checks.xml"

             failureProperty= "checkstyle.failure"

             failOnViolation= "false" >

              <!-- 指明输出格式和文件名 -->

             <formatter type = "xml"   tofile = "d:/report.xml" />

<!— 指明要检查的文件 -->

             <fileset dir = "${src.home}" >

                 <include name = "**/*.java" />

              </fileset>

         </checkstyle>

<!-- xml 文件转换成 html 文件 -->

         <style in= "d:/report.xml"   out = "d:/report.html"  

style= "${lib.home}/checkstyle-4.3/contrib/checkstyle-noframes.xsl" />

</target>

最后运行 ant checkstyle 即可。

 

注: checkstyle 提供了缺省的 xslt ,用来进行 xml 的格式转换。它们都放在 contrib 目录中。 checkstyle 同样也提供了自定义的 check ,但与 PMD 相比,书写要复杂。详细情况请参见 checkstyle 的文档。

 

2、   Eclipse 插件

Eclipse 当中安装 CheckStyle 插件非常方便,可以参照以下五个步骤进行:

a.       Eclipse 当中分别打开一下菜单 Help->Software Updates->Find and Install

b.       选择 Search for new features to install 选项然后点击 Next

c.       新建一个 New Remote Site...

d.       输入名称(比如: CheckStyle Plug-in )和下面的 URL http://eclipse-cs.sourceforge.net/update

e.       开始安装

安装好 CheckStyle 以后,不符合 CheckStyle 编码规范的信息将会出现在“问题 (Problems) ”视图当中,可以点击问题视图的“过滤器( Filters )”配置显示内容;

 

 

选择“ Window > Preferences -> Checkstyle ”进入 CheckStyle 的配置页面。 CheckStyle 默认的 sun 规范检查文件是: sun_checks.xml CheckStyle 的配置文件的导入 / 导出就在配置页面右侧。我们也可以导出以后,经过修改量身定做自己的规范。比如我们已经按照规范做好了一个代码规范文件,并且取名为“我的软件”,那么我们可以把这个规范导入,在 location 中加入自定义的 xml 文件, Type 选择 External Configuration File ,名称填上:“我的软件”,然后填上相应的描述,然后点击 browse 按钮找到相应的配置文档,点击 ok 就可以了。这样 checkstyle 当中又多了一个叫做“我的软件”的规范。

 

 

 

CheckStyle 是一个非常复杂的代码风格检查过程:包括缩进,命名规范等,因此缺省是 Disable 的,启动针对一个项目的 CheckStyle 需要用右键点击项目,在弹出的菜单中选择“ Checkstyle >Check Code with Checkstyle ”。 这样,我们就能使用 CheckStyle 对文档进行规范了。下面这个例子是使用 CheckStyle 以后,在 eclipse 中对不符合规范的代码进行标注,这样我们就可以按照“我的软件 规范对代码进行约束了。下图当中左边的放大镜图标表示此行代码不符合规范,当鼠标悬停在上面的时候,会显示这行代码的问题所在。(图略)

 

3、   定制 CheckStyle

CheckStyle 的最新发布版本中,有一个对于 Sun Java 编码规范的配置文件信息。但是,其中有很多条目并不一定符合项目开发的需要。就算是对于很多优秀的开源项目,按照这个规范来进行检查,也会出现成千上万的错误。这就是为什么需要定制 CheckStyle 的原因。

CheckStyle 的执行基于 XML 配置文件,它的主要组成部分是:
  · Module :整个配置文件就是一棵 Module 树。根节点是 Checker Module
  · Properties :它来决定一个 Module 如何进行检查。每个 Module 都有一个默认值,如果不满足开发需求,可以设定其它的值。
  下面是一个示例:

module name="MethodLength"

property name="max" value="60"/
/module

它表示,如果方法或者构造函数的长度超过 60 行, CheckStyle 就会报错。而默认值是 150 行。一般情况下,与 IDE 集成在一起使用的时候,点击出错的条目,可以跳转到相应的代码。

对于所有的模块来书,如果有这个模块则说明检测这一项,没有则不检测这一项。所有的模块中,其 ROOT 必须为 Checker 。配置文件中某些元素的具体讲解如下

<? xml version ="1.0" encoding ="UTF-8" ?>

<! DOCTYPE module PUBLIC "-//Puppy Crawl//DTD CheckeConfiguration 1.2//EN"

"http://www.puppycrawl.com/dtds/configuration_1_2.dtd">

<! -- 对于所有的模块来说, 如果有这个模块则说明检测这一项, 没有则不检测这一项 -- >

<! -- 所有的模块中,ROOT 必须为Checker -- >

< module name ="Checker">

     <! -- 检验每个包是否存在package.html 文件-- >

     <! -- See http://checkstyle.sf.net/config_javadoc.html#PackageHtml -- >

     <! --

     <module name="PackageHtml"/>

     -- >

     <! -- 检验每个文件末尾是否有一个空行,UNIT 机器上是有的,CVS 上如果没有会有警告的-- >

     <! -- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -- >

     <! --

     <module name="NewlineAtEndOfFile"/>

     -- >

     <! -- Checks that property files contain the same keys. -- >

     <! -- See http://checkstyle.sf.net/config_misc.html#Translation -- >

     < module name ="Translation" />

     < module name ="TreeWalker">

         <! -- Checks for Javadoc comments. -- >

         <! -- See http://checkstyle.sf.net/config_javadoc.html -- >

         <! -- Checks Javadoc commentsefor method definitions.-- >

         < module name ="JavadocMethod">

              < property name ="scope" value ="public" />

              <! -- 是否允许错误的参数声明,true 为允许, 缺省为不允许 -- >

              < property name ="allowMissingParamTags" value ="true" />

              <! -- 是否允许错误的错误声明,true 为允许, 缺省为不允许 -- >

              < property name ="allowMissingThrowsTags" value ="true" />

              <! -- 是否允许错误的返回类型声明,true 为允许, 缺省为不允许 -- >

              < property name ="allowMissingReturnTag" value ="true" />

         </ module >

         <! --Checks Javadoc comments for class and interface definitions.-- >

         < module name ="JavadocType" />

         <! -- Checks that variables have Javadoc comments.-- >

         < module name ="JavadocVariable">

              < property name ="scope" value ="protected" />

         </ module >

         <! -- 检查Javadoc 的格式 -- >

         < module name ="JavadocStyle">

              < property name ="scope" value ="public" />

              <! -- Comment 的第一句的末尾是否要有一个句号,true 必须有,defaulttrue -- >

              < property name ="checkFirstSentence" value ="false" />

              <! -- 检查错误的HTML 脚本, 比如不匹配,true 检查,defaulttrue -- >

              < property name ="checkHtml" value ="true" />

         </ module >

         <! -- Checks for Naming Conventions. -- >

         <! -- See http://checkstyle.sf.net/config_naming.html -- >

         <! -- 确省必须以Abstract 开始或者以Factory 结束 -- >

         <! --

         <module name="AbstractClassName"/>

         -- >

         < module name ="ConstantName" />

         < module name ="LocalFinalVariableName" />

         < module name ="LocalVariableName" />

         < module name ="MemberName" />

         < module name ="MethodName" />

         < module name ="PackageName" />

         < module name ="ParameterName" />

         < module name ="StaticVariableName" />

         < module name ="TypeName" />

         <! -- Checks for Headers -- >

         <! -- See http://checkstyle.sf.net/config_header.html -- >

         <! -- 检查文件是否以指定文件开始, 这里最好是放一些版权信息和工程描述 -- >

         <! -- headerFile: 指定的文件 -- >

         <! -- ignoreLines: 忽略哪些行,"," 分隔 -- >

         <! --

         <module name="Header">

             <property name="headerFile" value="java.header"/>

             <property name="ignoreLines" value="2, 3, 4, 5"/>

         </module>

         -- >

         <! -- Following interprets the header file as regular expressions. -- >

         <! --

         <module name="RegexpHeader"/>

         -- >

         <! -- Checks for imports -- >

         <! -- See http://checkstyle.sf.net/config_import.html -- >

         <! -- 检查使用* 号的导入, 默认为全部类 -- >

         < module name ="AvoidStarImport" />

         <! -- 检查是否有非法的包, 确省检查sun.*; 对于某些包是不建议直接调用的 -- >

         < module name ="IllegalImport">

              < property name ="illegalPkgs" value ="sun.*" />

         </ module >

         <! -- 检查多于的导入, 如一个类导入了多次 -- >

         < module name ="RedundantImport" />

         <! -- 检查没有使用的导入 -- >

         < module name ="UnusedImports" />

         <! -- 导入排序 -- >

         <! -- groups: 分组, 哪些是一组的 -- >

         <! -- ordered: 同一个组内是否排序,true 排序, 确省为true -- >

         <! -- separated: 各个组之间是否需要用空行分隔, 确省为false -- >

         <! -- caseSensitive: 是否是大小写敏感的, 确省是 -- >

         <! --

         <module name="ImportOrder">

             <property name="groups" value="java,javax"/>

             <property name="ordered" value="true"/>

             <property name="separated"evalue="true"/>

             <property name="caseSensitive" value="true"/>

         </module>

         -- >

         <! -- Checks for Size Violations. -- >

         <! -- See http://checkstyle.sf.net/config_sizes.html -- >

         <! -- 检查方法内可执行语句的个数, 确省为30 -- >

         <! --

         <module name="ExecutableStatementCount">

             <property name="max" value="30"/>

         </module>

         -- >

         <! -- 文件的最大行数, 缺省为1500 -- >

         < module name ="FileLength">

              < property name ="max" value ="2000" />

         </ module >

         <! -- 每行的最大字符数, 缺省为80 -- >

         < module name ="LineLength">

              <! -- 忽略指定格式的行,* 号开始的, -- >

              <! --

              <property name="ignorePattern" value="^ ** *[^ ]+$"/>

              -- >

              < property name ="max" value ="120" />

         </ module >

         <! -- 方法的最大行数, 缺省为150 -- >

         < module name ="MethodLength">

              < property name ="max" value ="200" />

              <! -- 统计时是否包括空行和以// 开始的注释, 缺省为统计(true)-- >

              < property name ="countEmpty" value ="false" />

         </ module >

         <! -- 匿名类的最大行数, 缺省为20 -- >

         < module name ="AnonInnerLength">

              < property name ="max" value ="60" />

         </ module >

         <! -- 检查方法和构造子参数的最大个数, 缺省为7 -- >

         < module name ="ParameterNumber" />

         <! -- Checks for whitespace -- >

         <! -- See http://checkstyle.sf.net/config_whitespace.html -- >

         < module name ="EmptyForInitializerPad" />

         < module name ="EmptyForIteratorPad" />

         < module name ="MethodParamPad">

              < property name ="allowLineBreaks" value ="true" />

         </ module >

         < module name ="NoWhitespaceAfter" />

         < module name ="NoWhitespaceBefore" />

         < module name ="OperatorWrap" />

         < module name ="ParenPad" />

         < module name ="TypecastParenPad" />

         < module name ="TabCharacter" />

         < module name ="WhitespaceAfter" />

         < module name ="WhitespaceAround" />

         <! -- Modifier Checks -- >

         <! -- See http://checkstyle.sf.net/config_modifiers.html -- >

         <! -- 要求JLS suggestions -- >

         <! --

         <module name="ModifierOrder"/>

         -- >

         < module name ="RedundantModifier" />

         <! -- Checks for blocks. You know, those {}'s -- >

         <! -- See http://checkstyle.sf.net/config_blocks.html -- >

         <! -- 检查空块 -- >

         <! --

         <module name="EmptyBlock"/>

         -- >

         < module name ="LeftCurly" />

         <! -- 检查只有必须有{}, 确省为必须, 主要在if,else 时有这样的情况 -- >

         < module name ="NeedBraces" />

         <! -- 检查"}", 确省在同一行 -- >

         < module name ="RightCurly">

              < property name ="option" value ="alone" />

         </ module >

         <! -- 检查多余嵌套的{}, 请看文档, 不易说明 -- >

         < module name ="AvoidNestedBlocks" />

         <! -- Checks for common coding problems -- >

         <! -- See http://checkstyle.sf.net/config_coding.html -- >

         < module name ="AvoidInlineConditionals" />

         < module name ="CovariantEquals" />

         < module name ="DeclarationOrder" />

         < module name ="DefaultComesLast" />

         < module name ="DoubleCheckedLocking" />

         <! --

             <module name="EmptyStatement"/>

         -- >

         < module name ="EqualsHashCode" />

         <! -- 变量必须初始化为自己的类型, 如果给一个Object 类型的变量初始化为null 会提示 -- >

         <! --

         <module name="ExplicitInitialization"/>

         -- >

         < module name ="FallThrough" />

         <! --

         <module name="FinalLocalVariable"/>

         -- >

         < module name ="HiddenField">

              < property name ="ignoreConstructorParameter" value ="true" />

              < property name ="ignoreSetter" value ="true" />

         </ module >

         <! -- Exception, Throwable, RuntimeException 是不允许catch -- >

         <! --

         <module name="IllegalCatch"/>

         -- >

         < module name ="IllegalInstantiation" />

         <! -- 有一个bug, 比如i++ 居然都不认

         <module name="IllegalToken"/>

         -- >

         < module name ="IllegalTokenText" />

         < module name ="IllegalType" />

         < module name ="InnerAssignment" />

         <! -- 检查直接数

         <module name="MagicNumber"/>

         检查是否有构造子

         <module name="MissingCtor"/>

         -- >

         < module name ="MissingSwitchDefault" />

         < module name ="MultipleVariableDeclarations" />

         <! --

         <module name="JUnitTestCase"/>

         <module name="NestedIfDepth"">

             <property name="max" value="5"/>

         </module>

         <module name="NestedTryDepth"">

             <property name="max" value="5"/>

         </module>

         <module name="PackageDeclaration"/>

         <module name="ReturnCount"/>

         -- >

         <! -- 不能为参数付值 -- >

         <! --

         <module name="ParameterAssignment"/>

         -- >

         < module name ="RedundantThrows" />

         <! -- 不能理解的, 好像是bug

         <module name="RequireThis"/>

         -- >

         < module name ="SimplifyBooleanExpression" />

         < module name ="SimplifyBooleanReturn" />

         < module name ="StringLiteralEquality" />

         < module name ="SuperClone" />

         < module name ="SuperFinalize" />

         < module name ="UnnecessaryParentheses" />

         <! -- Checks for class design -- >

         <! -- See http://checkstyle.sf.net/config_design.html -- >

         <! -- 要求一个方法必须声明为Extension, 否则必声明为abstract, final or empty -- >

         <! --

         <module name="DesignForExtension"/>

         -- >

         <! -- 检查private 构造子是否声明为final, 这里有个问题,Java 中构造子是不能声明为final -- >

         <! --

         <module name="FinalClass"/>

         -- >

         <! -- 要求一定要有一个构造子 -- >

         <! --

         <module name="HideUtilityClassConstructor"/>

         -- >

         < module name ="InterfaceIsType" />

         <! -- 检查变量的可见性, 确省只允许static final public, 否则只能为private -- >

         < module name ="VisibilityModifier">

              < property name ="packageAllowed" value ="true" />

              < property name ="protectedAllowed" value ="true" />

         </ module >

         <! --

         <module name="MutableException"/>

         -- >

         <! -- 限制抛出声明的指定数量, 确省为1 -- >

         <! --

         <module name="ThrowsCount"/>

         -- >

         <! -- Miscellaneous other checks. -- >

         <! -- See http://checkstyle.sf.net/config_misc.html -- >

         <! -- 数组的声明是否允许Java 的类型, 确省为允许,Java 类型为String[] xx,C++ 的类型为String xx[]; -- >

         < module name ="ArrayTypeStyle" />

         <! --

         <module name="FinalParameters"/>

         -- >

         <! -- 一般性的代码问题, 不好的习惯等, 可以多 -- >

         <! -- 文件中使用了System.out.print-- >

         < module name ="GenericIllegalRegexp">

              < property name ="format" value ="System.out.print" />

              < property name ="message" value ="bad practice of use System.out.print" />

         </ module >

         < module name ="GenericIllegalRegexp">

              < property name ="format" value ="System.exit" />

              < property name ="message" value ="bad practice of use System.exit" />

         </ module >

         < module name ="GenericIllegalRegexp">

              < property name ="format" value ="printStackTrace" />

              < property name ="message" value ="bad practice of use printStackTrace" />

         </ module >

         <! -- 关于Task, 你可以声明自己的Task 标识 -- >

         < module name ="TodoComment">

              < property name ="format" value ="TODO" />

         </ module >

         <! -- 强迫// 注释必须如何, 入下要求只能有一行, 具体看文档 -- >

         <! --

         <module name="TrailingComment">

             <property name="format" value="^s*$"/>

         </module>

         -- >

         <! -- main 方法经常会在debug 时使用, 但发行版本的时候可能并不需要这个方法, 提示 -- >

         <! --

         <module name="UncommentedMain"/>

         -- >

         <! -- 当定义一个常量时, 希望使用大写的L 来代替小写的l, 原因是小写的l 和数字1 很象 -- >

         < module name ="UpperEll" />

         <! -- 检查正确的缩进, 这个更象是个人习惯 -- >

         <! --

         <module name="Indentation">

            <property name="braceAdjustment" value="0"/>

         </module>

         -- >

         <! -- Checks For Metrics -- >

         <! -- See http://checkstyle.sf.net/config_metrics.html -- >

         <! -- 检查嵌套复杂度 -- >

         < module name ="CyclomaticComplexity">

              < property name ="max" value ="12" />

         </ module >

     </ module >

</ module >

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值