Я пытаюсь внедрить плагин gradle
в kotlin
, который поддерживал бы структуру, подобную этой
env { app ("ghc-haskell") { srcLink { "http://downloads.haskell.org/~ghc/8.0.1/ghc-8.0.1-x86_64-unknown-mingw32.tar.xz" } downloadPath { project(':').projectDir.absolutePath + "\\applications\\plugin" } installPath { project(':').projectDir.absolutePath + "\\applications\\plugin" } } }
Но у меня проблема с внутренними закрытиями, такими как srcLink
, downloadPath
, installPath
. Как передать свою инволюцию соответствующему классу kotlin
?
Мое расширение выглядит так
/** * Keeps all environments. */ open class ApplicationEnvironmentContainerExtension { val environs = mutableMapOf<String, ApplicationEnvironmentExtension>() fun app(id: String, closure : ApplicationEnvironmentContainerExtension.() -> String) : ApplicationEnvironmentExtension { val extension = ApplicationEnvironmentExtension() extension.installationId = id environs.put(id, extension) return extension } /** * Sub extension. */ open class ApplicationEnvironmentExtension { var installationId = "" var srcLink = "" var downloadPath = "" var installPath = "" fun srcLink(closure: ApplicationEnvironmentExtension.() -> String) { srcLink = closure() } fun downloadPath(closure: ApplicationEnvironmentExtension.() -> String) { downloadPath = closure() } fun installPath(closure: ApplicationEnvironmentExtension.() -> String) { installPath = closure() } override fun toString(): String { return "ApplicationEnvironmentExtension(" + "installationId='$installationId', " + "srcLink='$srcLink', " + "downloadPath='$downloadPath', " + "installPath='$installPath')" } } }
И когда я вызываю задачу print
для отображения списка окружений, она показывает set only installationId
– другие поля пусты
open class PrintingTask : DefaultTask() { @TaskAction fun print() { val extension = this.project.extensions.getByName("env") as ApplicationEnvironmentContainerExtension extension.environs.forEach { println(it.value) } } }
Как вызов closure
делегата в ApplicationEnvironmentExtension
?
Вы никогда не вызываете параметр closure
в своей функции app
. Я думаю, что подпись функции app
неверна. Это должно быть так:
fun app(id: String, closure: ApplicationEnvironmentExtension.() -> Unit)
Это делает this
в закрытии ссылкой на ApplicationEnvironmentExtension
. Это делает вызовы srcLink
, downloadPath
и installPath
попадают в правый объект.
Затем вы вызываете закрытие, делая следующее:
val extension = ApplicationEnvironmentExtension() extension.closure()
Это заполнит ApplicationEnvironmentExtension
.
Я также думаю, что подписи функций srcLink
, downloadPath
и installPath
неверны. Они должны быть определены следующим образом:
fun srcLink(closure: () -> String) fun downloadPath(closure: () -> String) fun installPath(closure: () -> String)
Вам даже нужны эти функции? Не можете ли вы установить scrLink
, downloadPath
и installPath
как свойства? т.е.
env { app ("ghc-haskell") { srcLink = "http://downloads.haskell.org/~ghc/8.0.1/ghc-8.0.1-x86_64-unknown-mingw32.tar.xz" downloadPath = project(':').projectDir.absolutePath + "\\applications\\plugin" installPath = project(':').projectDir.absolutePath + "\\applications\\plugin" } }
Я решил проблему, используя этот способ обхода.
По некоторым странным причинам closure
параметра, которое я передавал в метод app
всегда хотело разрешить против ApplicationEnvironmentContainerExtension
несмотря на то, что установка является закрытием ApplicationEnvironmentExtension
и даже вызовом.
Поэтому я решил использовать грубую силу и создать поля, которые должны быть заполнены в ApplicationEnvironmentExtension
в ApplicationEnvironmentContainerExtension
, заполнить их и установить вручную в требуемом классе.
open class ApplicationEnvironmentContainerExtension { val environs = mutableMapOf<String, ApplicationEnvironmentExtension>() var installationId = "" var srcLink = "" var installPath = "" var downloadPath = "" fun app(id: String, closure : ApplicationEnvironmentExtension.() -> Unit) { val extension = ApplicationEnvironmentExtension() extension.installationId = id environs.put(id, extension) extension.process(closure) extension.setEverything(installationId, srcLink, downloadPath, installPath) } }
Что касается закрытия, я решил установить их, как предложил Джеймс Бассетт
env { app ("ghc-haskell") { srcLink = "http://downloads.haskell.org/~ghc/8.0.1/ghc-8.0.1-x86_64-unknown-mingw32.tar.xz" downloadPath = "$path\\applications\\plugin" installPath = "$path\\applications\\plugin" } app ("mongo-db") { srcLink = "https://fastdl.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-3.4.1-signed.msi" downloadPath = "$path\\applications\\plugin" installPath = "$path\\applications\\plugin" } }