Checkstyle使用参考

    技术2022-05-11  116

    Checkstyle使用参考

    一、Checkstyle简介

    Checkstyle 是一个帮助开发者按照某种习惯编写 java 代码的工具,他实现了代码检查的自动化,帮助人们从这种繁琐的工作中解放出来。

    默认提供了对 sun 编程规范的支持,但是 Checkstyle 是一个具有高可配置性的,你完全可以根据自己的要求来配置需要检查的内容。

    二、Checkstyle+Ant

    1 下载安装

    1.1 Ant的下载安装

    下载apache-ant- 1.6.5 -bin.zip,然后解压缩到C:/apache-ant-1.6.5(或其它路径下)。

    添加新的环境变量ANT_HOME

     

    添加新的变量值到环境变量Path

     

    Dos窗口下输入ant回车,如果看到下图的内容,说明Ant已经成功安装了。

     

    如果没看到上图的信息,请根据运行环境的实际情况检查下列信息

    ANT_HOME = C:/apache-ant- 1.6.5

    JAVA_HOME = C:/j2sdk 1.4.2 _08

    Path = %ANT_HOME%/bin;%JAVA_HOME%/bin;(后面还有很多,这里就省略了)

    ClASSPATH = .;%JAVA_HOME%/jre/lib/rt.jar;%JAVA_HOME%/lib/tools.jar

    (注意上面一行等号后面是个点“.” 后面接分号)

     

    1.2 Checkstyle的下载安装

    下载checkstyle-4.2.zip,然后解压缩到C:/checkstyle-4.2(或其它路径下),下文提到这个路径时将使用CHECKSTYLE_HOME代替。

    CHECKSTYLE_HOME目录下的checkstyle-optional-4.2.jar拷贝到ANT_HOME/lib目录下

     

    2.使用Ant实现代码检查

    使用Ant实现代码检查,我们共需要三个文件build.xml, user.propertiessunrising_checks.xml,下面分别对讲解这三个文件。

    2.1 user.properties

    这个文件是将要在build.xml中用的属性文件,用户可以自定义下面的常用的属性

    # 项目名称

    project.name=TopShelf

     

    # 项目所在的路径

    project.dir=F/://eclipse//WorkSpace20061012//WordEmTest

     

    # 源文件所在的路径

    project.src.dir=${project.dir}//src

     

    # 报告生成的位置, 默认的位置为${project.dir}//report

    # 如果需要在其它位置生成报告, 请删除下面一行前面的"#",并且在等号后面给出路径

    # project.checkstyle.report.dir=new path here

     

    # 检测结果文件名, 默认为${project.name}-checkstyle-result-${DSTAMP}.xml

    # 如果需要在改成其它的文件名, 请删除下面一行前面的"#",并且在等号后面给出新的文件名

    # project.check.result.name=new name here

     

    # 检测报告文件名, 默认为${project.name}-checkstyle-report-${DSTAMP}.html

    # 如果需要在改成其它的文件名, 请删除下面一行前面的"#",并且在等号后面给出新的文件名

    # project.check.report.name=new name here

     

    # checkstyle的配置文件, 默认的配置文件为${basedir}/sunrising_checks.xml

    # 如果需要使用其它的配置文件, 请删除下面一行前面的"#",并且在等号后面给出配置文件的路径

    # checkstyle.config=new path here

     

    # checkstyle的报告风格, 默认值为${basedir}/contrib/checkstyle-noframes.xsl

    # checkstyle.report.style=new style here

     

    2.2 build.xml

    这个文件是运行Ant时需要用的文件

    <project name="checkstyle" default="checkstyle" basedir=".">

      <!-- 导入属性文件 -->

        <property file="user.properties" />

        <target name="init">

            <tstamp/>

            <!-- 报告的生成位置 -->

            <property name="project.checkstyle.report.dir" value="${project.dir}/report"/>

            <!-- 检测结果的文件名 -->

            <property name="project.check.result.name" value="${project.name}-checkstyle-result-${DSTAMP}.xml"/>

            <!-- 检测报告的文件名 -->

            <property name="project.check.report.name" value="${project.name}-checkstyle-report-${DSTAMP}.html"/>

            <!-- 所使用的配置文件 -->

            <property name="checkstyle.config" value="${basedir}/sunrising_checks.xml"/>

            <!-- 报告风格 -->

            <property name="checkstyle.report.style" value="${basedir}/contrib/checkstyle-noframes.xsl"/>

            <!-- 检测结果 -->

            <property name="checkstyle.result" value="${project.checkstyle.report.dir}/${project.check.result.name}"/>

            <!-- 检测报告 -->

            <property name="checkstyle.report" value="${project.checkstyle.report.dir}/${project.check.report.name}"/>

            <!-- 新建报告所在的文件夹 -->

            <mkdir dir="${project.checkstyle.report.dir}" />

        </target>

                 

        <taskdef resource="checkstyletask.properties" classpath="${basedir}/checkstyle-all-4.2.jar" />          

        <target name="checkstyle" depends="init" description="Check java code and report ">

            <!-- failOnViolation: 检测到问题时是否停止 -->

            <!-- failureProperty: 是否有问题, 这个参数在此暂没有用到 -->

            <!-- See CHECKSTYLE_HOME/docs/anttask.html -->

            <checkstyle config="${checkstyle.config}" failOnViolation="false" failureProperty="checkstyle.failure">

                <formatter type="xml" tofile="${checkstyle.result}"/>

                <fileset dir="${project.src.dir}" includes="**/*.java"/>

            </checkstyle>

            <!-- 生成报告,其格式取决于${checkstyle.report.style} -->

            <style in="${checkstyle.result}" out="${checkstyle.report}" style="${checkstyle.report.style}"/>

        </target>

    </project>

    2.3 sunrising_checks.xml

    这个文件是Checkstyle在执行代码检测时需要用的配置文件,里面定义的检查规则。详细的规则定义将在第四节做详细介绍。

     

    2.4 执行步骤

    A)     将上面提到的三个文件拷贝到CHECKSTYLE_HOME目录下

    B)     打开DOS窗口进入到CHECKSTYLE_HOME目录下

     

    C)     输入ant,然后回车,如果能看到BUILD SUCCESSFUL就成功了。

    三、Checkstyle+Eclipse

    1 安装CheckstyleEclipse的插件

    A)     首选下载CheckstyleEclipse的插件-com.atlassw.tools.eclipse.checkstyle_ 4.1.1 -bin.zip

    B)     将插件解压缩后,将featuresplugins和文件夹中的内容拷贝到Eclipse下对应的文件夹下

    C)     删除ECLIPSE_HOME/configuration/下的org.eclipse.update文件夹,然后重新启动Eclipse

    2 Eclipse中使用Checkstyle

    A)     插件安装成功后,在Eclipse中点击Window->Preferences选项可以看到下图

     

    B)     在项目上使用Checkstyle。右键单击项目,选择Properties选项后可以看到下图

    1)        选择Checkstyle

    2)        选中Check BoxCheckstyle active for this project

    3)        从下拉列表中选择一个Checkstyle的配置文件

    4)        点击OK

     

    查看项目中的任意一个源文件,可以看到类似下图的情况:

    将鼠标指向图中的放大镜处稍做停留便可看到提示信息,如图片中的”Missing a Javadoc comment.”

     

    四、Checkstyle配置文件的简要说明

    关于配置文件的各个模块的更多细节,请参考CHECKSTYLE_HOME/docs/index.html

     

    <?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">

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

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

    <module name="Checker">

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

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

    <!--

    <module name="PackageHtml"/>

    -->

    <!-- 检验每个文件末尾是否有一个空行-->

    <!-- 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 comments for 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" value="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"/>

    <!--

    <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>

     

    五、Checkstyle常见的输出结果

    1Type is missing a javadoc commentClass   

    缺少类型说明

    2“{” should be on the previous line

    “{” 应该位于前一行

    3Methods is missing a javadoc comment

    方法前面缺少javadoc注释

    4Expected @throws tag for “Exception”

    在注释中希望有@throws的说明

    5“.” Is preceeded with whitespace “.”

    前面不能有空格

    6“.” Is followed by whitespace“.”

    后面不能有空格

    7“=” is not preceeded with whitespace

    “=” 前面缺少空格

    8“=” is not followed with whitespace   

    “=” 后面缺少空格

    9“}” should be on the same line    

    “}” 应该与下条语句位于同一行

    10Unused @param tag for “unused”

    没有参数“unused”,不需注释

    11Variable “CA” missing javadoc

    变量“CA”缺少javadoc注释

    12Line longer than 80characters   

    行长度超过80

    13Line contains a tab character

    行含有”tab” 字符

    14Redundant “Public” modifier

    冗余的“public” modifier

    15Final modifier out of order with the JSL

    suggestionFinal modifier的顺序错误

    16Avoid using the “.*” form of import

    Import格式避免使用“.*”

    17Redundant import from the same package

    从同一个包中Import内容

    18Unused import-java.util.list

    Import进来的java.util.list没有被使用

    19Duplicate import to line 13

    重复Import同一个内容

    20Import from illegal package

    从非法包中 Import内容

    21“while” construct must use “{}”

    “while” 语句缺少“{}”

    22Variable “sTest 1” must be private and have accessor method

    变量“sTest 1” 应该是private的,并且有调用它的方法

    23Variable “ABC” must match pattern “^[a-z][a-zA-Z0-9]*$”      

    变量“ABC”不符合命名规则“^[a-z][a-zA-Z0-9]*$”

    24“(” is followed by whitespace    

    “(” 后面不能有空格

    25“)” is proceeded by whitespace

    “)” 前面不能有空格

     


    最新回复(0)