KSPにおけるKotlinコードのモデル化
API定義は、KSP GitHubリポジトリで確認できます。 この図は、KSPでKotlinがどのようにモデル化されるかの概要を示しています。
型と解決
解決処理は、基盤となるAPI実装において最もコストがかかります。そのため、型参照はプロセッサによって明示的に解決されるように設計されています(いくつかの例外を除いて)。KSFunctionDeclaration.returnType
や KSAnnotation.annotationType
のような 型 が参照される場合、それは常に KSTypeReference
であり、アノテーションと修飾子を持つ 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
よりも多くの情報をもたらしません。関数型参照を解決するユースケースの1つは、関数のプロトタイプ(prototype)の同一性を扱うことです。