KSP 快速入門指南
//: # (description: 將基於 Kotlin Symbol Processing (KSP) 的註解處理器新增到你的專案,或使用 KSP API 建立你自己的處理器。)
在本指南中,你將學習:
- 如何將基於 KSP 的註解處理器新增到你的專案。
- 如何使用 KSP API 建立你自己的註解處理器。
- 在哪裡可以找到處理器產生的程式碼。
將基於 KSP 的處理器新增到你的專案
若要在你的專案中使用外部處理器,請將 KSP 新增到 build.gradle(.kts) 檔案中的 plugins {} 區塊。如果僅在特定模組中需要該處理器,請改為將其新增到該模組的 build.gradle(.kts) 檔案中:
// build.gradle.kts
plugins {
kotlin("jvm") version "2.3.0"
id("com.google.devtools.ksp") version "2.3.3"
}// build.gradle
plugins {
id 'org.jetbrains.kotlin.jvm' version '2.3.0'
id 'com.google.devtools.ksp' version '2.3.3'
}若要尋找 KSP 的最新版本,請查看 GitHub Releases。
在頂層 dependencies {} 區塊中,新增你要使用的處理器。本範例使用 Moshi,但其他處理器的處理方式相同:
// build.gradle.kts
dependencies {
ksp("com.squareup.moshi:moshi-kotlin-codegen:1.15.2")
}// build.gradle
dependencies {
ksp 'com.squareup.moshi:moshi-kotlin-codegen:1.15.2'
}建立你自己的處理器
透過以下步驟,你將建立一個簡單的註解處理器,用以產生 helloWorld() 函式。雖然這在實踐中沒什麼用,但它展示了建立你自己的處理器和註解的基礎知識。
將 KSP 新增到專案
建立一個新的 Kotlin 專案並新增 KSP 外掛程式:
在 IntelliJ IDEA 中,選擇 File | New | Project。
在左側清單中,選擇 Kotlin。
選擇 Gradle 作為建置系統,然後點擊 Create。

將 KSP 外掛程式新增到
build.gradle(.kts)檔案中:kotlin// build.gradle.kts plugins { kotlin("jvm") version "2.3.0" id("com.google.devtools.ksp") version "2.3.3" apply false }groovy// build.gradle plugins { id 'org.jetbrains.kotlin.jvm' version '2.3.0' id 'com.google.devtools.ksp' version '2.3.3' apply false }
建立一個註解
在專案根目錄建立一個新模組並宣告一個註解:
選擇 File | New | Module。
在左側清單中,選擇 Kotlin。
指定以下欄位並點擊 create:
- Name:annotations
- Build system:Gradle

在該模組中,建立
HelloWorldAnnotation.kt檔案並宣告一個名為HelloWorldAnnotation的註解:kotlin// annotations/src/main/kotlin/com/example/annotations/HelloWorldAnnotation.kt package com.example.annotations annotation class HelloWorldAnnotation
建立並註冊處理器
在專案根目錄建立另一個名為 processor 的模組。
在該模組的
build.gradle(.kts)檔案中,將 KSP API 和你宣告的註解新增為相依性:kotlin// processor/build.gradle.kts plugins { kotlin("jvm") } dependencies { implementation(project(":annotations")) implementation("com.google.devtools.ksp:symbol-processing-api:2.3.6") }groovy// 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檔案並新增以下程式碼:kotlin// 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 建議的匯入內容。請確保從
com.google.devtools.ksp.processing匯入Resolver和Dependencies類別。或者,將以下幾行複製到HelloWorldProcessor.kt的頂部:kotlin// 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️⃣ 處理器使用訪問者遍歷 KSP 的 Kotlin 抽象語法樹 (AST) 檢視。在
HelloWorldProcessor類別中,HelloWorldVisitor類別即為訪問者。由於HelloWorldAnnotation僅用於函式,因此僅覆寫了visitFunctionDeclaration()。KSVisitorVoid是 KSP 提供的訪問者類別之一,你可以對其進行覆寫和調整。你也可以透過實作KSVisitor<D, R>介面 來建立自己的訪問者。3️⃣
createNewFileFrom()會建立 KSP 產生程式碼的檔案。createDependencyOn()使輸出檔案相依於使用該註解的原始碼檔案。若要進一步了解 KSP 如何建立和管理檔案,請造訪
CodeGenerator介面 的原始碼。
建立
HelloWorldProcessorProvider.kt檔案。在其中宣告一個繼承自SymbolProcessorProvider的HelloWorldProcessorProvider類別:kotlin// 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) } }註冊處理器提供者。在
resources/META-INF/services目錄中,建立一個com.google.devtools.ksp.processing.SymbolProcessorProvider檔案,並新增提供者的完全限定名稱:text## processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider HelloWorldProcessorProvider
使用你的處理器
現在你已準備好測試你的處理器。按照以下步驟建立一個用戶端模組,並讓你的處理器根據被標註的元素產生程式碼:
在專案根目錄建立一個名為
app的模組。在該模組的
build.gradle(.kts)檔案中:- 將 KSP 外掛程式新增到
plugins {}區塊。 - 將你的處理器和註解新增到
dependencies {}區塊。
例如:
kotlin// app/build.gradle.kts plugins { kotlin("jvm") id("com.google.devtools.ksp") } dependencies { implementation(project(":annotations")) ksp(project(":processor")) }groovy// app/build.gradle plugins { id 'com.google.devtools.ksp' } dependencies { implementation project (':annotations') ksp project (':processor') }- 將 KSP 外掛程式新增到
在專案層級的
settings.gradle(.kts)檔案中,確保所有子模組都已自動包含:kotlin// settings.gradle.kts include("annotations") include("app") include("processor")groovy// settings.gradle include 'processor' include 'annotations' include 'app'在
app模組中,建立一個Main.kt檔案並新增以下程式碼:kotlin// app/src/main/kotlin/Main.kt import com.example.annotations.HelloWorldAnnotation @HelloWorldAnnotation fun main() { helloWorld() }main()函式會呼叫helloWorld(),即使此函式尚不存在。你的 IDE 會將helloWorld()標記為未定義的參考。這是預期的:當你建置並執行專案時,KSP 會產生helloWorld()函式。執行程式。你將在主控台中看到
helloWorld()函式的輸出:textHello world from function generated by KSPKSP 會在
GeneratedHelloWorld.kt檔案中產生程式碼:textapp/build/generated/ksp/main/kotlin/GeneratedHelloWorld.kt
探索專案結構
你專案的最終檔案結構應如下所示:
.
├── app
│ ├── build.gradle.kts
│ └── src
│ └── main
│ └── kotlin
│ └── Main.kt
├── annotations
│ ├── build.gradle.kts
│ └── src
│ └── main
│ └── kotlin
| └── com
| └── example
| └── annotations
| └── HelloWorldAnnotation.kt
├── processor
│ ├── build.gradle.kts
│ └── src
│ └── main
│ ├── kotlin
│ │ ├── HelloWorldProcessor.kt
│ │ └── HelloWorldProcessorProvider.kt
│ └── resources/META-INF/services
| └── com.google.devtools.ksp.processing.SymbolProcessorProvider
├── build.gradle.kts
└── settings.gradle.kts你可能還有其他的檔案和目錄。
下一步
- 在 KSP 存儲庫 中探索此範例的完整程式碼。
- 在 KSP 存儲庫 中尋找更複雜的實際範例。
- 瀏覽 KSP 支援的程式庫 清單。
