Skip to content

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 的外掛視為 符號處理器,或簡稱 處理器,編譯中的資料流可以描述為以下步驟:

  1. 處理器讀取並分析原始程式和資源。
  2. 處理器生成程式碼或其他形式的輸出。
  3. Kotlin 編譯器將原始程式與生成的程式碼一起編譯。

與成熟的編譯器外掛不同,處理器不能修改程式碼。 改變語言語義的編譯器外掛有時會非常令人困惑。 KSP 通過將原始程式視為唯讀來避免這種情況。

您也可以在這段影片中獲得 KSP 的概述:

KSP 如何看待原始檔

大多數處理器會導航輸入原始碼的各種程式結構。 在深入了解 API 的用法之前,讓我們先看看一個檔案從 KSP 的角度來看可能長什麼樣:

text
KSFile
  packageName: KSName
  fileName: String
  annotations: List<KSAnnotation>  (File annotations)
  declarations: List<KSDeclaration>
    KSClassDeclaration // class, interface, object
      simpleName: KSName
      qualifiedName: KSName
      containingFile: String
      typeParameters: KSTypeParameter
      parentDeclaration: KSDeclaration
      classKind: ClassKind
      primaryConstructor: KSFunctionDeclaration
      superTypes: List<KSTypeReference>
      // contains inner classes, member functions, properties, etc.
      declarations: List<KSDeclaration>
    KSFunctionDeclaration // top level function
      simpleName: KSName
      qualifiedName: KSName
      containingFile: String
      typeParameters: KSTypeParameter
      parentDeclaration: KSDeclaration
      functionKind: FunctionKind
      extensionReceiver: KSTypeReference?
      returnType: KSTypeReference
      parameters: List<KSValueParameter>
      // contains local classes, local functions, local variables, etc.
      declarations: List<KSDeclaration>
    KSPropertyDeclaration // global variable
      simpleName: KSName
      qualifiedName: KSName
      containingFile: String
      typeParameters: KSTypeParameter
      parentDeclaration: KSDeclaration
      extensionReceiver: KSTypeReference?
      type: KSTypeReference
      getter: KSPropertyGetter
        returnType: KSTypeReference
      setter: KSPropertySetter
        parameter: KSValueParameter

此視圖列出了檔案中宣告的常見內容:類別、函數、屬性等等。

SymbolProcessorProvider:入口點

KSP 期望 SymbolProcessorProvider 介面的實作來實例化 SymbolProcessor

kotlin
interface SymbolProcessorProvider {
    fun create(environment: SymbolProcessorEnvironment): SymbolProcessor
}

SymbolProcessor 定義為:

kotlin
interface SymbolProcessor {
    fun process(resolver: Resolver): List<KSAnnotated> // Let's focus on this
    fun finish() {}
    fun onError() {}
}

ResolverSymbolProcessor 提供對編譯器細節(例如符號)的存取。 一個尋找所有頂層函數和頂層類別中非局部函數的處理器可能看起來像 以下這樣:

kotlin
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 支援
DaggerAlpha
MotifAlpha
Hilt進行中
Auto Factory尚不支援