Skip to content

Generated accessors for ExtensiblePolymorphicDomainObjectContainer elements are not cast to the correct type #24972

@aSemy

Description

@aSemy

Expected Behavior

Gradle generates accessors for added to a ExtensiblePolymorphicDomainObjectContainer, and they are cast to the correct type.

Current Behavior

Gradle generates accessors for added to a ExtensiblePolymorphicDomainObjectContainer, but they are not cast to the correct type, so I cannot use them.

plugins {
  `example-convention`
}

myExtension.myContainer.alphaValue {
  // this: MyPolymorphicType
  stringProperty.get() // ERROR Unresolved reference: stringProperty

  // but this succeeds:
  require(this is MyPolymorphicType.AlphaType)
  stringProperty.get()
}

Here is a generated accessor:

import MyPolymorphicType

/**
 * Provides the existing [alphaValue][MyPolymorphicType] element.
 */
val org.gradle.api.NamedDomainObjectContainer<MyPolymorphicType>.`alphaValue`: NamedDomainObjectProvider<MyPolymorphicType>
    get() = named<MyPolymorphicType>("alphaValue")

It should be something like this

import MyPolymorphicType

/**
 * Provides the existing [alphaValue][MyPolymorphicType.AlphaType] element.
 */
val org.gradle.api.NamedDomainObjectContainer<MyPolymorphicType.AlphaType>.`alphaValue`: NamedDomainObjectProvider<MyPolymorphicType.AlphaType>
    get() = named<MyPolymorphicType.AlphaType>("alphaValue")

Context (optional)

I am creating a Gradle plugin, which has an extension, MyExtension.

MyExtension has a ExtensiblePolymorphicDomainObjectContainer property, myContainer.

In order to generate the Kotlin DSL accessors, I add the myContainer to the ExtensionContainer of MyExtension.

abstract class MyExtension @Inject constructor(
  private val objects: ObjectFactory
) : ExtensionAware {
  val myContainer: ExtensiblePolymorphicDomainObjectContainer<MyPolymorphicType> =
    objects.polymorphicDomainObjectContainer(MyPolymorphicType::class)

  init {
    extensions.add("myContainer", myContainer)
  }
}

MyPolymorphicType is an interface with two subclasses, AlphaType and BetaType, which are managed types.

interface MyPolymorphicType : Named {
  abstract class AlphaType @Inject constructor(
    private val name: String
  ) : MyPolymorphicType {
    abstract val stringProperty: Property<String>

    override fun getName() = name
  }

  abstract class BetaType @Inject constructor(
    private val name: String
  ) : MyPolymorphicType {
    abstract val intProperty: Property<Int>
    override fun getName() = name
  }
}

In my plugin I add MyExtension, and add two elements to myContainer.

val myExtension: MyExtension = extensions.create("myExtension")

myExtension.myContainer.registerBinding(MyPolymorphicType.AlphaType::class, MyPolymorphicType.AlphaType::class)
myExtension.myContainer.registerBinding(MyPolymorphicType.BetaType::class, MyPolymorphicType.BetaType::class)

myExtension.myContainer.register<MyPolymorphicType.AlphaType>("alphaValue") {
  stringProperty.set("I'm a property in AlphaType")
}

myExtension.myContainer.register<MyPolymorphicType.BetaType>("betaValue") {
  intProperty.set(11)
}

Steps to Reproduce

.
├── build.gradle.kts
├── buildSrc
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   └── src
│       └── main
│           └── kotlin
│               ├── MyExtension.kt
│               ├── MyPolymorphicType.kt
│               └── example-convention.gradle.kts
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle.kts

polymorphic-container-dsl-accessors.zip

Gradle version

8.1.1

Build scan URL (optional)

No response

Your Environment (optional)

No response

Related

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions