Slackbot
02/04/2022, 5:02 PMmelix
02/04/2022, 5:27 PMplugins {
id 'java-library'
}
def ext = repositories.extensions.create("my", MyExtension, repositories)
abstract class MyExtension {
private final RepositoryHandler repositories
@Inject
MyExtension(RepositoryHandler repositories) {
this.repositories = repositories
}
void foo() {
repositories.maven { it.url = "<https://foo.com>" }
}
}
Then you can use it in the Groovy DSL like this:
plugins {
id 'my-plugin'
}
repositories {
my.foo()
}
and in the Kotlin DSL:
plugins {
id("my-plugin")
}
repositories {
my.foo()
}
(note, for RepositoryHandler
this actually only works in 7.4, not before, but in general this is how it should work)
The drawback of this approach is that you cannot directly "extend" the repository handler type: the extension is scoped with a name.Leon Linhart
02/04/2022, 5:36 PMThe drawback of this approach is that you cannot directly "extend" the repository handler type: the extension is scoped with a name.I was trying to avoid the extension mechanism for that reason but I guess this is the best way until support for custom repository types is added then. Thanks!
Thomas Broyer
02/04/2022, 6:07 PMinvoke()
operator for Kotlin, and implements a call()
method for Groovy? Not entirely sure it'd actually work because of Gradle's special handling of extensions that be used as my { … }
with a closure/action.Vampire
02/04/2022, 6:49 PMVampire
02/04/2022, 6:51 PMFoo.kt
(not kts
, that's important, it must be in a .kt
even if you otherwise have a precompiled script plugin)
fun RepositoryHandler.foo() = maven("...")
this makes it usable from Kotlin DSL scripts.
And then add somewhere in your plugin
(repositories as ExtensionAware).extra["foo"] = delegateClosureOf<Any> { repositories.foo() }
which makes it usable from Groovy DSL.Vampire
02/04/2022, 6:51 PMrepositories { foo() }
from both DSLs.melix
02/05/2022, 1:35 PMVampire
02/05/2022, 4:36 PMVampire
02/06/2022, 1:55 AM.kt
file:
fun RepositoryHandler.foo() = maven("repo")
fun RepositoryHandler.foo(bar: String) = maven("string/$bar")
fun RepositoryHandler.foo(bar: Any) = maven("any/$bar")
And in the plugin code:
(repositories as ExtensionAware).extra["foo"] = object : Closure<Unit>(this, this) {
fun doCall(vararg args: Any) {
when (args.size) {
0 -> repositories.foo()
1 -> {
args.first().let {
when (it) {
is String -> repositories.foo(it)
else -> repositories.foo(it)
}
}
}
else -> throw NoSuchMethodException()
}
}
}
Thomas Broyer
02/06/2022, 11:19 AMopen class MyExtension @Inject constructor(
private val repositories: RepositoryHandler
) {
operator fun invoke() = repositories.maven(url = "…")
operator fun invoke(bar: String) = repoitories.maven(url = "string/$bar")
// for Groovy:
fun call() = invoke()
fun call(bar: String) = invoke(bar)
}
repositories.extensions.create<MyExtension>("my", repositories)
Still kind of ugly if you ask me, and I'm worried about forward compatibility.Vampire
02/06/2022, 11:34 PMRepositoryHandler
no Kotlin DSL accessors are generated, so you need to provide the extension functions.
And besides that, even with 7.4 RepositoryHandler
is not formally ExtensionAware
, so you still need to cast it.
Starting with 7.4 the invoke
methods for the extensions would work for the Kotlin DSL.
But just having a call
method still does not work for Groovy.
You need it to be a Closure
for it to work and then you also have to manually instantiate it.
So for Gradle 7.4 you could do it like
open class MyExtension : Closure<ArtifactRepository>(this, this) {
operator fun invoke() = repositories.maven(url = "repo")
operator fun invoke(bar: String) = repositories.maven(url = "string/$bar")
operator fun invoke(bar: Any) = repositories.maven(url = "any/$bar")
fun doCall() = invoke()
fun doCall(bar: String) = invoke(bar)
fun doCall(bar: Any) = invoke(bar)
}
(repositories as ExtensionAware).extensions.add<MyExtension>("foo", MyExtension())
For Gradle <7.4 (also compatible with 7.4+ of course) you need to do it like I suggested, but you can of course do it less ugly then I did originally,
for example like this:
in a `.kt`:
fun RepositoryHandler.foo() = maven("repo")
fun RepositoryHandler.foo(bar: String) = maven("string/$bar")
fun RepositoryHandler.foo(bar: Any) = maven("any/$bar")
and in your plugin:
(repositories as ExtensionAware).extensions.add("foo", object : Closure<ArtifactRepository>(this, this) {
fun doCall() = repositories.foo()
fun doCall(bar: String) = repositories.foo(bar)
fun doCall(bar: Any) = repositories.foo(bar)
})
Vampire
02/06/2022, 11:36 PM(repositories as ExtensionAware).extra["foo"] = object : Closure<Unit>(this, this) {
fun doCall() = repositories.foo()
fun doCall(bar: String) = repositories.foo(bar)
fun doCall(bar: Any) = repositories.foo(bar)
}