メインコンテンツまでスキップ

KSPはKotlinコードをどのようにモデル化するか

KSP GitHubリポジトリでAPI定義を確認できます。 以下の図は、KotlinがKSPでどのようにモデル化されているかの概要を示しています。

class diagram

型と解決

解決(resolution)は、基盤となるAPI実装のコストの大部分を占めます。そのため、型参照は、(いくつかの例外を除き)プロセッサによって明示的に解決されるように設計されています。KSFunctionDeclaration.returnTypeKSAnnotation.annotationTypeのような_型_が参照される場合、それは常にKSTypeReferenceであり、これはアノテーションと修飾子を持つKSReferenceElementです。

interface KSFunctionDeclaration : ... {
val returnType: KSTypeReference?
// ...
}

interface KSTypeReference : KSAnnotated, KSModifierListOwner {
val type: KSReferenceElement
}

KSTypeReferenceKSTypeに解決(resolve)でき、これはKotlinの型システムにおける型を参照します。

KSTypeReferenceKSReferenceElementを持っており、これはKotlinのプログラム構造、すなわち参照がどのように記述されているかをモデル化します。これはKotlinの文法におけるtype要素に対応します。

KSReferenceElementKSClassifierReferenceまたはKSCallableReferenceになることができ、これらは解決を必要とせずに多くの有用な情報を含んでいます。例えば、KSClassifierReferencereferencedNameを持ち、KSCallableReferencereceiverTypefunctionArguments、およびreturnTypeを持ちます。

KSTypeReferenceによって参照される元の宣言が必要な場合、通常はKSTypeに解決し、KSType.declarationを通じてアクセスすることで見つけることができます。型が言及されている場所から、そのクラスが定義されている場所に移動する様子は次のようになります。

val ksType: KSType = ksTypeReference.resolve()
val ksDeclaration: KSDeclaration = ksType.declaration

型解決はコストがかかるため、明示的な形式をとります。解決から得られる情報の一部は、すでにKSReferenceElementで利用可能です。例えば、KSClassifierReference.referencedNameは、関心のない多くの要素をフィルタリングできます。KSDeclarationまたはKSTypeからの特定の情報が必要な場合にのみ、型を解決する必要があります。

関数型を指すKSTypeReferenceは、その要素にほとんどの情報を持っています。 Function0Function1などのファミリーに解決できますが、これらの解決はKSCallableReference以上の情報をもたらしません。関数型参照を解決するユースケースの1つは、関数のプロトタイプのアイデンティティを扱うことです。