Google checkstyle实战

概述

CheckStyle检查代码是否符合制定的规范。CheckStyle检查是基于源码的,无需编译,执行速度快。

CheckStyle的主要流程是:

  1. 对Java文件进行词法语法分析,生成语法树。
  2. 载入配置文件(checkstyle-metadata.xml以及自定义的配置文件)register check事件。
  3. 按照深度优先遍历对语法树进行解析,按照注册的事件,在到达某些节点(AST)时进行style检查。AST,A child-Sibling Tree,是语法树中的某个节点,其类型在TokenTypes类中定义。
  4. 自定义Style的检查,就是在第二步设定的。实现com.puppycrawl.tools.checkstyle.api.Check类,重载其中的两个方法:public int[] getDefaultTokens()public void visitToken(DetailAST ast)。这两个方法的含义为,在遍历语法树的过程中,每当到达getDefaultTokens函数所返回的AST类型,程序就进入visitToken进行具体的检查和分析,即真正的分析检查过程是在visitToken中实现的。

CheckStyle有针对不同IDE和构建工具的各种插件,如 maven-checkstyle-plugin 插件,配置很简单:

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-checkstyle-plugin</artifactId><version>3.3.1</version><configuration><!--内置4种规范:config/sun_checks.xml、config/maven_checks.xml、config/turbine_checks.xml、config/avalon_checks.xml、其中sun_checks.xml为默认值。修改默认配置--><configLocation>google_checkstyle.xml</configLocation></configuration><executions><execution><id>checkstyle</id><phase>validate</phase><goals><goal>check</goal></goals><configuration><failOnViolation>true</failOnViolation></configuration></execution></executions>
</plugin>

定义在maven lifecycle的validate阶段执行check task,并且如果发现有违反标准的情况就会fail当前的build。运行checkstyle检查:mvn checkstyle:checkstyle

跳过对指定文件的某些检查

  • suppression:忽略指定文件的问题检查,不推荐;
  • 新增checkstyle-suppressions.xml文件suppressions配置项:
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC"-//Puppy Crawl//DTD Suppressions 1.0//EN""http://www.puppycrawl.com/dtds/suppressions_1_0.dtd">
<suppressions><suppress checks="LineLengthCheck"files="SessionMessageSource.java"/>
</suppressions>

<suppressionsLocation>${basedir}/src/config/checkstyle-suppressions.xml</suppressionsLocation>
然后在配置文件里面可以定义一系列可用的模块,每一个模块提供严格程度(强制的,可选的…)可配置的检查规则。规则可以触发通知(notification),警告(warning)和错误(error)。
附:google-checkstyle

特点:

  1. 它可以有效的帮助我们检视代码以便更好的遵循代码编写标准,特别适用于小组开发时彼此间的样式规范和统一。
  2. Checkstyle提供高可配置性,以便适用于各种代码规范,所以除了使用它提供的几种常见标准之外,你也可以定制自己的标准。
  3. Checkstyle提供支持大多数常见IDE的插件,大部分插件中就含有最新的Checkstyle。
  4. Checkstyle可以检查代码的很多方面,从传统观点看,它主要是用来检查代码层面的,自从第三版以后,它的内部架构作了重大改变,很多其它意图的检测加了进来,现在Checkstyle可以检查像类设计的问题,重复代码,如锁的双重检查的bug模式。

报错

Token “METHOD_REF” was not found in Acceptable tokens list in check SeparatorWrapCheck

在IDEA的Terminal执行mvn clean compile报错:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-checkstyle-plugin:3.0.0:check (checkstyle) on project test: Failed during checkstyle configuration: cannot initialize module TreeWalker - Token "METHOD_REF" was not found in Acceptable tokens list in check com.puppycrawl.tools.checkstyle.checks.whitespace.SeparatorWrapCheck.

参考stackoverflow问答java-google-checkstyle-maven:

You are trying to use a newer configuration with an old version of Checkstyle.

上面的报错信息提示,使用的Maven插件版本为3.0.0,升级到当前最新版3.3.1解决问题。

TreeWalker is not allowed as a parent of LineLength Please review ‘Parent Module’ section for this Check in web documentation if Check is standard.

继续执行mvn clean compile报错:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-checkstyle-plugin:3.3.1:check (checkstyle) on project test: Failed during checkstyle configuration: cannot initialize module TreeWalker - TreeWalker is not allowed as a parent of LineLength Please review 'Parent Module' section for this Check in web documentation if Check is standard.

参考GitHub issue,LineLength本来在TreeWalker module下面,提升到与TreeWalker同级的module,解决问题。
在这里插入图片描述
虽然解决问题,但是这样下去感觉问题会无穷无尽。

升级配置文件

考虑到上面升级过maven插件,即maven-checkstyle-plugin到最新版,那配置文件是不是也得一起升级下?打开托管在GitHub的官方配置文件google_checks,借助于diffchecker这类在线文本对比工具,好家伙。本地配置文件和GitHub里的配置文件相差也太大了吧。是该更新一下了!!

至于为何不直接使用存放在GitHub上的配置文件?这样的话,可以保证一直使用最新的配置文件。而要使用一个下载到本地的必定会过期的备份配置文件?主要是两点考量:

  1. The Wall的存在,访问GitHub速度不是很快很稳定;
  2. 一份可用的配置文件可以保证团队成员使用尽可能相同的编码规范。

Token “LITERAL_SWITCH” was not found in Acceptable tokens list in check RightCurlyCheck.

继续执行mvn clean compile依旧报错:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-checkstyle-plugin:3.3.1:check (checkstyle) on project test: Failed during checkstyle configuration: cannot initialize module TreeWalker - Token "LITERAL_SWITCH" was not found in Acceptable tokens list in check com.puppycrawl.tools.checkstyle.checks.blocks.RightCurlyCheck.

不会吧。插件和配置文件都是最新的,配置文件是官方提供的,没有任何修改。

搜索google_checkstyle.xml文件,可以找到LITERAL_SWITCH及RightCurly。分析此最新版配置文件,不难得出结论:

  • checkstyle有若干个module组成,表示各个不同检查环节
  • LineLength不再是TreeWalker module下的子module,而是和TreeWalker同级,这也正好印证上面一个问题
  • TreeWalker下有若干个module,一个module对应一个方法,如com.puppycrawl.tools.checkstyle.checks.blocks.RightCurlyCheck
  • 那token是什么呢?进阶章节会继续研究

回到问题本身。分析报错,大意是在RightCurly这个module里有个tokens属性字段里不能出现LITERAL_SWITCH?

抱着试一试的想法,修改官方提供的配置文件,删除RightCurly module下LITERAL_SWITCH这个token。

再次执行mvn clean compile,上面这个报错消失。出现新的报错,不过其形式和上面的报错一模一样。那就依样画瓢,找到报错的module和token,删除。最后执行mvn clean compile成功。

进阶

源码分析

上面留下一个疑问:token是什么?

看到完整包路径com.puppycrawl.tools.checkstyle.checks.blocks.RightCurlyCheck,不难找到maven依赖:

<dependency><groupId>com.puppycrawl.tools</groupId><artifactId>checkstyle</artifactId><version>10.13.0</version>
</dependency>

包结构如下:
在这里插入图片描述
配置文件google_checkstyle.xml里的module对应的**Check类全部位于com.puppycrawl.tools.checkstyle.checks包下面。并且Check也模块化,有一下几种类型:
在这里插入图片描述
与此同时,在目录com.puppycrawl.tools.checkstyle.meta.blocks.blocks下面有一个xml文件RightCurlyCheck.xml,和Check方法一一对应。配置文件里的module对应一个继承AbstractCheck的Check方法,对应一个**Check.xml配置文件。

NoLineWrapCheck.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<checkstyle-metadata><module><check fully-qualified-name="com.puppycrawl.tools.checkstyle.checks.whitespace.NoLineWrapCheck"name="NoLineWrap"parent="com.puppycrawl.tools.checkstyle.TreeWalker"><description>Checks that chosen statements are not line-wrapped. By default, this Check restricts wrapping import and package statements, but it's possible to check any statement.</description><properties><property default-value="PACKAGE_DEF,IMPORT,STATIC_IMPORT"name="tokens"type="java.lang.String[]"validation-type="tokenSet"><description>tokens to check</description></property></properties><message-keys><message-key key="no.line.wrap"/></message-keys></check></module>
</checkstyle-metadata>

check下的name和配置文件google_checkstyle.xml的module name正好对应,parent指向TreeWalker,fully-qualified-name指向Java类文件。properties定义检查的token。

token是什么,回到文章开头,提到AST语法树及TokenTypes类。

借助于IDEA Double Shift快捷键以及左侧的项目视图,不难快速找到com.puppycrawl.tools.checkstyle.api.TokenTypes类文件,定义194个静态常量。以及tokentypes.properties配置文件,里面正好也是194行。经过对比,是一一对应的。

tokentypes.properties文件样例:

OBJBLOCK=An object block.

message-keys

参考

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/498963.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++——模板详解

目录 模板 函数模板 显示实例化 类模板 模板特点 模板 模板&#xff0c;就是把一个本来只能对特定类型实现的代码&#xff0c;变成一个模板类型&#xff0c;这个模板类型能转换为任何内置类型&#xff0c;从而让程序员只需要实现一个模板&#xff0c;就能对不同的数据进行操…

数据库子父结构表,树状结构数据进行递归查询

表结构&#xff1a; 三个字段如图所示&#xff0c;目标是获取每条数据的根id&#xff08;父id为0的数据根id就是自己的id,否则一直根据父id去查找一直找到父id为0的数据&#xff0c;此数据的id就是根id&#xff09; 业务中实际的解决办法&#xff1a; 新加一个字段进行存储&…

【c++】 STL的组件简介与容器的使用时机

STL六大组件简介 STL提供了六大组件&#xff0c;彼此之间可以组合套用&#xff0c;这六大组件分别是:容器、算法、迭代器、仿函数、适配器&#xff08;配接器&#xff09;、空间配置器。 容器&#xff1a;各种数据结构&#xff0c;如vector、list、deque、set、map等,用来存放…

135.乐理基础-半音是小二度吗?全音是大二度吗?三全音

内存参考于&#xff1a;三分钟音乐社 上一个内容&#xff1a;134.乐理基础-音程名字的简写-CSDN博客 上一个内容里练习的答案&#xff1a; 半音可以与小二度划等号吗&#xff1f;全音可以和大二度划等号吗&#xff1f; 严格来说它们是不能划等号的&#xff0c;半音与全音是侧…

如何在Windows部署TortoiseSVN客户端并实现公网连接内网VisualSVN服务端

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

vulhub中Tomcat7+ 弱口令 后台getshell漏洞

Tomcat版本&#xff1a;8.0 环境说明 Tomcat支持在后台部署war文件&#xff0c;可以直接将webshell部署到web目录下。其中&#xff0c;欲访问后台&#xff0c;需要对应用户有相应权限。 Tomcat7权限分为&#xff1a; manager&#xff08;后台管理&#xff09; manager-gui 拥…

Spring IOC在业务中常见的使用方式

目录 1、什么是IOC 2、java实现创建对象的方式有哪些 3、基于配置文件的di实现 3.1、什么是di 3.2、入门案例 3.3、环境搭建 接口和实现类 ioc配置文件 测试程序 3.4、案例总结 3.5、简单类型属性的赋值&#xff08;set注入&#xff09; set注入要求 JavaBean sp…

内存飙高问题如何排查?

目录 1、查看日志 2、查看GC情况 3、分析堆内存对象占用情况 4、分析堆内存快照文件 内存飙高如果发生在java进程上&#xff0c;一般情况是因为创建了大量对象导致&#xff0c;持续飙高说明垃圾回收跟不上对象创建的速度&#xff0c;或者内存泄漏导致对象无法被回收&#x…

力扣刷题:2.两数相加

题目&#xff1a; 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这…

枚举(蓝桥练习)(反倍数、特别数的和、找到最多的数、小蓝的漆房、小蓝和小桥的挑战)

目录 一、枚举算法介绍 二、解空间的类型 三、循环枚举解空间 四、例题 &#xff08;一、反倍数&#xff09; &#xff08;二、特别数的和&#xff09; &#xff08;三、找到最多的数&#xff09; &#xff08;四、小蓝的漆房&#xff09; &#xff08;五、小蓝和小桥的…

(C语言)Sleep函数,system函数,数组练习,详解与运用

一维数组详解&#xff1a;http://t.csdnimg.cn/zahZF 二维数组详解&#xff1a;http://t.csdnimg.cn/h2mLe 我们看过可一维数组与二维数组&#xff0c;现在我们来进行简单的练习。 题目&#xff1a;编写代码&#xff0c;演⽰多个字符从两端移动&#xff0c;向中间汇聚 1. …

Mysql索引优化导致死锁问题

1、背景 随着公司业务的发展&#xff0c;商品库存从商品中心独立出来成为一个独立的系统&#xff0c;承接主站商品库存校验、订单库存扣减、售后库存释放等业务。在上线之前我们对于核心接口进行了压测&#xff0c;压测过程中出现了MySQL 5.6.35死锁现象&#xff0c;通过日志发…