将任意命名的域对象添加到任务中

时间:2015-12-02 03:40:22

标签: gradle

我是Groovy / Gradle的新手,所以如果我的任何术语出错,请原谅我。

我正在尝试为Gradle编写插件。我想要的是一个自定义任务,可以采用任意名称并使用这些名称创建域对象。这样的事情就是我的目标:

task myTask(type: MyTask) {
    hello {
        myMethod 'my data'
    }
    hiagain {
        myMethod 'other data'
    }
}

hellohiagain分别是每个域对象的名称。我目前只想在顶级做这个,但我可以看到其他用例,我会有几个可能的嵌套级别。还有一种情况是同时具有动态命名的对象,但在这些任务中也有其他特定的属性和方法,但我现在并不关心。

我尝试使用NamedDomainObjectContainer执行此操作(任务,容器,:

package com.mkobit.gradle

import org.gradle.api.DefaultTask
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Task

class MyTask extends DefaultTask {

    NamedDomainObjectContainer<MyContainerData> container

    MyTask() {
        container = project.container(MyContainerData)
    }

    @Override
    Task configure(Closure closure) {
        closure.delegate = container
        closure()
        this
    }

    String getGuy(String name) {
        container.getByName(name).myValue
    }
}
package com.mkobit.gradle

import org.gradle.util.Configurable

class MyContainerData implements Configurable<MyContainerData> {

    String myValue


    public MyContainerData(String name) {
        this.name = name
    }

    @Override
    MyContainerData configure(Closure closure) {
        closure.delegate = this
        closure()
        this
    }

    void myMethod(String s) {
        myValue = s
    }
}
package com.mkobit.gradle

import org.gradle.testfixtures.ProjectBuilder
import spock.lang.Specification

class MyTaskTest extends Specification {
    def project = ProjectBuilder.builder().build()

    def "name test"() {
        given:
        def task = project.task('myTask', type: MyTask)

        expect:
        task.name == 'myTask'
    }

    def "try domain container"() {
        given:
        def task = project.task('myTask', type: MyTask) {
            hello {
                myMethod 'my data'
            }
            hiagain {
                myMethod 'other data'
            }
        }

        expect:
        task.getGuy('hello') == 'my data'
        task.getGuy('hiagain') == 'other data'
    }
}

我在文档中看到类似内容的唯一地方位于Chapter 61. Writing Custom Plugins

的底部

这不起作用,当我运行测试时,我得到了这个堆栈跟踪:

  

没有方法签名:com.mkobit.gradle.MyTaskTest.hello()是   适用于参数类型:   (com.mkobit.gradle.MyTaskTest $ __ spock_feature_0_1_closure1 $ _closure2)   值:

     

...

我不确定如何实现这一目标,或者即使这是正确的方法。

提供的方法更好地包含这些任务吗?然后它看起来像:

task myTask(type: MyTask) {
    myHellos {
        hello {
            myMethod 'my data'
        }
        hiagain {
            myMethod 'other data'
        }
    }
}

但我仍然不确定我会怎么做。

基本上,如何将任意命名的域对象添加到任务中?

1 个答案:

答案 0 :(得分:1)

由于answer提供了不同的@Opal,我能够提出解决方案。 TaskExtensionAware,因此您可以在任务上创建扩展程序。以下是我能够如何调整上述类以获得我在问题底部描述的DSL:

import org.gradle.api.DefaultTask

class MyTask extends DefaultTask {

    MyTask() {
        def myExtensionContainer = project.container(MyContainerData)
        extensions.add('myExtension', myExtensionContainer)
    }
}
class MyContainerData {

    String myValue
    String name

    public MyContainerData(String name) {
        this.name = name
    }

    void myMethod(String s) {
        myValue = s
    }
}
mport org.gradle.testfixtures.ProjectBuilder
import spock.lang.Specification

class MyTaskTest extends Specification {
    def project = ProjectBuilder.builder().build()

    def "name test"() {
        given:
        def task = project.task('myTask', type: MyTask)

        expect:
        task.name == 'myTask'
    }

    def "try domain container"() {
        given:
        def task1 = project.task('myTask', type: MyTask) {
            myExtension {
                hello {
                    myMethod 'my data'
                }
                hiagain {
                    myMethod 'other data'
                }
            }
        }
        def task2 = project.task('otherTask', type: MyTask) {
            myExtension {
                myDude {
                    myMethod 'other data'
                }
            }
        }
        expect:
        task1.extensions.myExtension.hello.myValue == 'my data'
        task1.extensions.myExtension.hello.name == 'hello'
        task1.extensions.myExtension.hiagain.myValue == 'other data'
        task1.extensions.myExtension.hiagain.name == 'hiagain'
        task2.extensions.myExtension.myDude.myValue == 'other data'
    }
}