可以摇篮扩展处理财产的懒惰评价?(Can gradle extensions handle lazy

2019-09-01 03:31发布

我正在写一个自定义插件的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作为输入,而是由插件应用的任务是贪婪和值为空早期。 (在申请阶段?)

我发现的唯一的解决方案是使用封闭在插件任务的配置块,像这样:

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

那个漂亮的很好解决了贪婪的评价问题, 只是现在的自定义任务,必须修改的期望和处理封闭。 这不是得不得了很难做到,但我不认为它应该是对付关闭,因为该插件是“惹的祸”任务的责任。

我使用的扩展错误吗? 或者,他们只是没有足够的? 官方的立场似乎是, 我们应该使用扩展 ,但我还没有找到任何实例,其中扩展可以做什么,我需要。 我可以向前与我使用闭包,写了一堆样板干将是做封闭评估和能够处理关闭和正常类型的制定者,但它似乎很对的常规,因此gradle这个理念。 我会非常高兴,如果有一种方法,我可以使用扩展和自动获得懒惰的评价。

Answer 1:

这个问题通常的解决方法是使用约定的映射:

class MyPlugin implements Plugin<Project> {
    void apply(Project project) {
       project.extensions.create('myPluginProps', MyPluginExtension)

        project.task(type: MyTask, 'thisTaskWorksIncorrectly') {
            conventionMapping.input = { project.myPluginProps.message }
        }
    }
}

然后在任务:

class MyTask extends DefaultTask {
    def String input

    @TaskAction
    def action() {
        println "You gave me this: ${getInput()}"
    }

}

请注意,我明确使用getter方法input -如果你直接引用领域的约定映射不会一命呜呼



Answer 2:

彼得在我的问题的答案在这里表示conventionMapping功能肯定会消失。 这是最好的避免。

使用afterEvaluate解决递延配置问题,使我的代码有很多比conventionMapping方法清洁。

class MyPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.extensions.create('myPluginProps', MyPluginExtension)

        project.afterEvaluate {
            project.task(type: MyTask, 'thisTaskWorksIncorrectly') {
                input = project.myPluginProps.message
            }
        }
    }
}


文章来源: Can gradle extensions handle lazy evaluation of a property?
标签: gradle