Name conflict resolution ordering

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:

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

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.

1 Like