KSP 如何模型化 Kotlin 程式碼
你可以在 KSP GitHub 儲存庫 找到 API 定義。 此圖表概述了 Kotlin 在 KSP 中是如何被模型化的:
型別與解析
解析會耗費底層 API 實作的大部分成本。因此,型別引用被設計為由處理器明確地解析(少數例外)。當一個 型別 (例如 KSFunctionDeclaration.returnType 或 KSAnnotation.annotationType) 被引用時,它總是一個 KSTypeReference,後者是一個帶有 annotations 和 modifiers 的 KSReferenceElement。
interface KSFunctionDeclaration : ... {
val returnType: KSTypeReference?
// ...
}
interface KSTypeReference : KSAnnotated, KSModifierListOwner {
val type: KSReferenceElement
}一個 KSTypeReference 可以被解析為一個 KSType,後者指的是 Kotlin 型別系統中的一個型別。
一個 KSTypeReference 具有一個 KSReferenceElement,它模型化了 Kotlin 的程式結構:即引用是如何被撰寫的。它對應於 Kotlin 語法中的 type 元素。
一個 KSReferenceElement 可以是一個 KSClassifierReference 或 KSCallableReference,它們包含了許多有用的資訊,而無需解析。例如,KSClassifierReference 具有 referencedName,而 KSCallableReference 具有 receiverType、functionArguments 和 returnType。
如果需要 KSTypeReference 所引用的原始宣告,通常可以透過解析為 KSType 並透過 KSType.declaration 存取來找到它。從型別被提及的地方轉移到其類別被定義的地方,看起來像這樣:
val ksType: KSType = ksTypeReference.resolve()
val ksDeclaration: KSDeclaration = ksType.declaration型別解析代價高昂,因此具有明確的形式。一些從解析中獲取的資訊已在 KSReferenceElement 中可用。例如,KSClassifierReference.referencedName 可以過濾掉許多不相關的元素。你只應在需要從 KSDeclaration 或 KSType 獲取特定資訊時才解析型別。
指向函式型別的 KSTypeReference 大部分資訊都在其元素中。儘管它可以被解析為 Function0、Function1 等家族,但這些解析不會帶來比 KSCallableReference 更多的資訊。解析函式型別引用的一個用例是處理函式原型的識別。
