KotlinシンボルプロセッシングAPI
Kotlin Symbol Processing (KSP) は、軽量なコンパイラプラグインを開発するために使用できるAPIです。 KSPは、Kotlinの能力を活用しつつ学習曲線を最小限に抑える、簡素化されたコンパイラプラグインAPIを提供します。 kaptと比較して、KSPを使用するアノテーションプロセッサは最大2倍高速に実行できます。
- KSPがkaptと比較してどうかを詳しく知るには、KSPを使用する理由をご覧ください。
- KSPプロセッサの記述を始めるには、KSPクイックスタートをご覧ください。
概要
KSP APIは、Kotlinプログラムを慣用的に処理します。KSPは、拡張関数、宣言サイトの分散(declaration-site variance)、ローカル関数など、Kotlin固有の機能を理解します。 また、型を明示的にモデル化し、等価性や代入互換性などの基本的な型チェックも提供します。
このAPIは、Kotlinの文法に従ってKotlinプログラムの構造をシンボルレベルでモデル化します。 KSPベースのプラグインがソースプログラムを処理する際、クラス、クラスメンバー、関数、および関連するパラメータのような構造がプロセッサからアクセス可能になりますが、if
ブロックやfor
ループのようなものはアクセスできません。
概念的には、KSPはKotlinリフレクションのKTypeに似ています。 このAPIにより、プロセッサはクラス宣言から特定の型引数を持つ対応する型へ、またその逆へのナビゲーションを可能にします。 また、型引数を置換し、分散を指定し、スタースプロジェクションを適用し、型のnull許容性をマークできます。
KSPをKotlinプログラムのプリプロセッサフレームワークと考えることもできます。KSPベースのプラグインを シンボルプロセッサ、または単に_プロセッサ_と見なすことで、コンパイルにおけるデータフローを次のステップで記述できます。
- プロセッサはソースプログラムとリソースを読み込み、分析します。
- プロセッサはコードやその他の形式の出力を生成します。
- Kotlinコンパイラは、ソースプログラムと生成されたコードを一緒にコンパイルします。
本格的なコンパイラプラグインとは異なり、プロセッサはコードを変更することはできません。 言語の意味を変更するコンパイラプラグインは、時に非常に混乱を招く可能性があります。 KSPは、ソースプログラムを読み取り専用として扱うことで、これを回避します。
KSPの概要は、こちらのビデオでも確認できます。
KSPがソースファイルをどのように見ているか
ほとんどのプロセッサは、入力ソースコードの様々なプログラム構造をナビゲートします。 APIの利用法に入る前に、KSPの視点からファイルがどのように見えるかを見てみましょう。
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は、SymbolProcessor
をインスタンス化するためにSymbolProcessorProvider
インターフェースの実装を期待します。
interface SymbolProcessorProvider {
fun create(environment: SymbolProcessorEnvironment): SymbolProcessor
}
一方、SymbolProcessor
は次のように定義されています。
interface SymbolProcessor {
fun process(resolver: Resolver): List<KSAnnotated> // Let's focus on this
fun finish() {}
fun onError() {}
}
Resolver
は、シンボルなどのコンパイラの詳細へのアクセスをSymbolProcessor
に提供します。 すべてのトップレベル関数と、トップレベルクラス内の非ローカル関数を見つけるプロセッサは、次のようになるでしょう。
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()
}
}
リソース
- クイックスタート
- KSPを使用する理由
- 例
- KSPがKotlinコードをモデル化する方法
- Javaアノテーションプロセッサ作成者向けリファレンス
- インクリメンタル処理の注意点
- 複数ラウンド処理の注意点
- マルチプラットフォームプロジェクトにおけるKSP
- コマンドラインからのKSP実行
- FAQ
サポートされているライブラリ
以下の表は、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を介してサポート |
Dagger | アルファ |
Motif | アルファ |
Hilt | 進行中 |
Auto Factory | 未サポート |