2017-01-31 3 views
0

Ich versuche gradle Plugin in kotlin zu implementieren, die die Struktur wie diesedelegieren verschachtelt Schließung Invokation zu entsprechenden Klasse

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

Aber ich habe ein Problem mit inneren Verschlüsse wie srcLink, downloadPath, installPath unterstützen würde. Wie kann man seine Aufrufe an die entsprechende Klasse kotlin delegieren?

Meine Erweiterung sieht wie folgt aus

/** 
* 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')" 
     } 


    } 
} 

Und wenn ich meine print Aufgabe aufrufen Liste der Umgebung anzuzeigen es zeigt nur gesetzt installationId - andere Felder sind leer

open class PrintingTask : DefaultTask() { 

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

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

Wie delegieren closure Invokation zu ApplicationEnvironmentExtension?

Antwort

0

Ich löste das Problem mithilfe dieser Problemumgehung.

Bei einigen seltsamen Gründen der Parameter closure, dass ich in app Methode übergeben immer gegen ApplicationEnvironmentContainerExtension lösen wollte trotz Einstellung ist als Verschluss von ApplicationEnvironmentExtension und Aufrufen es sogar.

Also entschied ich Brute Force zu verwenden und die Felder zu erstellen, die in ApplicationEnvironmentExtension in ApplicationEnvironmentContainerExtension aufgefüllt werden sollen, füllen Sie sie aus, und legen Sie manuell in der erforderlichen Klasse fest.

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

Wie für die Schließung habe ich beschlossen, sie zu setzen wie James Bassett

vorgeschlagen
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

Sie rufen nie den closure Parameter in Ihrer app Funktion auf. Ich denke, die Signatur der app Funktion ist falsch. Es sollte so aussehen:

fun app(id: String, closure: ApplicationEnvironmentExtension.() -> Unit) 

Dies macht die this in der Schließung der ApplicationEnvironmentExtension beziehen. Das führt dazu, dass die Aufrufe an srcLink, downloadPath und das richtige Objekt treffen.

Sie rufen dann die Schließung durch dies zu tun:

val extension = ApplicationEnvironmentExtension() 
extension.closure() 

Das die ApplicationEnvironmentExtension bevölkern.

Ich denke auch, dass die Signaturen der srcLink, downloadPath und Funktionen falsch sind. Sie sollten wie folgt definiert werden:

fun srcLink(closure:() -> String) 
fun downloadPath(closure:() -> String) 
fun installPath(closure:() -> String) 
+0

In diesem Fall kehrt 'konnte nicht Methode srcLink() für Argumente [build_7r01ofigr1pt144ypsds3y84p $ _run_closure2_closure5_closure7 @ 718989fa]' – lapots

+0

finden Was meinst du "returns"? Wird während der Laufzeit ein Kompilierfehler oder eine Ausnahme ausgelöst? – marstran

+0

in Laufzeit. Wenn ich einige Aufgaben von meinem Plugin – lapots

0

Benötigen Sie sogar diese Funktionen? Können Sie nicht scrLink, downloadPath und als Eigenschaften festlegen? d. h.

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

Es funktioniert auch nicht. Das Feld 'srcLink' kann nicht gefunden werden – lapots

Verwandte Themen