Nested extension plugin written in Java

plugins

(Andrew Holland) #1

Hi, im trying to create a nested dsl with a plugin written in Java, could someone point me in the right direction on how to get this working?

Example classes

class Dsl {
  Nested nested;
}

class Nested {
  public void method(String arg) {
  }
}

Example dsl

dsl {
  nested {
    method("")
  }
}

(Andrew Holland) #2

found the answer needed to add the Closure methods also.


(uklance) #3

Typically you’d add Closure and Action methods to be java & kotlin friendly

class Dsl {
   Nested nested;
   Dsl() {
      nested = new NestedImpl() 
   } 
   void nested(Closure c) {
      org.gradle.util.ConfigureUtil.configure(c, nested) 
   } 
   void nested(Action<? super Nested> action) {
      action.execute(nested);
   } 
} 

(Mark Vieira) #4

FWIW you can typically omit the method which takes a Closure as Gradle will generate one for you based on the Action<T> method.


(Andrew Holland) #5

I had to add the closure method manually otherwise it didn’t work, there was a comment on the link I posted that says it won’t generate them if it’s added via create.


(Stefan Oehme) #6

It is decorated when using the create() method, but not when you call new XYZ(). We plan to improve nested DSL creation with a public Instantiator API. Currently that API is internal :frowning:


(Andrew Holland) #7

without adding the closure methods manually, its looking for the method() method on the dsl class and not the nested class, do i need action methods on the nested class?


(Stefan Oehme) #8

As I said, since you are using new Nested(), you have to add the Closure overloads manually. We will provide a better API for nested DSLs soon.


(Andrew Holland) #9

i’m using project.getExtensions().create(EXTENSION_NAME, MyExtension.class);


(Stefan Oehme) #10

You can leave out the Closure overloads on objects created by Gradle, only the Action overloads are needed there. But if you create any object yourself using new XYZ(), they will not be enhanced.


(Andrew Holland) #11

Thats not what i’m seeing, Closure methods need to be added. I will create a simple project on github with my reproducer.


(Andrew Holland) #12

Seem to have tracked it down, it only likes two levels of nesting, heres an example project with three levels of nesting https://github.com/a1dutch/nested-dsl. Adding the closure methods manually makes it works as expected.


(Stefan Oehme) #13

You are calling new Outer() here. That means that this object is not enhanced and will have no auto-generated Closure methods. Only objects created by Gradle have auto-generated methods.


(Andrew Holland) #14

Okay thanks, i thought it was the call to project.create(new Outist()) that was the problem, not the nested objects. Thanks for your help @st_oehme.


(uklance) #15

I’m guessing you could @Inject a private service into your plugin and pass it through your model. You could then call

somePrivateService.create(Outer.class)

instead of

new Outer()

I’m guessing @st_oehme is purposefully not telling us the private service :smile:


(Stefan Oehme) #16

@Lance It’s the Instantiator. It’s high on our list for adding a public replacement.