LoginSignup
1

More than 1 year has passed since last update.

posted at

updated at

Organization

KSPのProcessor実装でハマったこと備忘録

特に下調べせずKSPを触り始めたところ、色々ハマりました。
大体は公式ドキュメントをちゃんと読めば解決する内容です。

ハマりながら書いたSymbolProcessor: https://github.com/tkhskt/ShaderView/tree/feature/kotlin_dsl_interface/processor

環境

Kotlin: 1.6.10
KSP: 1.6.10-1.0.4
KotlinPoet: 1.10.2

ハマったこと

コード生成されない

SymbolProcessorを実装するモジュールでは、resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProviderを作成する必要があります。
resources/services/com.google.devtools.ksp.processing.SymbolProcessorProvider(META-INFが抜けてる)だと、ProcessorProviderは認識されるようでしたが、Processorを使用するモジュールにコードが生成されませんでした。

インクリメンタルビルドすると生成されたコードが消える

KSP関連の記事を見ていると、こんな感じ↓でファイル(コード)を生成していることが多いですが、これだとIncremental Buildを行った際に前回生成したコードが消えてしまいます。

val file = codeGenerator.createNewFile(
            Dependencies(false),
            "com.hoge",
            "Hoge"
        )

        file.write(code.toByteArray())
        file.close()

これを回避するためには、Dependenciessource: KSFileを渡します。

val file = codeGenerator.createNewFile(
            Dependencies(false, classDeclaration.containingFile!!), // KSFileを渡す
            "com.hoge",
            "Hoge"
        )

        file.write(code.toByteArray())
        file.close()

このあたりの挙動は下記の動画が非常に参考になります。
https://youtu.be/sJfURbrdau0

KotlinPoetだと下記のようになります。

val file = FileSpec.builder(packageName, className)
            ...
            .build()
        file.writeTo(codeGenerator, Dependencies(false, classDeclaration.containingFile!!))

生成されたコードがIDE(AndroidStudio)で認識されない

KSPを使用するモジュールのbuild.gradleのandroidブロックにsourceSetsの設定を追加します。

android {
    applicationVariants.all { variant ->
        kotlin.sourceSets {
            def name = variant.name
            getByName(name) {
                kotlin.srcDir("build/generated/ksp/$name/kotlin")
            }
        }
    }
}

パッケージ名をどうやって管理するか問題

KSPとは直接関係ないのですが、Processorで使うパッケージ名/クラス名をどうやって管理するか悩みました。
airbnb/epoxyのProcessorで採用されている方法が良い感じでした。(airbnb/epoxy/processor/ClassNames.kt)

object ClassNames {
    private const val PKG_SHADER_VIEW = "com.appspell.shaderview"
    private const val PKG_SHADER_VIEW_GL_PARAMS = "com.appspell.shaderview.gl.params"
    private const val PKG_SHADER_VIEW_KTX_ANNOTATION = "com.appspell.shaderview.ktx.annotation"
    ...

    val SHADER_VIEW = ClassName(PKG_SHADER_VIEW, "ShaderView")
    val SHADER_PARAMS = ClassName(PKG_SHADER_VIEW_GL_PARAMS, "ShaderParams")
    val SHADER_PARAMS_BUILDER = ClassName(PKG_SHADER_VIEW_GL_PARAMS, "ShaderParamsBuilder")
    val SHADER_PARAMETERS = ClassName(PKG_SHADER_VIEW_KTX_ANNOTATION, "ShaderParameters")
   ...
}

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1