http://stackoverflow.com/questions/28100232/groovy-no-signature-of-method-running-closure-against-delegate
I’ll add Gradle-specific info here:
I have an extension object Foo. I create the extension using:
project.extensions.create("foo", Foo)
And Foo looks something like
class Foo {
Bar bar
// If bar is configurable I would think I should be able to omit these
// routing methods and simply pass the Closure through to the 'bar'
// reference.
public void bar(Closure config) {
ConfigureUtil.configure(config, bar)
}
public bar(Action<Bar> action) {
action.execute(bar)
}
}
and Bar is as in the SO question but I should add it also implements Configurable:
class Bar implements Configurable<Bar> {
...
Bar configure(Closure config) {
ConfigureUtil.configure(config, this, false)
}
}
The SO thread has been answered, but if there are any more Gradle specific comments on this surrounding the convention (as the DSL makes heavy use of these interchangeable method/property references) I wouldn’t mind any additional info (=
In your specific example above. creating the extension ‘foo’ effectively adds a method to your project, which takes a closure that configures an instances of ‘Foo’. This does not however apply to nested objects. If you want a configure method for them then you’ll have to define them, as you did in your example.
Sometimes this is also confused with “setter methods”. Gradle will decorate objects with methods than can be used to set values. This is mainly just to allow for a cleaner DSL. For example, given an extension like this:
project.extensions.create(‘foo’, Foo)
class Foo {
private String bar;
void setBar(String bar) {
this.bar = bar
}
String getBar() {
return this.bar
}
}
I could do the following in my build script:
foo {
bar ‘hello’
}
You’ll note that my extension class contains no method ‘bar()’. Gradle adds this method for me when the extension is created. A similar decoration process is done for tasks as well, allowing the same DSL syntax. The exception to this is that Gradle does not create setter methods for collection types. In that case, you must use the assignment operator (=).
I thought there was more to it. So how would I get the same behavior for my ‘Bar’ class? Do I need to extend one of the objects from the Gradle api or maybe the groovy GroovySupportObject? Is this recommended in the first place or am I worrying too much?
Extensions themselves can be extended. So in your example, instead of defining a property of type ‘Bar’ on the ‘Foo’ extension, you would create an extension of type ‘Bar’.
project.foo.extensions.create(‘foo’, Foo)
This would enable a DSL like so:
foo {
bar {
// configure ‘bar’
}
}
(you mean ‘project.foo.extensions.creat(‘bar’, Bar)’) cool! Thanks.