Thursday, February 27, 2025

How can I use the Gradle documentation to find out how to add a plugin?

 I'm only trying to compile simple programs in Android Studio. However, Gradle proves to be a challenge, not least because of it's elliptic documentation.

1. How can I use the official Gradle documentation to find out which function is called in a Gradle script?
For example, the Android Studio's Empty Activity default configuration features a project_name/app/build.gradle.kts file that begins with this function call:

plugins {
    alias(libs.plugins.androidApplication)
    alias(libs.plugins.jetbrainsKotlinAndroid)
}

In order to find out which plugins function is called, I use the following information:

every Groovy build script is backed by an implicit instance of Project. If you see an unqualified element and you don’t know where it’s defined, always check the Project API documentation to see if that’s where it’s coming from.

On this page there is a plugins function. Now, to identify the alias functions called in the lambda argument, I searched alias and I found four functions: open fun alias(notation: Provider<PluginDependency>): PluginDependencySpec and alias(notation: ProviderConvertible<PluginDependency>): PluginDependencySpec, open override fun alias(notation: Provider<PluginDependency>): PluginDependencySpec and open override fun alias(notation: ProviderConvertible<PluginDependency>): PluginDependencySpec. They all return a PluginDependencySpec object, and therefore they are incompatible with the plugins function, which accepts Unit returning lambdas. Which alias is called depends on the delegate object and the type of the argument. I don't know how to find out any of them. I could not find the source code to find out the delegate object, and I could not find the type of the argument by searching the site.

However, if I hover the mouse over plugins in the script I get an infotip saying that the function is defined in org.gradle.kotlin.dsl.KotlinBuildScript as plugins(PluginDependenciesSpecScope.() -> Unit): Unit. The KotlinBuildScript abstract class declares two plugins functions, one of them indeed receives a PluginDependenciesSpecScope.() -> Unit function, as specified in the hint in the script next to plugins. But when I hover over the second alias, the infotip says that it returns a PluginDependencySpec object, not Unit. Indeed, there is an alias function in PluginDependenciesSpecScope that returns a PluginDependencySpec object, like the infotip says. Kotlin does not accept an incompatible return type. And how was I supposed to know, from the documentation, that the alias function is called with a PluginDependencySpec delegate object?

So the first strategy led me to this plugin and the second to this plugin. Also, both strategies feature an incompatible object type returned by the second alias. How am I supposed to use the official Gradle documentation to find out which functions are called in these four lines of code?

2. Both found plugins functions are deprecated in Gradle 9. Using them will trigger an error:
- the first one

Deprecated (with error)
The plugins {} block must not be used here. If you need to apply a plugin imperatively, please use apply<PluginType>() or apply(plugin = "id") instead.
- the second one has its whole class deprecated:
Deprecated
Will be removed in Gradle 9.0

They are supposed to be replaced by apply:
If you need to apply a plugin imperatively, please use apply() or apply(plugin = "id") instead.
project(":core") {
apply(plugin = "java")
}
The following statements make me believe that the plugins call can be replaced with an apply call with no repercussions on the rest of the script:
The plugins {} block serves a similar purpose to the apply method that can be used to apply a plugin directly to a Project object or similar. A key difference is that plugins applied via the plugins {} block are conceptually applied to the script, and by extension the script target. At this time there is no observable practical difference between the two approaches with regard to the end result.
link 

If you need to apply a plugin imperatively, please use apply() or apply(plugin = "id") instead.
project(":core") {
    apply(plugin = "java")
}

link

However, I utterly failed to find a solution. Many apply syntax constructs are accepted, but the plugin is not added. Please show me how it's done and also show me how you found out the solution from the official Gradle documentation site. Also, how do I find out what am I supposed to put in place of ":core" as an argument to project, if required.