Как Gant может ссылаться на цели по их именам и не получать исключение об отсутствующем свойстве?
-
19-09-2019 - |
Вопрос
В представленном здесь коде: Файл Ганта, есть следующий код:
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)
Мне интересно, как он умеет писать setDefaultTarget(dist)
, и не получать исключение о dist
как пропавшее имущество.Этот фрагмент оценивается в контексте какого-то объекта, а целевые объекты создают переменные экземпляра?
Решение
Вам необходимо учитывать два момента: привязку сценария и способ объявления цели.
Во-первых, это привязка.Сценарий Groovy немного отличается от класса Groovy/Java.Сценарии Groovy допускают несвязанные переменные.Это означает, что при компиляции скрипта переменную не нужно объявлять.Когда компилятор видит одну из этих ссылок на необъявленные переменные, он преобразует ссылку на скрытую переменную в вызов метода привязки.getVariable(имя переменной) (или что-то в этом роде).Таким образом, последняя строка сценария функционально эквивалентна
setDefaultTarget(binding.getVariable('dist'))
Во-вторых, это объявление цели.Когда цель объявлена, компилятор Groovy фактически видит вызов метода:target(Map args, Closure closure) (или около того).При выполнении этого метода он проверяет аргументы, извлекает имя цели и сохраняет в привязке некую обернутую ссылку на замыкание с этим именем.Приближение будет..
target(Map args, Closure closure) {
binding.setVarialbe(
args.keySet().iterator().next(),
gantClosureWrapping(args, closure))
}
Конечно, приведенный выше код является приблизительным, а не настоящим кодом Ганта.
так по сути...
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')