静态代码检查-CheckStyle

来源:互联网 发布:ftp同步文件软件 编辑:程序博客网 时间:2024/04/27 05:56

提高代量,除了要提高逻辑上的控制以及业务流程的理解外,代本身也存在提高的空,例如一些潜在的问题可以很早的就避免。似于编码规范上的内容,如果全靠编码员进行自行检查,那无疑需要很大的工作量,如果可以使用代的静态检查工具检查,那将大大的提高编码的效率。

本文是提高代码质量系列文章的第二篇,主要介了如何使用checkstyle工具行代的自检查,以避一些潜在的问题并找出代逻辑错误

1.         什么是checkstyle

Checkstyle是一个用于帮助编写Java代码的程序员来遵守特定的编码标准。Checkstyle可以自动进行代码的检查,因为代码检查非常重要,但是又很枯燥,所以可以自动的进行代码检查无疑节省了很多的工作量。Checkstyle尤其适用于强制使用编码标准的项目。

Checkstyle是完全可以进行自定义配置的,并且可以支持几乎任何的编码标准。例如提供了支持Sun Code Conventions编码标准的样例配置文件以及一些其他的样例配置文件。

Checkstyle可以检查源代码的很多方面,checkstyle的本意是检查代码的布局及样式,但是从版本3之后,就已经追加了更多的检查项目。现在的checkstyle版本已经可以检查诸如设计问题,重复代码,以及double checked lockingbug。具体请参考标准检查项可选检查项

可以在SourceForge下载页面下载Checkstyle的最新版本。

相关工具:如果将Checkstyle集成到构建过程中的话,那么将起到最大的作用。Checkstyle的发布版本包含以下内容:

       Ant Task

       命令行工具

另外,也有很多第三方的插件可供使用,例如EclipseWSADIntelliJ IDEANetBeans等流程的Java开发IDE

2.         CheckStyle的配置

Checkstyle的配置用来指定哪些模块适用于Java源文件。模块是一个以Checker模块为根元素的树结构。modules的下一层元素包括如下的内容:

®       FileSetChecks:一些以输入文件为参数的模块,并引发错误消息。

®       Filters:过滤审核事件的模块,包括错误消息。

®       AuditListeners:报告被接受的事件。

很多检查是TreeWalker FileSetCheck模块的子模块。TreeWalker通过逐个的将Java源文件转换成抽象的语法树,然后循环它的每个子模块来处理检查结果。每个子模块检查各自特定的方面。

CheckstyleXML文件获取配置,在XML文档中指定了配置的模型的层次以及他们的属性。当使用命令行执行Checkstyle命令(或者在ant任务中使用Checkstyle的时候)是需要提供一个包含配置文档的文件。Checkstyle的发布包中的doc目录中包含了一个样例的配置文件sun_checks.xml可以检查Sun的编码规范。

Modules

XML配置文档中由元素的name属性指定的module元素。下面是一个典型的配置片段:

<module name="Checker">

    <module name="PackageHtml"/>

    <module name="TreeWalker">

        <module name="AvoidStarImport"/>

        <module name="ConstantName"/>

        <module name="EmptyBlock"/>

    </module>

</module>

在上面的配置中:

®       根模块Checker包含了子模块FileSetChecks PackageHtmlTreeWalker(PackageHtml模块检查所有的包都要有文档)

®       模块TreeWalker包含了子模块AvoidStarImportConstantNameEmptyBlock。这些子模块分别检查Java源文件是否有星号引入语句、合法的常两名以及是否包含空块。

对于每个配置模块,checkstyle通过module元素的name属性指定要加载的类。加载模块的类的规则如下:

®       根据指定的包名,例如加载类com.puppycrawl.tools.checkstyle.TreeWalker<module name =” com.puppycrawl.tools.checkstyle.TreeWalker”>,这有助于第三方的模块集成到配置中。

®       checkstyle预定义的包名,例如com.puppycrawl.tools.checkstyle.checkscom.puppycrawl.tools.checkstyle.filters以及它的子包(仅包含在Checkstyle发布版本中)

®       上述规则中与Check连接而成的,例如com.pupycrawl.tools.checkstyle.checks.ConstantNameCheck类的话,可以使用ConstantName作为module的名字

属性

属性用于控制模块如何执行任务的。每个模块的属性都有一个默认值。下面是三个例子用于指定属性:

<module name="MethodLength">

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

</module>

max的默认值为150,可以将其自定义为60,如果默认值可以满足检查的要求,那么就不要修改默认值。

<module name="Checker">

    <module name="PackageHtml"/>

    <module name="TreeWalker">

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

        <module name="AvoidStarImport"/>

        <module name="ConstantName"/>

        ...

    </module>

</module>

模块的属性是可以继承的,例如上面例子中的TreeWalker的属性tabWidth,就可以被AvoidStarImportConstantName等子模块继承。

<property name="headerFile" value="${checkstyle.header.file}"/>

属性是可以被扩展的,可以在运行时指定属性的值。

<module name="JavaDocMethod">

  <property name="severity"

               value="${checkstyle.javadoc.severity}"

               default="error"/>

</module>

可以在指定属性值后设置一个默认值,当属性值没有被设置时,使用默认的属性值,如上面的例子中checkstyle.javadoc.severity没有被设置时,severity属性的值就是error

Checker

所有的配置都有一个根模块CheckerChecker包含以下内容:

®       FileSetCheck:用于检查文件的模块

®       Filter:用于过滤审核事件

®       AuditListener:报告被过滤的事件

Checker还定义被所有其他模块继承的属性:

®       basedir:基准目录名,字符串类型,默认值为null

®       localeCountry:区域设置,字符串类型,可以是空字符串或者大写的ISO 3166标准的2个大写代码,默认值为JVM的区域设置

®       localeLanguage:消息的区域语言,字符串类型,可以是空字符串或者是小写的ISO 639代码,默认值是JVM的区域语言

TreeWalker

FilterSetCheck TreeWalker 检查单个的Java源文件,并定义适用于检查这些文件的属性:

®       cacheFile:缓存文件,用于缓存已经通过检查的文件,避免重复检查文件。字符串类型,默认为null

®       tabWidthtab字符的空格数。整型,默认为8

®       fileExtensions:用于标识java文件的扩展名。字符串类型集合,默认为java

®       charset:文件的编码格式。字符串类型,默认为系统属性file.encoding

<module name="Checker">

    <module name="TreeWalker">

        <property name="cacheFile" value="target/cachefile"/>

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

                     <property name="charset" value="UTF-8"/>

        ...

    </module>

</module>

可以在TreeWalker中写重复的模块来应用不同的检查。

<module name="MethodLength">

    <property name="tokens" value="METHOD_DEF"/>

</module>

<module name="MethodLength">

    <property name="tokens" value="CTOR_DEF"/>

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

</module>

Severity

每个检查都有一个severity属性,这是Checkstyle审查分配给检查的所有违反项。默认的severity等级是error

使用下面的定义就可以输出转换警告:

<module name="Translation">

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

</module>

Filters

checkstyle模块可以包含一系列的Filter子模块用于过滤审查事件,包括checks产生的错误消息。过滤器可以接受获取拒绝审查事件。如果所有的过滤器都接受审查事件,那么checker就报告该事件。

SeverityMatchFilter

这个过滤器根据severity等级来决定审查事件。这个过滤器包含如下的属性:

®       severity:过滤器的severity的等级。severity类型,默认值为error

®       acceptOnMatch:如果该属性的值为true,那么当且仅当事件的severity等级和属性severity的值相匹配时,才接受审查。如果值为false的话,那么当且仅当事件的severity等级与severity属性值不匹配时才接受审查。boolean型,默认值为true

<module name="SeverityMatchFilter">

    <property name="severity" value="info"/>

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

</module>

一些其他的过滤器请参考checkstyles文档

3.         运行Checkstyle

可以通过两种方式来运行Checkstyle,一种是使用Ant Task,即在Ant构建脚本中执行Checkstyle,另一种就是命令行。当然还有很多IDE的集成插件,在后面进行介绍。

checkstyleant task用于在指定的Java文件中运行Checkstylecheckstyle ant taskAnt 1.5版本下测试完成。最新版本的Checkstyle中包含了ant task

最简单的安装方式就是将checkstyle-all-4.4.jar加入到classpath中。这个jar文件中包含了所有运行Checkstyle所需的类。如果不这样做的话,下面的这些类必须添加到classpath中:

®       checkstye-4.4.jar

®       ANTLR 2.7.2中的类,在发布版本中已经包含了这个jar文件

®       Jakarta Commons中的Beanutils类、Collections类、Logging类,这些jar包都包含在发布版本中

®       符合JAXP规范的XML解析器,在JDK 1.4版本以后就已经包含了

如果要使用checkstyle ant task,需要使用taskdef定义checkstyle任务:

<taskdef resource="checkstyletask.properties"

         classpath="/path/to/checkstyle-all-4.4.jar"/>

或者假设Checkstyle位于全局的classpath中,可以使用如下的taskdef定义:

<taskdef resource="checkstyletask.properties"/>

checkstyle任务的参数:

file:需要检查的文件。

config:指定配置文件。

configURL:指定配置文件的URL

(configconfigURL中必须指定一个)

properties:指定包含扩展属性值的属性文件。

packageNamesFile:指定一个包含配置的package名的文件。

failOnViolation:如果检查出错误时,是否停止。默认为true

failureProperty:如果发生错误时,需要设置的属性的名称。

maxErrors:允许发生错误ude最大数。默认为0

maxWarnings:允许发生的警告的最大数。默认值为整型的最大值。

classpath:查询类时使用的类路径。默认为当前classpath

classpathref:类路径的引用。

嵌套元素:checkstyle任务支持以下的嵌套元素:<fileset><classpath><formatter><property>。其中<formatter>元素的参数如下:

type:生成的输出内容的类型,合法的值包括plainxml。默认的值为plain

toFile:将输出写入的文件。默认为标准输出。

useFile:是否将输出写入到文件,默认为true

<property>元素指定提供扩展属性的值的属性文件。该元素的参数如下:

key:属性的键值。

value:字符串格式的属性的值。

file:文件格式的属性的值。

(valuefile参数必须设置一个)

下面是一些例子:

<checkstyle config="docs/sun_checks.xml" file="Check.java"/>

 

<checkstyle config="/path/to/site/sun_checks.xml">

  <fileset dir="src/checkstyle" includes="**/*.java"/>

  <!-- Location of cache-file. Something that is project specific -->

  <property key="checkstyle.cache.file" file="target/cachefile"/>

</checkstyle>

 

<checkstyle config="docs/sun_checks.xml">

  <fileset dir="src/checkstyle" includes="**/*.java"/>

  <formatter type="plain"/>

  <formatter type="xml" toFile="build/checkstyle_errors.xml"/>

</checkstyle>

 

<checkstyle config="docs/sun_checks.xml"

            packageNamesFile="myPackageNames.xml"

            file="Check.java"/>

 

<target name="checkstyle"

        description="Generates a report of code convention violations.">

  <checkstyle config="docs/sun_checks.xml"

              failureProperty="checkstyle.failure"

              failOnViolation="false">

    <formatter type="xml" tofile="checkstyle_report.xml"/>

    <fileset dir="src" includes="**/*.java"/>

  </checkstyle>

  <style in="checkstyle_report.xml" out="checkstyle_report.html" style="checkstyle.xsl"/>

</target>

<!-- run this target as part of automated build -->

<target name="checkstyle-nightly"

        depends="checkstyle"

        if="checkstyle.failure"

        description="Sends email if checkstyle detected code conventions violations.">

  <!-- use your own server and email addresses below. See Ant documentation for details -->

  <mail from="qa@some.domain"

        tolist="someone@some.domain,someoneelse@some.domain"

        mailhost="mailbox.some.domain"

        subject="Checkstyle violation(s) in project ${ant.project.name}"

        files="checkstyle_report.html"/>

</target>

 

Checkstyle的命令行使用方式:

java -D<property>=<value>  /

     com.puppycrawl.tools.checkstyle.Main /

     -c <configurationFile> [-n <packageNameFile>] /

     [-f <format>] [-p <propertiesFile>] [-o <file>] /

     [-r <dir>] file...

    *   -n packageNamesFile - 指定使用的package name文件。

    * -f format - 指定输出的格式。

    * -p propertiesFile - 指定使用的属性文件。

    * -o file - 指定输出文件。

    * -r dir - 指定需要遍历java文件的目录。

4.         Eclipse中使用Checkstyle

CheckstyleEclipse插件的官方地址为:http://eclipse-cs.sourceforge.net/。安装Checkstyle插件的过程与安装PMDFindbugs的过程一致,这里就不做介绍了。

下面是安装Eclipse插件的过程与注意点(注意点适用于所有的Eclipse Plug-in)

The first way to install the Eclipse Checkstyle Plug-in is via the update site.

   1. Within Eclipse go to Help->Software Updates->Find and Install

   2. Choose Search for new features to install and press Next

   3. Create a New Remote Site...

   4. Input a name to your liking (for instance Checkstyle Plug-in) and input the following URL: http://eclipse-cs.sourceforge.net/update

   5. Click your way through the following pages to install the plug-in.

Alternatively the Checkstyle Eclipse Plug-in can be downloaded from the Eclipse Checkstyle Plug-in's SourceForge project page. The download package consists of a single zip file that contains both the Checkstyle Plug-in and the Checkstyle core engine.

Once you have downloaded the distribution zip file extract its contents. First, exit from Eclipse. Next, copy the com.atlassw.tools.eclipse.checkstyle_<version> folder to your Eclipse plug-in folder and restart Eclipse. That's all there is to it, you are now ready to run Checkstyle.

Important Note: If you did not use the update site to install the plug-in please make sure to restart Eclipse with the -clean option at least once. This is because Eclipse caches a lot of information about plug-ins. In case you just updated the plug-in from a previous version this information cached by Eclipse is not up to date - resulting in the plug-in failing with ClassNotFoundExceptions and other serious issues.

Important Note: As of plug-in release 4.0.0 only Eclipse 3.0 and newer is supported. Eclipse 2.x.x support is discontinued. Please use older plug-in versions with Eclipse 2.x.x. - downloadable from the SourceForge Project Page

关于在Eclipse中使用Checkstyle的方法,请参考Eclipse-checkstyle官方文档:

http://eclipse-cs.sourceforge.net/getting_started.html

以上,笔者只是简单的介绍了checkstyle的一些基本内容,当然,更多的知识需要去学习与掌握。只有先进行一定的了解,例如,必须先知道要进行代码的静态检查,提高代码的质量,然后考虑代码的人工检查还是自动检查,再考虑使用自动检查工具,最后去熟悉流行的业界检查工具标准,最后学习如何使用检查工具。

希望笔者的抛砖引玉的文章可以给各位读者带来一些帮助。

原创粉丝点击