What's the supported equivalent of exclusions in Java Platform Plugin? (Or do we have another escape route for our issue)

We currently have a giant dependencies.gradle file which defines a gigantic libraries hash like:

libraries = [
  acme: ['com.acme:acme-detonator:1.0', {
    exclude group: 'com.acme', module: 'acme-detcord'
  }],

  // ...
]

Now we’re ready to put the work in to move to Java Platform Plugin.

So using Java Platform Plugin at least, I can pin the versions in.

dependencies {
    constraints {
        api 'com.acme:acme-detonator:1.0'
    }
}

And then dependencies.gradle can just have:

libraries = [
  acme: ['com.acme:acme-detonator', {
    exclude group: 'com.acme', module: 'acme-detcord'
  }],

  // ...
]

But I want to eventually rid ourselves of dependencies.gradle entirely, so I was wondering how I would have a platform also document the exclusions.

This is sort of like in Maven, wanting to use exclusions in a DependencyManagement, which as far as I know is not yet supported in Maven either. But it’s also something that seems perfectly reasonable to want to do.

Background for the curious:

The actual motivation for wanting to rid ourselves of this file is that it’s a file which is apparently really hard to convert to Kotlin DSL, and every other file I try to convert to Kotlin DSL ultimately comes back to this file being the blocker. So as soon as I can either rid our project of this file, or convert it to Kotlin, life gets a lot better overall.

The Kotlin equivalent way to do this file seems to be to write extension functions for DependencyHandler, which is very different to the Groovy way, which makes it hard to do the transition without duplicating all dependencies. Having Groovy world stuff and Kotlin world stuff share the same information seems really challenging at times.

Some more stuff I tried today to no avail:

1. Declaring the dependencies on an object:

object Libraries {
    val acme = dependencies.create("com.acme:acme-detonator").apply {
        this as ModuleDependency
        exclude(group = "com.acme", module = "acme-detcord")
    }
}

Theoretically you could then use this like Libraries.acme, but it doesn’t work because of some bug in either Gradle or the Kotlin compiler which I filed earlier but which is almost certainly a duplicate because this stuff just doesn’t seem like an uncommon thing to try.

I’m not sure whether you’d then also have to put it into project.extra or whether the new type would just be visible from elsewhere. It doesn’t really matter right now because it won’t even compile.

2. Declaring the dependencies on a class and then putting an instance of that into extra

class Libraries {
    val acme = dependencies.create("com.acme:acme-detonator").apply {
        this as ModuleDependency
        exclude(group = "com.acme", module = "acme-detcord")
    }
}

val libraries by project.extra { Libraries() }

Theoretically you could then use this like libraries.acme (similar to what it looks like in Groovy even, so it may have even aided migration!), but again, same compiler error.

3. The same, but with inner class

This was a bit of a desperate stab.

inner class Libraries {
    val acme = dependencies.create("com.acme:acme-detonator").apply {
        this as ModuleDependency
        exclude(group = "com.acme", module = "acme-detcord")
    }
}

val libraries by project.extra { Libraries() }

This does compile, but then you can’t use the libraries value anyway, because you need to declare its type when you use it, and you can’t reference the inner class from another file. So that’s another bust.

X. One “working” solution

It is possible to do this:

val libraries by project.extra {
    mapOf(
        "acme" to dependencies.create("com.acme:acme-detonator").apply {
            this as ModuleDependency
            exclude(group = "com.acme", module = "acme-detcord")
        }
    )
}

That does work, but every time you use it, it looks like libraries["acme"]!!, which is pretty awful to look at.