程序静态分析
本文为《深入实践 kotlin 元编程》读书笔记,想要深入了解 kotlin 元编程的同学可以阅读原书。
程序静态分析(Program Static Analysis)是指在不运行代码的方式下,通过词法分析、语法分析、控制流分析、数据流分析等技术对程序代码进行扫描,验证代码是否满足规范性、 安全性、可靠性、可维护性等指标的一种代码分析技术。
使用 Kotlin 编译器做语义分析
需要获取语义分析的结果,就不得不借助编译器了。
编译器的加持下,想要做目标程序的静态分析思路上并不复杂。不过,想要轻松实现这样的功能需要对编译器的各种类型有相对清晰的认识。
由于文档较为缺乏,初学者通常在处理语法结构时容易对以下几种类型的作用和使用方法产生疑惑,主要包括:
- 类名形如 Kt*,例如 KtFile、KtClass,是对 Kotlin 语法树的描述,我们完全可以把它们当做结构化的源码本身来看待。实际上,Kt 类型正是 PSI 的 Kotlin 实现。
- 类名形如 **Descriptor,例如 ClassDescriptor,是对 Kotlin 语法的描述。语法树解析之后,编译器会为不同类型的语法节点关联相应的语法描述类。
- KotlinType 及其子类,是对 Kotlin 类型的描述。
简单来说,如果你希望分析目标程序当中的程序结构信息,使用 Kt 来访问语法树;如果你希望分析目标程序的语法信息,使用 Descritpor 类型;如果想要获取 Kotlin 的类 型信息,则使用 KotlinType。
通常情况下,我们的分析工作都是从语法树出发,使用 BindingContext 来获取语法信息和类型信息,进而得出分析的结果。
使用 Detekt 做静态扫描
在实际项目当中,我们通常会使用成熟的静态分析框架来完成代码扫描和分析的需求。业内最为著名的 Kotlin 代码扫描框架就是 detekt 和 ktlint。其中:
- detekt 支持非常灵活的配置,也支持实现自定义的扫描规则。
- ktlint 则主要基于官方的代码风格做检查。
对于有自定义需求的我们而言,detekt 显然更具优势。detekt 除了内置了诸多代码风格、代码质量相关的检查以外,还支持实现自定义扫描规则。
小结
本章以扫描项目当中的数据类为背景,展开了对 Kotlin 代码静态扫描的探讨。随着需求复杂度的提升,先后基于文本分析(正则表达式)、语法分析(Antlr)、语义分析(编译器) 三个层次来实现代码扫描。
之后还介绍了如何基于 detekt 以及 IntelliJ 的代码检查和快捷修复等功能来实现对代码的扫描和分析。