各个团队多少都有一些自己的代码规范,但制定代码规范简单,困难的是如何落地。如果完全依赖人力难免有所遗漏。
这个时候就需要通过静态代码检查工具在每次提交代码时自动检查,本文主要介绍如何使用落地代码规范,主要包括以下内容
- 为什么使用?
- 接入插件
- 命令行方式接入
- 方式接入
- 自定义检测规则
- 集成检测
说起静态代码检查,大家首先想起来的可能是,相比只支持代码,不仅支持,代码,也支持资源文件规范检查,那么我们为什么不使用呢?
在我看来,在使用上主要有两个问题:
- 与集成不够好,自定义规则的警告只有在运行后才会在上展示出来,在之后又会消失
- 检查速度较慢,尤其是大型项目,只对增量代码进行检查的逻辑需要自定义
而提供了插件,开启后可直接在中查看警告,这样可以在第一时间发现问题,避免后续检查发现问题后再修改流程过长的问题
同时支持命令行方式接入与方式接入,支持只检查新增代码,在检查速度上比起也有一定的优势
如果能在中提示代码中存在的问题,应该是最快发现问题的方式,也贴心的为我们准备了插件,如下所示:
主要可以配置以下内容:
- 开关
- 格式化开关,直接使用了的规则
- :规则配置文件,可以在其中配置各种规则的开关与参数,默认配置可见:default-detekt-config.yml
- :基线文件,跳过旧代码问题,有了这个基线文件,下次扫描时,就会绕过文件中列出的基线问题,而只提示新增问题。
- : 自定义规则包,在自定义规则后打出包,在扫描时就可以使用自定义规则了
插件可以实时提示问题(包括自定义规则),如下图所示,我们添加了自定义禁止使用的规则:
对于一些支持自动修复的格式问题,插件支持自动格式化,同时也可以配置快捷键,一键自动格式化,如下所示:
支持通过命令行方式接入,支持只检测几个文件,比如本次提交的文件
我们可以通过如下方式,下载的然后使用
支持很多参数,下面列出一些常用的,其他可以参见:Run detekt using Command Line Interface
在命令行可以直接通过如下方式检查
通过如上方式进行代码检查速度是非常快的,根据经验来说一般就是几秒之内可以完成,因此我们完成可以将与结合起来,在每次提交的时候进行检测,而如果是一些比较耗时的工具比如,应该是做不到这一点的
类型解析
上面我们提到了,的参数与参数,这些是用于类型解析的。
类型解析是的一项功能,它允许 对您的 源代码执行更高级的静态分析。
通常, 在编译期间无法访问编译器语义分析的结果,我们只能获取源代码的抽象语法树,却无法知道语法树上符号的语义,这限制了我们的检查能力,比如我们无法判断符号的类型,两个符号究竟是不是同一个对象等
通过启用类型解析, 可以获取编译器语义分析的结果,这让我们可以自定义一些更高级的检查。
而要获取类型与语义,当然要传入依赖的,也就是,比如项目中常常需要传入与
方式检测虽然快,但是需要手动传入,比较麻烦,尤其是有时候自定义规则需要解析我们自己的类而不是中的类时,那么就需要将项目中的代码的编译结果传入作为了,这样就更麻烦了
同样支持插件方式接入,这种方式不需要我们另外再配置,我们可以将命令行方式与方式结合起来,在本地通过方式快速检测,在上通过插件进行完整的检测
接入步骤
如上所示,接入主要需要做这么几件事:
- 引入插件
- 配置插件,主要是配置与,即规则开关与老代码过滤
- 引入与自定义规则的依赖
- 配置,用于类型解析,但不用再配置了。
- 除了之外,也可以通过与的方式指定只扫描指定文件的方式来实现增量检测
通过以上方式就接入成功了,运行就可以开始检测了,扫描结果可在终端直接查看,并可以直接定位到问题代码处,也可以在路径下查看输出的报告文件:
要落地自己制定的代码规范,不可避免的需要自定义规则,当然我们首先要看下自带的规则,是否已经有我们需要的,只需把开关打开即可.
自带规则
自带的规则都可以通过开关配置,如果没有在 闭包中指定 属性, 会使用默认的规则。这些规则采用 文件描述,运行 会生成 文件,我们可以在这个文件的基础上制定代码规范准则。
中的每条规则形如:
更多关于配置文件的修改方式,请参考官方文档-配置文件
的规则集划分为 9 个大类,每个大类下有具体的规则:
更细节的规则说明,请参考:官方文档-规则集说明
自定义规则
接下来我们自定义一个检测使用的规则,如下所示:
代码其实并不复杂,主要做了这么几件事:
- 添加作为自定义规则的入口,并将添加进去
- 实现类,主要包括与各种方法
- 属性用于定义在控制台或任何其他输出格式上打印的、严重性和提示信息
- 即通过访问者模式访问语法树的回调,当访问到时会回调,我们在这里检测有没有添加,发现存在则报告异常
支持类型解析的自定义规则
上面的规则没有用到类型解析,也就是说不传入也能使用,我们现在来看一个需要使用类型解析的自定义规则
比如我们需要在项目中禁止直接使用,而是使用我们统一封装的工具类,那么我们可以自定义如下规则:
可以看出,我们在回调中检测表达式,我们不仅需要判断是否存在表达式,因为可能存在同名类,更需要判断类的具体类型,而这就需要获取语义信息
我们这里通过来获取表达式的语义,这里的其实就是编译器存储语义信息的表,详细的可以参阅:K2 编译器是什么?世界第二高峰又是哪座?
当我们获取了语义信息之后,就可以获取的具体类型,就可以判断出这个是不是,也就可以完成检测了
在完成了接入与自定义规则之后,接下来就是每次提交代码时在上进行检测了
一些大的开源项目每次提交都会进行一系列的检测,我们也用来实现一个
我们在目录添加如下代码
这样在每次提交的时候,就都会自动调用该进行检测了,检测不通过则不允许合并,如下所示:
点进去也可以看到详细的报错,具体是哪一行代码检测不通过,如图所示:
本文主要介绍了的接入与如何自定义规则,通过集成,命令行方式与插件方式接入,以及自动检测,可以保证代码规范,提示,检测三者的统一,方便提前暴露问题,提高代码质量。
如果本文对你有所帮助,欢迎点赞~
示例代码
本文所有代码可见:github.com/RicardoJian…
参考资料
detekt.dev/docs/intro
代码质量堪忧?用 detekt 呀,拿捏得死死的~
作者:程序员江同学
链接:https://juejin.cn/post/7152886037746827277
- 使用 Kotlin 进行服务器端开发
- 使用 Kotlin 进行 Android 开发
- Kotlin JavaScript 概述
- Kotlin/Native 用于原生开发
- 用于异步编程等场景的协程
- Kotlin 1.1 的新特性
- Kotlin 1.2 的新特性
- Kotlin 1.3 的新特性
- 基本语法
- 习惯用法
- 编码规范
- 基本类型
- 包
- 控制流:if、when、for、while
- 返回和跳转
- 类与继承
- 属性与字段
- 接口
- 可见性修饰符
- 扩展
- 数据类
- 密封类
- 泛型
- 嵌套类与内部类
- 枚举类
- 对象表达式与对象声明
- Inline classes
- 委托
- 函数
- 高阶函数与 lambda 表达式
- 内联函数
- 解构声明
- 集合:List、Set、Map
- 区间
- 类型的检查与转换“is”与“as”
- This 表达式
- 相等性
- 操作符重载
- 空安全
- 异常
- 注解
- 反射
- 类型安全的构建器
- 类型别名
- 多平台程序设计
- 关键字与操作符
- 在 Kotlin 中调用 Java 代码
- Java 中调用 Kotlin
- JavaScript 动态类型
- Kotlin 中调用 JavaScript
- JavaScript 中调用 Kotlin
- JavaScript 模块
- JavaScript 反射
- JavaScript DCE
- 协程基础
- 取消与超时
- 通道 (实验性的)
- 组合挂起函数
- 协程上下文与调度器
- 异常处理
- select 表达式(实验性的)
- 共享的可变状态与并发
- 编写 Kotlin 代码文档
- Kotlin 注解处理
- 使用 Gradle
- 使用 Maven
- 使用 Ant
- Kotlin 与 OSGi
- 编译器插件
- 不同组件的稳定性
- FAQ
- 与 Java 语言比较
- 与 Scala 比较【官方已删除】
- Kotlin 概述
- Kotlin 与 Java 比较
- 巧用 Android Studio
- 认识 Kotlin 基本类型
- 走进 Kotlin 的数组
- 走进 Kotlin 的集合
- 完整代码
- 基础语法
- 方法入参是常量,不可修改
- 不要 Companion、INSTANCE?
- Java 重载,在 Kotlin 中怎么巧妙过渡一下?
- Kotlin 中的判空姿势
- Kotlin 复写 Java 父类中的方法
- Kotlin “狠”起来,连TODO都不放过!
- is、as` 中的坑
- Kotlin 中的 Property 的理解
- also 关键字
- takeIf 关键字
- 单例模式的写法
- 从一个膜拜大神的 Demo 开始
- Kotlin 写 Gradle 脚本是一种什么体验?
- Kotlin 编程的三重境界
- Kotlin 高阶函数
- Kotlin 泛型
- Kotlin 扩展
- Kotlin 委托
- 协程“不为人知”的调试技巧
- 图解协程:suspend