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") } } } }