No Kotlin type-safe accessor for extension of element in project-extension container

I was trying out the Kotlin DSL, specifically type-safe accessors. I wanted to test how accessors are generated for extensions on various elements. I add all extensions from a plugin, because they have to be added when the plugins block is evaluated.

In my plugin, I created a dummy type for the elements to store in a container:

// in plugin
interface Element extends Named, ExtensionAware {
}

I add a container to the project as an extension:

// in plugin
def containerOfElement = project.container(Element)
project.extensions.add('projectExtensionContainerOfElement', containerOfElement)

This leads to a type-safe accessor for it being generated:

// in build script
println(project.projectExtensionContainerOfElement)

Type safe accessors are also added to elements in the container:

// in plugin
def foo = project.objects.newInstance(Element, 'foo')
containerOfElement.add(foo)

// in build script
println(project.projectExtensionContainerOfElement.foo)

I also add an extension to the foo element:

// in plugin
foo.extensions.add('someStringProperty', project.objects.property(String))

According to the Kotlin DSL primer, I expected also a type-safe accessor for the property:

// in build script
println(project.projectExtensionContainerOfElement.foo.someStringProperty)

This unfortunately doesn’t work. I get a compile error.

Am I doing something wrong? Am I misunderstanding the DSL primer?

For completeness, here is the full code.

The plugin:

// in buildSrc/src/main/groovy/org.example.org.example.plugin-which-contributes-extensions.gradle

interface Element extends Named, ExtensionAware {
}

def containerOfElement = project.container(Element)
project.extensions.add('projectExtensionContainerOfElement', containerOfElement)

def foo = project.objects.newInstance(Element, 'foo')
containerOfElement.add(foo)

foo.extensions.add('someStringProperty', project.objects.property(String))

The build script:

// in build.gradle.kts
plugins {
    id("org.example.plugin-which-contributes-extensions")
}

// Type-safe model accessor for project extension
println(project.projectExtensionContainerOfElement)

// Type-safe model accessor for element in project extension container
println(project.projectExtensionContainerOfElement.foo)
println(project.projectExtensionContainerOfElement.foo.name)

// Type-safe model accessor for extension of element in container
println(project.projectExtensionContainerOfElement.foo.get().extensions.get("someStringProperty"))  // check that the extension exists
// println(project.projectExtensionContainerOfElement.foo.someStringProperty)  // doesn't work
// println(project.projectExtensionContainerOfElement.foo.get().someStringProperty)  // doesn't work either

What you are after is Properties of extensions that are containers should have Kotlin DSL accessors for existing elements · Issue #9264 · gradle/gradle · GitHub :slight_smile:

But am I crazy for assuming that this should already work after reading the primer?

  • Elements in project-extension containers (for example the source sets contributed by the Java Plugin that are added to the sourceSets container)

This gives me projectExtensionContainerOfElement.foo.

  • Extensions on each of the above

Should give me foo.someStringProperty, because it’s an extension of foo (one of the above).

Also, how can the Kotlin DSL for the Groovy plugin work? I’m referring to:

sourceSets {
  main {
    groovy {
      // do stuff
    }
}

The groovy extension is added in the same way as I did in my example.

Also, come to think of it, isn’t the case you listed actually talking about the elements in the container (i.e. in this case foo)? This already works.

Oh, right, the issue I linked to does not apply, sorry.
And yeah, I think the primer can be understood such that it should work.
I don’t see anything done wrongly.
Except maybe that Element is not accessible by the consumer.
But even moving it to its own classes does not make the accessor appear.
So you probably either hit a doc bug, or an implementation bug I’d say.

1 Like

I opened No Kotlin type-safe accessor for extension of element in project-extension container · Issue #28162 · gradle/gradle · GitHub

1 Like