静态分析:用Checkstyle实施Java代码规范

众所周知,良好的代码规范有助于提升可维护性和协作效率,预防缺陷。但怎样才能保证有效执行呢?

我所在团队早期曾需要在代码审查中投入时间保证规范。通过引入静态分析,问题代码被100%提前拦截,而开发人员也在即时反馈中养成了良好习惯。

本文将介绍如何为Java项目配置代码规范检查。

关于静态分析

为保证软件质量,开发团队通常需要针对每项功能进行特定的代码审查和测试,其效果受功能复杂度和经验影响并需要投入大量时间。

静态分析允许我们:

  • 不运行程序的情况下

  • 根据最佳实践常见缺陷模式

  • 对代码本身执行统一、跨功能的自动化检查

  • 从而有效扩大覆盖面、降低成本

关于Checkstyle

Checkstyle初发布于2001年,是目前GitHub上人气最高 (★4.6k)、持续活跃的Java静态分析工具。

它主要关注代码风格方面的检查,目前支持14大类、162个检查项,提供Google/Sun代码风格规范对应的配置文件,同时支持灵活的定制与扩展。

Checkstyle拥有丰富的集成方式:CLI (命令行)、构建工具支持、IDE支持等。

快速集成——Gradle

让我们以流行的Java构建工具Gradle为例,给项目添加Checkstyle检查。

利用Gradle,我们只需配置一次,即可在本地Shell构建、IDE构建和CI构建中统一生效:

集成后目录结构如下:

步骤

1

下载配置文件

首先,下载官方提供的Google Checkstyle配置文件,将其保存为config/checkstyle/checkstyle.xml 

https://github.com/checkstyle/checkstyle/blob/checkstyle-8.22/src/main/resources/google_checks.xml

2

添加插件

接下来,向 build.gradle中添加Checkstyle Gradle插件,并指定所用的Checkstyle库版本。注意:不同版本的Gradle插件默认使用的库版本是不一样的,显式指定版本可以避免兼容性问题。

3

执行构建

执行Gradle构建 (或单独运行checkstyleMain /checkstyleTest任务),可以看到检查已经生效:

4

查看报告

访问 build/reports/checkstyle 目录,可以查看报告:

Checkstyle工作流程

在做进一步详细配置前,我们先来了解一下Checkstyle的工作流程:

初始化

无论我们使用哪种集成方式调用Checkstyle,集成接口都会根据收到的参数及Checkstyle配置文件来:

  • 调用Checkstyle相关组件,创建 Configuration对象;

  • 使用Configuration创建 Checker (根模块) 实例;

  • 生成输入文件列表,将其传给 Checker开始执行。

执行

收到文件列表后,Checker模块会调用前面初始化的四种不同职责子模块完成检查:

其中“检查”阶段最常用的模块是 TreeWalker,它负责Java AST (抽象语法树) 检查的公共流程。通过配置它的子模块可以:

  • 完成各方面的AST检查 (如变量名、import语句等)。

  • 过滤事件。此处利用AST信息可以实现比顶层Filters更精细的过滤。

配置文件

了解完工作流程,我们就可以根据项目情况做进一步配置了:

  • Checkstyle配置文件: 检查规则、文件预过滤、事件过滤、TreeWalker内部过滤等绝大部分核心行为。

  • 集成接口层参数: 文件列表,配置文件路径,属性值外部定义,集成接口自有输出选项等。

Gradle等集成接口的参数较为简单并已有合理的默认值,我们关注的重点还是配置文件。配置文件与Checkstyle基于Composite (组合) 模式的模块化相对应,每个 <module> 元素包含该模块的属性值定义及子模块的配置:

典型配置文件结构如下 (属性略):

全局属性

我们可以配置根模块属性来控制Checkstyle的全局行为。常用的属性包括:

  • severity : 违规事件的严重程度

  • charset : 用于解析输入文件的字符集 (如 utf-8 )

  • fileExtensions : 受检查的文件扩展名 (逗号分隔)

基中部分属性 (如 severity ) 也适用于子模块,可在子模块配置中覆盖从父级继承的值。

完整列表请参阅:

https://checkstyle.org/config.html#Checker_Properties

实例

为确保代码规范的有效执行,我们希望把Checkstyle检查出来的问题报告为错误,中断Gradle构建。这可以通过配置 severity 实现:

重新运行 checkstyleMain 任务,得到错误信息:

自定义检查项

通过配置TreeWalker Check或独立的FileSetCheck,我们可以自定义检查项。

CheckStyle目前共支持14大类、162个检查项。想了解常用的检查项,最简单的方式就是对照Google Java Style Guide,阅读Google Checkstyle配置文件。

  • 完整列表:

    https://checkstyle.org/checks.html

  • Google Checkstyle配置文件:

    https://github.com/checkstyle/checkstyle/blob/checkstyle-8.22/src/main/resources/google_checks.xml

  • 检查项与Style Guide的对应关系:

    https://checkstyle.org/google_style.html

实例

From: Code2048

缩进圣战,是一场双方实力悬殊但仍在激烈持续的大型宗教战争,打响于人们使用编辑器编写代码伊始。

为了安抚习惯了4空格缩进和超大屏幕的团队成员,让我们在Google配置文件的基础上做点修改——缩进2→4,行宽100→150:

重新运行 checkstyleMain 任务,可见错误数显著下降,团队内的紧张气氛也随之化解了:

跳过文件

通过配置FileFilters,我们可以直接跳过文件,不对其执行任何检查。目前Checkstyle提供了BeforeExecutionExclusionFileFilter,可在其中指定要跳过的文件名正则表达式:

忽略事件

FileFilter的过滤条件不涉及文件内容。如要针对违规的位置或种类等进行过滤,可以使用TreeWalkerFilter或独立Filter,对已经产生的事件进行过滤。

下面介绍两个典型用法。完整Filter/TreeWalkerFilter列表请参阅: 

https://checkstyle.org/config_filters.html

实例:SuppressionFilter

利用SuppressionFilter这一顶级Filter,我们可以在单独的文件中定义事件过滤规则。一个常见的做法是在不同的项目间共享Checkstyle配置文件,同时分别维护各自的suppressions.xml文件。

config/checkstyle/checkstyle.xml:

(注:config_loc的值由Gradle插件传入,默认为 $rootProject.projectDir/config/checkstyle )

config/checkstyle/suppressions.xml:

实例:SuppressionCommentFilter

即便制定了最完善的代码风格规范,代码里仍可能会存在一些“合理”的违规。如果我们既不想禁用一项检查,又不想为每个特例手动修改配置文件该怎么办呢?

这时我们可以考虑SuppressionCommentFilter这一TreeWalkerFilter。定义好特殊的代码注释模式后,我们就能随时在代码中标记排除范围。例如,对由CHECKSTYLE:OPEN和 CHECKSTYLE:CLOSE 包围的代码块,忽略全部检查事件:

完整属性列表和更多实例请参阅:

https://checkstyle.org/config_filters.html#SuppressionCommentFilter

扩展Checkstyle

如果现有的检查、过滤器和报告还不能满足项目需要,我们还可以对其进行扩展。这里就不详细展开了,请参考官方文档:

https://checkstyle.org/writingchecks.html 

了解更多Java编程,请长按二维码关注微公众号

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值