# Name conflict resolution ordering

**URL:** <https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791>\
**Category:** Help/Discuss\
**Created:** [December 27, 2021, 11:19am UTC](https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791 "2021-12-27T11:19:00Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![yschimke](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/yschimke/32/9237_2.png) [@yschimke](https://discuss.gradle.org/u/yschimke)\
**Post date:** [December 27, 2021, 11:19am UTC](https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791/1 "2021-12-27T11:19:00Z")

</div>

From [Awkwardness with Gradle Kotlin DSL · Issue #624 · jreleaser/jreleaser · GitHub](https://github.com/jreleaser/jreleaser/issues/624#issuecomment-1001506254)

 ![image](https://global.discourse-cdn.com/gradle/original/2X/4/4b89222aa03318bcbc04a374a0317656c7806ecd.png)

Using jreleaser with kotlin-dsl, I need to use this.distributions because distributions binds to project.distributions. Is there a clean way to avoid this ambiguity?

Say a scope in JReleaserExtensions that causes it to prefer JReleaserExtension.distributions.

---

<div class="post-metadata">

**Author:** ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)\
**Post date:** [December 27, 2021, 6:40pm UTC](https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791/2 "2021-12-27T18:40:38Z")

</div>

TL;DR: scroll down and read below the other horizontal ruler if you are not interested in the details

* * *

That’s more Kotlin precedence rules you are hitting here I’d say.

You have the two plugins `distribution` and `org.jreleaser` applied.

The `distribution` plugin adds an extension called `distributions` to the `project`, so when applied using the preferred `plugins` DSL method, the `kotlin-dsl` magic generates two accessors for this extension:

```gradle
val Project.distributions: DistributionContainer get() = ...
fun Project.distributions(configure: Action<DistributionContainer>): Unit = ...

```

The `org.jreleaser` plugin has in its `JReleaserExtension` a method `NamedDomainObjectContainer<Distribution> getDistributions()`.

The `kotlin-dsl` magic again has a shipped extension function

```gradle
inline operator fun <T : Any, C : NamedDomainObjectContainer<T>> C.invoke(
    configuration: Action<NamedDomainObjectContainerScope<T>>
): C = ...

```

so that you can do `distributions.invoke { ... }` or as it is the invoke operator just `distributions { ... }`.

Additionally it is important for understanding this, that in Kotlin direct members win over extension functions or properties.

So what you now have available inside the `JReleaserExtension` is an extension function named `distributions`, an extension property named `distributions`, a member property named `distributions` and an extension operator function called `invoke` on the type of the member property.

If you now do `distributions { ... }`, the choice is between the direct extension function `distributions` and the extension operator function `invoke` on the `distributions` member property, so the direct extension function wins here by Kotlin language rules.

* * *

There are at least two things you could do to mitigate this precedence problem.

The imho worse one is to not apply the `distribution` plugin (or any plugin that applies it transitively like `application`) via the `plugins` DSL, but instead using the legacy `apply` syntax, because then no accessors are generated that then have higher precedence.

The better solution is within the `org.jreleaser` plugin. As I just shortly described the relevant precedence rules, you might have guessed it already. If the `JReleaserExtensions` has a member function called `distributions` which takes an `Action<>`, then it will win over the extensions function as member functions always win if possible.

Even an extension function `JReleaserExtension.distributions` would work as then the extension function on the inner scope would win over the extension function on the outer scope.

---

<div class="post-metadata">

**Author:** ![yschimke](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/yschimke/32/9237_2.png) [@yschimke](https://discuss.gradle.org/u/yschimke)\
**Post date:** [December 28, 2021, 9:53am UTC](https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791/3 "2021-12-28T09:53:01Z")

</div>

Thanks for the thorough answer, much appreciated.

---

<div class="post-metadata">

**Author:** ![Andres\_Almiray](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/andres_almiray/32/7420_2.png) [@Andres\_Almiray](https://discuss.gradle.org/u/Andres_Almiray)\
**Post date:** [December 28, 2021, 2:48pm UTC](https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791/4 "2021-12-28T14:48:57Z")

</div>

How would this member function in `JReleaserExtensionImpl` should look like? I tried

```gradle
void distributions(Action? super NamedDomainObjectContainer<Distribution> action) { ... }

```

But didn’t work at all. TIA.

---

<div class="post-metadata">

**Author:** ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)\
**Post date:** [December 28, 2021, 5:10pm UTC](https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791/5 "2021-12-28T17:10:14Z")

</div>

Why not?  
Works fine here.  
Or well, I didn’t really test it, but according to IntelliJ highlighting and code-linking it works fine.

I added

```groovy
void distributions(Action<? super NamedDomainObjectContainer<Distribution>> action)

```

to the interface and

```groovy
@Override
void distributions(Action<? super NamedDomainObjectContainer<Distribution>> action) {
}

```

to the implementation and it resolves as expected downstream according to IDE.

But actually you might want to return `NamedDomainObjectContainer<Distribution>` from your method though to be more consistent with the accessors that are generated.

---

<div class="post-metadata">

**Author:** ![Andres\_Almiray](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/andres_almiray/32/7420_2.png) [@Andres\_Almiray](https://discuss.gradle.org/u/Andres_Almiray)\
**Post date:** [December 28, 2021, 8:37pm UTC](https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791/6 "2021-12-28T20:37:25Z")

</div>

Thanks. I should had been more clear. Adding the method is not a problem, the contents of the method are. Invoking `action.execute(distributions)` leads to a compiler error →

```gradle
'execute' in 'org.gradle.api.Action<? super org.gradle.api.NamedDomainObjectContainer<org.jreleaser.gradle.plugin.dsl.Distribution>>' cannot be applied to '(org.gradle.api.NamedDomainObjectContainer<org.jreleaser.gradle.plugin.internal.dsl.DistributionImpl>)'

```

But this appears to compile

```gradle
    @Override
    void distributions(Action<? super NamedDomainObjectContainer<? extends Distribution>> action) {
        action.execute(distributions)
    }

```

Which leads to usage such as

```gradle
  distributions {
    create("okurl") {
      active.set(org.jreleaser.model.Active.RELEASE)
      distributionType.set(org.jreleaser.model.Distribution.DistributionType.NATIVE_IMAGE)
      artifact {
        platform.set("osx")
        path.set(file("build/distributions/okurl-graal-$version.zip"))
      }
    }
  }

```

---

<div class="post-metadata">

**Author:** ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)\
**Post date:** [December 29, 2021, 12:13am UTC](https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791/7 "2021-12-29T00:13:57Z")

</div>

Yeah, well, that’s because of that `NamedDomainObjectContainer<DistributionImpl> distributions` you have in the impl class. `NamedDomainObjectContainer<DistributionImpl>` is not compatible to `NamedDomainObjectContainer<Distribution>`. I wonder how that actually works as intended, but I guess that is some Groovy magic I forgot about.

Maybe it would be better to have it actually as `NamedDomainObjectContainer<Distribution>` and downcast it internally if needed or something like that.

But besides that, the usage you showed is exactly what you wnated to achieve, isn’t it?  
So you are happy now, right?

Well, maybe besides that fact that `org.jreleaser.model.Distribution.DistributionType` is not resolvable.

---

<div class="post-metadata">

**Author:** ![Andres\_Almiray](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/andres_almiray/32/7420_2.png) [@Andres\_Almiray](https://discuss.gradle.org/u/Andres_Almiray)\
**Post date:** [December 29, 2021, 2:33pm UTC](https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791/8 "2021-12-29T14:33:41Z")

</div>

> [@Vampire](#):
>
> Well, maybe besides that fact that `org.jreleaser.model.Distribution.DistributionType` is not resolvable.

You’ve lost me with this comment. What does it mean?

---

<div class="post-metadata">

**Author:** ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)\
**Post date:** [December 30, 2021, 11:35am UTC](https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791/9 "2021-12-30T11:35:03Z")

</div>

![grafik](https://global.discourse-cdn.com/gradle/original/2X/e/e70ae75dfe0049198b3a2432abc889e31d209e6c.png)

---

<div class="post-metadata">

**Author:** ![Vampire](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/vampire/32/9082_2.png) [@Vampire](https://discuss.gradle.org/u/Vampire)\
**Post date:** [December 30, 2021, 11:38am UTC](https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791/10 "2021-12-30T11:38:12Z")

</div>

Hm, must be a problem with composite build in IntelliJ.  
If I use the released version it is resolvable.

---

<div class="post-metadata">

**Author:** ![Andres\_Almiray](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/andres_almiray/32/7420_2.png) [@Andres\_Almiray](https://discuss.gradle.org/u/Andres_Almiray)\
**Post date:** [December 30, 2021, 11:44am UTC](https://discuss.gradle.org/t/name-conflict-resolution-ordering/41791/11 "2021-12-30T11:44:10Z")

</div>

Which is why I was confused. It it wasn’t resolvable the the build file wouldn’t compile at all.
