前回、途中で力尽きてしまったので続きです。
Step 2 続き
Step 2のハマリポイントは記載しきったつもりだったのですが、1つ忘れていたのでそこからです。
コード全体は前回のStep 2を参照してください。
ハマリポイント 3: Pluginのconfigurationが参照できない
このsampleではRibbonizer pluginを使用しています。
Groovy版ではこのように設定を書くことが出来ました。
ribbonizer {
builder { variant, iconFile ->
if (variant.buildType.name == "debug") {
return yellowRibbonFilter(variant, iconFile)
} else {
return grayRibbonFilter(variant, iconFile)
}
}
}
ぱっと見、そのままKotlin化できそうな雰囲気を感じますが実際にはbuilder
が参照できずコンパイルエラーになります。
ribbonizer
は参照できているのでコードジャンプして見てみます。
/**
* Configures the [ribbonizer][com.github.gfx.ribbonizer.plugin.RibbonizerExtension] project extension.
*
* `ribbonizer` is not accessible in a type safe way because:
* - `com.github.gfx.ribbonizer.plugin.RibbonizerExtension` is not public
*/
fun Project.`ribbonizer`(configure: Any.() -> Unit): Unit =
extensions.configure("ribbonizer", configure)
どうやら、plugins構文で指定されたプラグインへのアクセスはこのaccessors.kt
というファイルが生成されることで実現しているようです。
この拡張関数のコメントによると、configurationのインターフェースであるExtensionクラスがpublicではないときにtype safeなアクセスができないようです。
実際、RibbonizerExtension
クラスはpublicではありませんでした。
このような場合どうするかというと、withGroovyBuilder
ブロックを使って文字列指定でパラメータやメソッドに値を設定していくことになります。
ribbonizer {
withGroovyBuilder {
"builder"(FilterBuilder { variant, iconFile ->
return@FilterBuilder when (variant.buildType.name) {
"debug" -> YellowRibbonBuilder().apply(variant, iconFile)
else -> GrayRibbonBuilder().apply(variant, iconFile)
}
})
}
}
このように書くことでbuilder
メソッドに引数を渡すことができます。
また、groovyでyellowRibbonFilter(variant, iconFile)
のようにしていた箇所も直接アクセス出来ないためyellowRibbonFilter
の内部実装をコピペしています。
Step 3 - plugin versionの共通化
pluginのバージョン指定をする際、変数やgradle.propertiesの値を使うことができない謎の制限があるため、Kotlin関連プラグインのような同じバージョンのものを複数指定するパターンで記述をまとめることができず更新時などに辛い感じになってしまいます。
plugins {
...
kotlin("android") version "1.2.0-rc-39"
kotlin("android.extensions") version "1.2.0-rc-39"
...
}
これを一箇所まとめたい場合はまたpluginManagement
で行うことになります。
今回はkotlinのバージョンはgradle.propertiesに記載することにします
kotlinVersion=1.2.0-rc-39
idを正規表現でKotlin関連プラグインが引っかかるように定義してuseVersionでバージョンを指定
resolutionStrategy {
eachPlugin {
switch (requested.id.id) {
...
case ~/org\.jetbrains\.kotlin\..*/:
useVersion("${kotlinVersion}")
break
}
}
}
build.gradle側では、versionの指定を無くします
plugins {
...
kotlin("android")
kotlin("android.extensions")
...
}
拡張プロパティの取得はextra
というdelegated propertyで行えたのですが、プロジェクトのプロパティは同様にproject
というdelegated propertyで行えます。
(projectで取得できる型はAnyになるので適宜Stringなどにcastして使ってください)
val kotlinVersion by project
参考資料
gradleのkotlin-dslリポジトリにはサンプルが多く用意されているのでまずはここを見てみるのがいいと思います
gradle/kotlin-dsl: Kotlin language support for Gradle build scripts
おわりに
今回、build.gradleをkotlinに書き換えてみましたが正直なところ本格的に使うのは厳しいかなという感じです。
この記事では書きませんでしたが、一度スクリプトがコンパイルエラーになると補完がまともに効かなくなりコンパイルが通るようになるまで結局補完を使えないみたいな状況になりがちで想像していた快適さには程遠いものでした。
とはいえ、今後そのあたりも改善されていくと思うので期待しながら状況ウォッチしていきたいと思います。
今回の最終的なコードはここにあります
chibatching/KtsSample
途中のstep毎にコミットしているので必要に応じてそちらも参照していただけると〜