这里借用了一下善用佳软网站的名头,个人很喜欢这个网站,里面有很多小巧而实用的软件。之所以接触CheckStyle,是因为另一个项目组请我帮忙规范一下代码格式。他们在做一个核心版本,希望开一个好头,格式什么的都统一起来。为此我做了一番调研,看了几个文档。

Sun的 Code Conventions for the Java TM Programming Language

http://www.oracle.com/technetwork/java/codeconvtoc-136057.html

Patrick Thompson写的 The Elements of Java? Style

根据这两个文档,再结合公司实际情况修改了下,给了份文档过去,以为这就完事了。岂料对方老大告诉我,代码已经写了大半了,新的代码会按规范写,旧的能不能再想办法都统一起来。╮(╯▽╰)╭,难道让我一行行代码给你看啊?好人做到底。又研究了一番,总算了发现了CheckStyle这个好东东。

安装就不废话了,http://eclipse-cs.sourceforge.net/downloads.html

p_w_picpath

安装完后,用Sun Checks(Eclipse)配置文件一检查,我的个天啊,几千个。看来得放宽限制了。

先把Sun Checks(Eclipse)导出一份,名字为DataExchange(Eclipse)。再来以DataExchange(Eclipse)为基础新配一个。

p_w_picpath

接下来就是修改配置了。两种方式,一种是通过插件直接改,另外一种就是直接改XML配置文件。以下是原始配置。咱先来看配置文件吧。

<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
    "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
    "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">

<!--

  Checkstyle configuration that checks the sun coding conventions from:

    - the Java Language Specification at
http://java.sun.com/docs/books/jls/second_edition/html/index.html

    - the Sun Code Conventions at http://java.sun.com/docs/codeconv/

    - the Javadoc guidelines at
http://java.sun.com/j2se/javadoc/writingdoccomments/index.html

    - the JDK Api documentation http://java.sun.com/j2se/docs/api/index.html

    - some best practices

  Checkstyle is very configurable. Be sure to read the documentation at
http://checkstyle.sf.net (or in your downloaded distribution).

  Most Checks are configurable, be sure to consult the documentation.

  To completely disable a check, just comment it out or delete it from the file.

  Finally, it is worth reading the documentation.

-->

<module name="Checker">
    <property name="severity" value="warning"/>

    <!-- Checks that a package.html file exists for each package.     -->
    <!-- See http://checkstyle.sf.net/config_javadoc.html#PackageHtml -->
    <module name="JavadocPackage"/>

    <!-- Checks whether files end with a new line.                        -->
    <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
    <module name="NewlineAtEndOfFile">
        <property name="severity" value="ignore"/>
    </module>

    <!-- Checks that property files contain the same keys.         -->
    <!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
    <module name="Translation"/>

    <!-- Checks for Size Violations.                    -->
    <!-- See http://checkstyle.sf.net/config_sizes.html -->
    <module name="FileLength"/>
    <!-- Checks for whitespace                               -->
    <!-- See http://checkstyle.sf.net/config_whitespace.html -->
    <module name="FileTabCharacter">
        <property name="severity" value="ignore"/>
    </module>

    <!-- Miscellaneous other checks.                   -->
    <!-- See http://checkstyle.sf.net/config_misc.html -->
    <module name="RegexpSingleline">
       <property name="severity" value="ignore"/>
       <property name="format" value="\s+$"/>
       <property name="minimum" value="0"/>
       <property name="maximum" value="0"/>
       <property name="message" value="Line has trailing spaces."/>
    </module>

    <module name="TreeWalker">
        <property name="tabWidth" value="4"/>

        <!-- Checks for Javadoc comments.                     -->
        <!-- See http://checkstyle.sf.net/config_javadoc.html -->
        <module name="JavadocMethod">
            <property name="logLoadErrors" value="true"/>
            <property name="suppressLoadErrors" value="true"/>
        </module>
        <module name="JavadocType"/>
        <module name="JavadocVariable"/>
        <module name="JavadocStyle"/>

        <!-- Checks for Naming Conventions.                  -->
        <!-- See http://checkstyle.sf.net/config_naming.html -->
        <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   -->
        <!-- &lt;module name="Header">                            --&gt;
            <!-- The follow property value demonstrates the ability     -->
            <!-- to have access to ANT properties. In this case it uses -->
            <!-- the ${basedir} property to allow Checkstyle to be run  -->
            <!-- from any directory within a project. See property      -->
            <!-- expansion,                                             -->
            <!-- http://checkstyle.sf.net/config.html#properties        -->
            <!-- &lt;property                                              -->
            <!--     name="headerFile"                                  -->
            <!--     value="${basedir}/java.header"/>                   --&gt;
        <!-- &lt;/module> --&gt;

        <!-- Following interprets the header file as regular expressions. -->
        <!-- &lt;module name="RegexpHeader"/>                                --&gt;

        <!-- Checks for imports                              -->
        <!-- See http://checkstyle.sf.net/config_import.html -->
        <module name="AvoidStarImport"/>
        <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
        <module name="RedundantImport"/>
        <module name="UnusedImports"/>

        <!-- Checks for Size Violations.                    -->
        <!-- See http://checkstyle.sf.net/config_sizes.html -->
        <module name="LineLength"/>
        <module name="MethodLength"/>
        <module name="ParameterNumber"/>

        <!-- Checks for whitespace                               -->
        <!-- See http://checkstyle.sf.net/config_whitespace.html -->
        <module name="EmptyForIteratorPad"/>
        <module name="MethodParamPad"/>
        <module name="NoWhitespaceAfter">
            <property name="tokens" value="BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
        </module>
        <module name="NoWhitespaceBefore"/>
        <module name="OperatorWrap"/>
        <module name="ParenPad"/>
        <module name="TypecastParenPad"/>
        <module name="WhitespaceAfter"/>
        <module name="WhitespaceAround">
            <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LCURLY,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,RCURLY,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND,WILDCARD_TYPE"/>
        </module>

        <!-- Modifier Checks                                    -->
        <!-- See http://checkstyle.sf.net/config_modifiers.html -->
        <module name="ModifierOrder"/>
        <module name="RedundantModifier"/>

        <!-- Checks for blocks. You know, those {}'s         -->
        <!-- See http://checkstyle.sf.net/config_blocks.html -->
        <module name="AvoidNestedBlocks"/>
        <module name="EmptyBlock"/>
        <module name="LeftCurly"/>
        <module name="NeedBraces"/>
        <module name="RightCurly"/>

        <!-- Checks for common coding problems               -->
        <!-- See http://checkstyle.sf.net/config_coding.html -->
        <module name="AvoidInlineConditionals"/>
        <module name="DoubleCheckedLocking"/>    <!-- MY FAVOURITE -->
        <module name="EmptyStatement"/>
        <module name="EqualsHashCode"/>
        <module name="HiddenField"/>
        <module name="IllegalInstantiation"/>
        <module name="InnerAssignment"/>
        <module name="MagicNumber"/>
        <module name="MissingSwitchDefault"/>
        <module name="RedundantThrows">
            <property name="logLoadErrors" value="true"/>
            <property name="suppressLoadErrors" value="true"/>
        </module>
        <module name="SimplifyBooleanExpression"/>
        <module name="SimplifyBooleanReturn"/>

        <!-- Checks for class design                         -->
        <!-- See http://checkstyle.sf.net/config_design.html -->
        <module name="DesignForExtension"/>
        <module name="FinalClass"/>
        <module name="HideUtilityClassConstructor"/>
        <module name="InterfaceIsType"/>
        <module name="VisibilityModifier"/>

        <!-- Miscellaneous other checks.                   -->
        <!-- See http://checkstyle.sf.net/config_misc.html -->
        <module name="ArrayTypeStyle"/>
        <module name="FinalParameters"/>
        <module name="TodoComment">
            <property name="severity" value="ignore"/>
        </module>
        <module name="UpperEll"/>

    </module>

</module>

 

从中,我们不难提炼出关键部分:

<module name="Checker">
    <module name="TreeWalker">
        <property name="tabWidth" value="4"/>
        <property name="charset" value="UTF-8"/>
        <module name="JavadocMethod"/>
        <module name="JavadocVariable"/>
            <property name="severity" value="ignore"/>
            <property name="scope" value="protected"/>
        </module>
        <module name="AvoidStarImport"/>
    </module>
    <module name="PackageHtml"/>
</module>

以树的形式解析Java文件的各个部分,方法啊,变量啊。module下可以通过property 来定义属性,有个万精油属性severity,任何module都可以用,用来标识是否执行某项检查,设为ignore即不报警。如果你想严格控制代码格式,好,没问题,设成 error,\(^o^)/~,即便一个空格不对也给你显示一个红叉,O(∩_∩)O~,估计人家项目组会过来拍砖了。

不同的Module拥有的属性都不一样,具体有哪些属性可以参考文档 http://checkstyle.sourceforge.net/。如果不想查文档,或者查不了文档(断网了),没关系我们还可以用第二种方式,咱不还有插件嘛。

插件的好处就在于不用再费心去查文档看有哪些属性了,双击打开一目了然。比如我发现很多警告都是因为第一行没以句号结尾。几乎所有的Java Doc注释都是如下形式:

/**

* XXX

*/

当然没有句号了,于是去掉勾选checkFisrtSentence。再一查,少了很多警告。

p_w_picpath 

对于CheckStyle的介绍到这里差不多了,最后啰嗦一句,openutils工程下也有两个CheckStyle文件

https://openutils.svn.sourceforge.net/svnroot/openutils/trunk/src/config,可以参考;另外OReilly.Java.Power.Tools这本书也颇具参考价值。