Nested extension plugin written in Java

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("")
  }
}

found the answer needed to add the Closure methods also.

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);
   } 
} 

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

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.

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:

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?

1 Like

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.

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

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.

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

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.

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.

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.

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:

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

3 Likes

The public replacement is ObjectFactory.newInstance.

Excuse me for bumping this old thread, but this is the best explanation of this issue I’ve found anywhere, and I thought it deserved a conclusion.

1 Like