KSP 入门
在这篇指南中, 你将学习:
如何向你的项目添加基于 KSP 的注解处理器.
如何使用 KSP API 创建你自己的注解处理器.
在哪里查找处理器生成的代码.
向你的项目添加基于 KSP 的处理器
要在你的项目中使用外部处理器, 请在 build.gradle(.kts) 文件的 plugins {} 代码块 中添加 KSP. 如果只有某个特定模块需要这个处理器, 请改为在该模块的 build.gradle(.kts) 文件中添加:
在最顶层的 dependencies {} 代码块中, 添加你想要使用的处理器. 这个示例使用 Moshi, 其他处理器的添加方式也是一样的:
创建你自己的处理器
按照以下步骤, 你将创建一个简单的注解处理器, 它会生成一个 helloWorld() 函数. 虽然在实际中用处不大, 但它演示了创建你自己的处理器和注解的基本方法.
向项目添加 KSP
创建一个新的 Kotlin 项目, 并添加 KSP plugin:
在 IntelliJ IDEA 中, 选择 File | New | Project.
在左侧列表中, 选择 Kotlin.
选择 Gradle 作为构建系统, 然后点击 Create.

向
build.gradle(.kts)文件添加 KSP plugin:// build.gradle.kts plugins { kotlin("jvm") version "2.4.0" id("com.google.devtools.ksp") version "2.3.9" apply false }// build.gradle plugins { id 'org.jetbrains.kotlin.jvm' version '2.4.0' id 'com.google.devtools.ksp' version '2.3.9' apply false }
创建注解
在项目的根目录创建一个新模块, 并声明一个注解:
选择 File | New | Module.
在左侧列表中, 选择 Kotlin.
填写以下项目, 然后点击 create:
Name: annotations
Build system: Gradle

在这个模块中, 创建
HelloWorldAnnotation.kt文件, 并声明一个注解, 名为HelloWorldAnnotation:// annotations/src/main/kotlin/com/example/annotations/HelloWorldAnnotation.kt package com.example.annotations annotation class HelloWorldAnnotation
创建并注册处理器
在项目的根目录创建另一个模块, 名为 processor.
在这个模块的
build.gradle(.kts)文件中, 将 KSP API 和你声明的注解添加为依赖项:// processor/build.gradle.kts plugins { kotlin("jvm") } dependencies { implementation(project(":annotations")) implementation("com.google.devtools.ksp:symbol-processing-api:2.3.6") }// processor/build.gradle plugins { id 'org.jetbrains.kotlin.jvm' } dependencies { implementation project ':annotations' implementation 'com.google.devtools.ksp:symbol-processing-api:2.3.6' }在
processor模块中, 创建一个新的HelloWorldProcessor.kt文件, 添加以下代码:// processor/src/main/kotlin/HelloWorldProcessor.kt class HelloWorldProcessor(val codeGenerator: CodeGenerator) : SymbolProcessor { // 1️⃣ process() 函数 override fun process(resolver: Resolver): List<KSAnnotated> { resolver .getSymbolsWithAnnotation("com.example.annotations.HelloWorldAnnotation") .filter { it.validate() } .filterIsInstance<KSFunctionDeclaration>() .forEach { it.accept(HelloWorldVisitor(), Unit) } return emptyList() } // 2️⃣ 访问器(Visitor) inner class HelloWorldVisitor : KSVisitorVoid() { override fun visitFunctionDeclaration(function: KSFunctionDeclaration, data: Unit) { createNewFileFrom(function).use { file -> file.write( """ fun helloWorld(): Unit { println("Hello world from function generated by KSP") } """.trimIndent() ) } } } // 3️⃣ createNewFileFrom() 函数 private fun createNewFileFrom(function: KSFunctionDeclaration): OutputStream { return codeGenerator.createNewFile( dependencies = createDependencyOn(function), packageName = "", fileName = "GeneratedHelloWorld" ) } // 3️⃣ createDependencyOn() 函数 private fun createDependencyOn(function: KSFunctionDeclaration): Dependencies { return Dependencies(aggregating = false, function.containingFile!!) } } // 工具函数, 用于将字符串写入 OutputStream fun OutputStream.write(string: String): Unit { this.write(string.toByteArray()) }添加 IDE 建议的 import 语句. 请确保从
com.google.devtools.ksp.processing导入Resolver和Dependencies类. 或者, 将以下代码复制到HelloWorldProcessor.kt的顶部:// processor/src/main/kotlin/HelloWorldProcessor.kt import com.google.devtools.ksp.processing.CodeGenerator import com.google.devtools.ksp.processing.Dependencies import com.google.devtools.ksp.processing.Resolver import com.google.devtools.ksp.processing.SymbolProcessor import com.google.devtools.ksp.symbol.KSAnnotated import com.google.devtools.ksp.symbol.KSFunctionDeclaration import com.google.devtools.ksp.symbol.KSVisitorVoid import com.google.devtools.ksp.validate import java.io.OutputStream我们来逐步了解这段代码:
1️⃣
process()函数包含处理器的主逻辑. 它获取所有带有HelloWorldAnnotation注解的符号, 并为每个符号调用HelloWorldVisitor.process()函数返回未处理的符号列表, 以便在后续轮次中进行处理. 在这个示例中, 它安全地返回emptyList(). 详情请参见 多轮处理.2️⃣ 处理器使用访问器(Visitor)遍历 KSP 对 Kotlin 抽象语法树 (Abstract Syntax Tree, AST) 的视图. 在
HelloWorldPocessor类中,HelloWorldVisitor类是访问器(Visitor). 由于HelloWorldAnnotation只用于函数, 因此只覆盖了visitFunctionDeclaration().3️⃣
createNewFileFrom()创建 KSP 生成代码的文件.createDependencyOn()使输出的文件依赖于使用注解的源代码文件.
创建
HelloWorldProcessorProvider.kt文件. 在这个文件中, 声明一个HelloWorldProcessorProvider类, 继承自SymbolProcessorProvider:// processor/src/main/kotlin/HelloWorldProcessorProvider.kt import com.google.devtools.ksp.processing.SymbolProcessor import com.google.devtools.ksp.processing.SymbolProcessorEnvironment import com.google.devtools.ksp.processing.SymbolProcessorProvider class HelloWorldProcessorProvider : SymbolProcessorProvider { override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor { return HelloWorldProcessor(environment.codeGenerator) } }注册处理器 Provider. 在
resources/META-INF/services目录中, 创建com.google.devtools.ksp.processing.SymbolProcessorProvider文件, 并添加 Provider 的完全限定名称:## processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider HelloWorldProcessorProvider
使用你的处理器
现在你已经准备好, 可以测试你的处理器了. 按照以下步骤创建客户端模块, 让你的处理器根据带有注解的元素生成代码:
在项目根目录创建一个模块, 名为
app.在这个模块的
build.gradle(.kts)文件中:在
plugins {}代码块中, 添加 KSP 插件.在
dependencies {}代码块中, 添加你的处理器和注解.
例如:
// app/build.gradle.kts plugins { kotlin("jvm") id("com.google.devtools.ksp") } dependencies { implementation(project(":annotations")) ksp(project(":processor")) }// app/build.gradle plugins { id 'com.google.devtools.ksp' } dependencies { implementation project (':annotations') ksp project (':processor') }在项目级的
settings.gradle(.kts)文件中, 确认所有子模块都已自动包含:// settings.gradle.kts include("annotations") include("app") include("processor")// settings.gradle include 'processor' include 'annotations' include 'app'在
app模块中, 创建Main.kt文件, 添加以下代码:// app/src/main/kotlin/Main.kt import com.example.annotations.HelloWorldAnnotation @HelloWorldAnnotation fun main() { helloWorld() }运行程序. 你会在控制台中看到
helloWorld()函数的输出:Hello world from function generated by KSPKSP 在
GeneratedHelloWorld.kt文件中生成代码:app/build/generated/ksp/main/kotlin/GeneratedHelloWorld.kt
查看项目结构
你的项目的最终文件结构应该如下所示: