Kotlin 符号处理 API
Kotlin 符号处理 (KSP) 是一个可用于开发轻量级编译器插件的 API。 KSP 提供了一个简化的编译器插件 API,它充分利用 Kotlin 的强大功能,同时最大限度地降低了学习曲线。与 kapt 相比,使用 KSP 的注解处理器运行速度可快达两倍。
概述
KSP API 以惯用的方式处理 Kotlin 程序。KSP 理解 Kotlin 特有特性,例如扩展函数、声明处型变和局部函数。它还显式地建模类型,并提供基本的类型检测,例如等价性和赋值兼容性。
该 API 在符号层面根据 Kotlin 语法 对 Kotlin 程序结构进行建模。当基于 KSP 的插件处理源程序时,诸如类、类成员、函数和相关参数之类的构造可供处理器访问,而诸如 if
代码块和 for
循环之类的则不可访问。
从概念上讲,KSP 与 Kotlin 反射中的 KType 相似。 该 API 允许处理器从类声明导航到具有特定类型实参的相应类型,反之亦然。你还可以替换类型实参、指定型变、应用星型投影并标记类型的可空性。
考虑 KSP 的另一种方式是将其视为 Kotlin 程序的预处理器框架。通过将基于 KSP 的插件视为 符号处理器,或简称为 处理器,编译过程中的数据流可以按以下步骤描述:
- 处理器读取并分析源程序和资源。
- 处理器生成代码或其他形式的输出。
- Kotlin 编译器将源程序与生成的代码一起编译。
与功能完备的编译器插件不同,处理器不能修改代码。 改变语言语义的编译器插件有时会让人非常困惑。 KSP 通过将源程序视为只读来避免这种情况。
你还可以通过此视频了解 KSP 概览:
KSP 如何看待源文件
大多数处理器会遍历输入源代码的各种程序结构。 在深入了解 API 的用法之前,让我们看看文件从 KSP 的视角看是怎样的:
KSFile
packageName: KSName // 包名
fileName: String // 文件名
annotations: List<KSAnnotation> // 注解 (文件注解)
declarations: List<KSDeclaration> // 声明
KSClassDeclaration // 类、接口、对象
simpleName: KSName // 简单名称
qualifiedName: KSName // 限定名称
containingFile: String // 所在文件
typeParameters: KSTypeParameter // 类型形参
parentDeclaration: KSDeclaration// 父声明
classKind: ClassKind // 类类型
primaryConstructor: KSFunctionDeclaration // 主构造函数
superTypes: List<KSTypeReference> // 父类型
// 包含内部类、成员函数、属性等
declarations: List<KSDeclaration> // 声明
KSFunctionDeclaration // 顶层函数
simpleName: KSName // 简单名称
qualifiedName: KSName // 限定名称
containingFile: String // 所在文件
typeParameters: KSTypeParameter // 类型形参
parentDeclaration: KSDeclaration// 父声明
functionKind: FunctionKind // 函数类型
extensionReceiver: KSTypeReference? // 扩展接收者
returnType: KSTypeReference // 返回类型
parameters: List<KSValueParameter> // 形参
// 包含局部类、局部函数、局部变量等
declarations: List<KSDeclaration> // 声明
KSPropertyDeclaration // 全局变量
simpleName: KSName // 简单名称
qualifiedName: KSName // 限定名称
containingFile: String // 所在文件
typeParameters: KSTypeParameter // 类型形参
parentDeclaration: KSDeclaration// 父声明
extensionReceiver: KSTypeReference? // 扩展接收者
type: KSTypeReference // 类型
getter: KSPropertyGetter // getter
returnType: KSTypeReference // 返回类型
setter: KSPropertySetter // setter
parameter: KSValueParameter // 形参
此视图列出了文件中声明的常见内容:类、函数、属性等。
SymbolProcessorProvider:入口点
KSP 需要 SymbolProcessorProvider
接口的实现来实例化 SymbolProcessor
:
interface SymbolProcessorProvider {
fun create(environment: SymbolProcessorEnvironment): SymbolProcessor
}
而 SymbolProcessor
的定义如下:
interface SymbolProcessor {
fun process(resolver: Resolver): List<KSAnnotated> // 让我们关注这里
fun finish() {}
fun onError() {}
}
Resolver
为 SymbolProcessor
提供访问编译器详细信息(例如符号)的能力。 一个查找所有顶层函数和顶层类中非局部函数的处理器可能如下所示:
class HelloFunctionFinderProcessor : SymbolProcessor() {
// ...
val functions = mutableListOf<KSClassDeclaration>()
val visitor = FindFunctionsVisitor()
override fun process(resolver: Resolver) {
resolver.getAllFiles().forEach { it.accept(visitor, Unit) }
}
inner class FindFunctionsVisitor : KSVisitorVoid() {
override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
classDeclaration.getDeclaredFunctions().forEach { it.accept(this, Unit) }
}
override fun visitFunctionDeclaration(function: KSFunctionDeclaration, data: Unit) {
functions.add(function)
}
override fun visitFile(file: KSFile, data: Unit) {
file.declarations.forEach { it.accept(this, Unit) }
}
}
// ...
class Provider : SymbolProcessorProvider {
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor = TODO()
}
}
资源
支持的库
下表列出了 Android 上一些常用库及其对 KSP 的支持阶段:
库 | 状态 |
---|---|
Room | 官方支持 |
Moshi | 官方支持 |
RxHttp | 官方支持 |
Kotshi | 官方支持 |
Lyricist | 官方支持 |
Lich SavedState | 官方支持 |
gRPC Dekorator | 官方支持 |
EasyAdapter | 官方支持 |
Koin Annotations | 官方支持 |
Glide | 官方支持 |
Micronaut | 官方支持 |
Epoxy | 官方支持 |
Paris | 官方支持 |
Auto Dagger | 官方支持 |
SealedX | 官方支持 |
Ktorfit | 官方支持 |
Mockative | 官方支持 |
DeeplinkDispatch | 通过 airbnb/DeepLinkDispatch#323 支持 |
Dagger | Alpha |
Motif | Alpha |
Hilt | 开发中 |
Auto Factory | 暂不支持 |