Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested object inside custom plugin extension

I'm developing a custom Gradle plugin and I want to define a configuration closure (plugin extension) like this:

myplugin {
   property1 'value'

   property2 {
     a1 'hello'
     a2 'bye'
   }
}

I have this classes:

public class MyPluginExtension { //root extension

    String property1;
    Property2 peroperty2;

    //getters and setters
}

public class Property2 {
    String a1;
    String a2;
    //getters and setters
}

And, in the plugin project, I create the extension this way:

project.getExtensions().create("myplugin", MyPluginExtension.class);

But in my client project, when I apply and configure the plugin like shown above, I get this error:

Gradle DSL method not found: 'property2()'

How can I define the property2 closure in my MyPluginExtension class?

EDIT

I have tried this:

 public class MyPluginExtension { //root extension

    String property1;
    Property2 peroperty2;

        //getters and setters

    public void property2(Closure c) {
        c.setResolveStrategy(Closure.DELEGATE_FIRST);
        c.setDelegate(property2);
        c.call();
    }
}

But now I get this error:

Gradle DSL method not found: a1()

It can't resolve nested closure fields.

like image 570
Héctor Avatar asked Nov 09 '15 10:11

Héctor


1 Answers

You need to utilize a Closure with delegate set to particular object:

class SamplePlugin implements Plugin {
   void apply(Object p) {
      p.extensions.create("e", MyPluginExtension)
   }
}

class MyPluginExtension { 

    Property2 property2 = new Property2()
    String property1

    def property2(Closure c) {
      c.resolveStrategy = Closure.DELEGATE_FIRST
      c.delegate = property2
      c()
    }
}

class Property2 {
    String a1
    String a2

    def a1(a1) {
      this.a1 = a1
    }

    def a2(a2) {
      this.a2 = a2
    }
}

apply plugin: SamplePlugin

e {
   property1 'lol'
   property2 {
      a1 'lol2'
      a2 'lol3'
   }
}

println e.property1
println e.property2.a1

Please also have a look here why additional methods are needed. And here you can find a working demo that is implemented in java.

like image 116
Opal Avatar answered Oct 06 '22 01:10

Opal