Come è Gant in grado di fare riferimento a obiettivi con il loro nome, e non ottenere un'eccezione immobile manca?
-
19-09-2019 - |
Domanda
Nel codice qui presentata: Gant il file , v'è il seguente codice:
target(dist: 'Create release artefacts') {
depends(test)
depends(jar)
}
target(run: 'Run the distributed jar') {
depends(dist)
Ant.java(jar: distributedJarPath, fork: 'true')
}
target(hello: 'Hello World') {
println("Hello World")
}
setDefaultTarget(dist)
Mi interessa come è in grado di scrivere setDefaultTarget(dist)
, e non riceve un'eccezione circa dist
come una proprietà mancante. E 'questo frammento valutato nel contesto di un oggetto, e gli obiettivi di creare variabili di istanza?
Soluzione
Ci sono due elementi da tenere in considerazione, il legame dello script, e come un obiettivo viene dichiarato.
In primo luogo c'è il legame. Uno script Groovy è un po 'diverso da una classe Groovy / Java. Groovy script consentono per le variabili non legati. Significato quando si compila lo script non deve essere dichiarata la variabile. Quando il compilatore vede uno di questi riferimenti variabile non dichiarata, che convertirà il refrence alla variabile sotto le coperte per una chiamata a binding.getVariable (nome della variabile) (o qualcosa giù di lì). Quindi l'ultima riga dello script è funzionalmente l'equivalente di
setDefaultTarget(binding.getVariable('dist'))
In secondo luogo v'è la è la dichiarazione del bersaglio. Quando il bersaglio viene dichiarato il compilatore Groovy è in realtà vedendo una chiamata di metodo: bersaglio (Mappa args, Chiusura) (o giù di lì). Quando questo metodo esegue esamina i args, estrae il nome della destinazione, e memorizza qualche riferimento avvolto alla chiusura con quel nome nel legame. Un appropximation sarebbe ..
target(Map args, Closure closure) {
binding.setVarialbe(
args.keySet().iterator().next(),
gantClosureWrapping(args, closure))
}
Naturalmente il codice di cui sopra è un'approssimazione e non il vero e proprio codice di Gant.
Quindi, in sostanza ...
target(dist: 'doc') { ... }
// the above adds 'dist' as a variable to the binding
//...
setDefaultTarget(dist)
// dist is unbound, so it is replaced with binding.getVariable('dist')