Я пишу пользовательский плагин gradle для обработки некоторой смутно сложной работы, и я столкнулся с расстраивающей проблемой при использовании свойств для настройки некоторых задач, которые применяет плагин.
apply plugin: myPlugin
//Provide properties for the applied plugin
myPluginProps {
message = "Hello"
}
//Define a task that uses my custom task directly
task thisTaskWorksFine(type: MyTask) {
input = myPluginProps.message
}
//Define a plugin that will apply a task of my custom type
class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create('myPluginProps', MyPluginExtension)
project.task(type: MyTask, 'thisTaskWorksIncorrectly') {
input = project.myPluginProps.message
}
}
}
//The extension used by my custom plugin to get input
class MyPluginExtension {
def String message
}
//The task used by both the standard build section and the plugin
class MyTask extends DefaultTask {
def String input
@TaskAction
def action() {
println "You gave me this: ${input}"
}
}
Результаты использования этого файла следующие:
$ gradle thisTaskWorksFine thisTaskWorksIncorrectly
:thisTaskWorksFine
You gave me this: Hello
:thisTaskWorksIncorrectly
You gave me this: null
BUILD SUCCESSFUL
Я считаю это очень неожиданным. На мой взгляд, применение задачи из плагина и запись напрямую должно приводить к тому же выводу, когда ему дают один и тот же ввод. В этом случае обе задания задаются myPluginProps.message
как входные данные, но задача, применяемая плагином, является жадным и сначала оценивается как null. (Во время фазы применения?)
Единственное решение, которое я нашел, - это использовать блокировки в блоке конфигурации задачи плагина следующим образом:
//Define a plugin that will apply a task of my custom type
class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create('myPluginProps', MyPluginExtension)
project.task(type: MyTask, 'thisTaskWorksIncorrectly') {
input = { project.myPluginProps.message }
}
}
}
Это очень хорошо решает проблему жадной оценки, за исключением того, что теперь настраиваемая задача должна быть изменена, чтобы ожидать и иметь дело с закрытием. Это не очень сложно сделать, но я не думаю, что ответственность за это должно быть связана с тем, что плагин "виноват".
Я использую расширения здесь неправильно? Или они просто не адекватны? Официальная позиция, по-видимому, заключается в том, что мы должны использовать расширения, но я еще не нашел примеров, когда расширения могли бы делать то, что мне нужно. Я могу продвигаться вперед с использованием закрытий и написанием кучи шаблонных геттеров, которые закрывают eval и сеттеры, которые могут обрабатывать замыкания и нормальные типы, но это кажется очень против философии groovy и, следовательно, gradle. Я был бы очень рад, если есть способ, которым я могу использовать расширения и получить ленивую оценку автоматически.