2017-01-31 3 views
0

Я пытаюсь реализовать gradle плагин в kotlin, которая будет поддерживать структуру как этогоделегата вложенного закрытие invokation к соответствующему классу

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 задачу, чтобы отобразить список окрестностей он показывает набор только installationId - другие поля пустые

open class PrintingTask : DefaultTask() { 

    @TaskAction 
    fun print() { 
     val extension = this.project.extensions.getByName("env") as ApplicationEnvironmentContainerExtension 

     extension.environs.forEach { 
      println(it.value) 
     } 
    } 
} 

Как делегировать closure invokation в ApplicationEnvironmentExtension?

ответ

0

Я решил проблему с использованием этого обходного пути.

Для некоторых странных причин параметр 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" 
    } 
} 
0

Вы не вызываете параметр 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) 
+0

В этом случае она возвращает 'Не удалось найти метод srcLink() для аргументов [build_7r01ofigr1pt144ypsds3y84p $ _run_closure2_closure5_closure7 @ 718989fa]' – lapots

+0

Что вы имеете в виду «возвращает»? Это ошибка компиляции или исключение, возникшее во время выполнения? – marstran

+0

во время выполнения. Когда я пытаюсь запустить некоторые задачи из своего плагина – lapots

0

Вам даже нужны эти функции? Не можете ли вы установить 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" 
    } 
} 
+0

Это тоже не работает. Он не может найти поле 'srcLink' – lapots

 Смежные вопросы

  • Нет связанных вопросов^_^