Gradleは元々Groovyで書かれてたツールで、バージョン2の頃にほぼすべてをJavaに置き換えられたという経緯があるのですが、未だに古い一部の実装ではGroovyでスクリプトを書くことを前提にしている箇所があります(と断言していいかどうかは自信がない)。
maven プラグインの uploadArchives まわりもGroovyで書くことを前提としているフシがあり、 MavenDeployer -> MavenPom#project の後のブロックは delegate オブジェクトが groovy.lang.GroovyObject というまさに groovy なDSLになっている
先日、mavenにリリースするライブラリーのdslをkotlinで書いていたが、この部分のdslを最初次のように書いていた。入れ子構造になっている部分を書き始めようとした時に、どのように書くのかわからず、手探りで書いていた。
mavenDeployer {
pom.project {
invoke("name", "library-name")
invoke("packaging", "jar")
invoke("scm", mapOf(
"connection" to "scm:git:https://github.com/mike-neck/repository-name",
"url" to "https://github.com/mike-neck/repository-name"
))
}
}
しかし、この部分、おそらくgroovyの MarkupBuilder を使っていることは想像がついたため、このようなDSLだと次のような望まないpom.xmlが生成されるように思われた。
<name>librry-name</name> <scm connection="scm:git:https://github.com/mike-neck/repository-name" url="https://github.com/mike-neck/repository-name"/>
というわけで、1〜2時間悩んでいたのだが、kotlin-dslのサンプルにあたってみたところ、すでに解決策が提示されていた。
GroovyObject を扱う場合は withGroovyBuilder(GroovyBuilderScope.() -> T) という拡張関数を使えば解決できるそうだ。
したがって、次のような dslを書けば、valid な pom.xml が出力される
mavenDeployer {
pom.project {
withGroovyBuilder {
"name" ("library-name")
"packaging" ("jar")
"scm" {
"connection"("scm:git:https://github.com/mike-neck/repository-name")
"url"("https://github.com/mike-neck/repository-name")
}
}
}
}