TL;DR
kotlin -> javaのcode generationを行うときは変数名にjavaの予約語は使わないほうがいいよ
kaptとは
- javaのAnnotation processorsをkotlinでサポートするpluginのこと
- android開発ではおなじみのdagger2やDataBindingで使用することが多い
- アノテーションを付けたクラスを付けてkaptを走らせるとアノテーションを読み取ってコードを自動生成してくれる
見つかった経緯
- androidの公式ORMのRoomを使用していてぶつかりました
- ある公開APIの返却のレスポンスjsonでキー名がcatchというものをその定義のままRoomを使用してローカルDBに保存しようとしてたらビルドがこけて調べました
Room
- RoomはGoogleが作っているSQLiteを抽象化してくれるライブラリです
- 公式HP
- Roomは下記のように@Entityがついているclassをテーブル定義としてkaptでDAO等を自動生成します
@Entity
data class StringEntity(
@PrimaryKey(autoGenerate = false)
val id: Int,
val catch: String
)
確認方法
- サンプルプロジェクトを作って試しました
- entityを用意しました
- entityの変数名をcatchにしてビルド
- 下記のようにビルド失敗になりました
エラー: Entities and POJOs must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type).
public final class StringEntity {
^
Tried the following constructors but they failed to match:
StringEntity(int,java.lang.String) -> [param:id -> matched field:id, param:catch -> matched field:unmatched]\room-catch\app\build\tmp\kapt3\stubs\debug\com\ryunen344\room\column\db\entity\StringEntity.java:9: エラー: Cannot find setter for field.
private final int id = 0;
原因
- kaptでkotlinのコードから情報を読み取ってjavaコードへ変換する際にjavaの予約語とぶつかるため失敗するようです
- 既に同様(catchではなくabstract)の問題でissueあげて、won't fix張られてるものがありました
- void, catch, abstract, javaのprimitive型名にするとkaptが失敗することまでは確認しました
結論
kaptだけでなくkotlinを書くときはjavaを意識して書いたほうが良い(当たり前っちゃ当たり前)