Allprojects block forces extension addition to be deferred to outside of plugin

I’m attempting to use the sonar gradle plugin, but this block is preventing me from extracting the logic out into a buildSrc plugin. Is there any way you could change how the extension is added to the plugin, as it interferes with wrapping the plugin in buildSrc.

For further information you can see this thread

You can also attempt to create a buildSrc plugin with the following (kotlin) code

class SonarPlugin : Plugin<Project> {
    override fun apply(project: Project): Unit = {
        if (!pluginManager.hasPlugin("org.sonarqube")) {
        tasks {
            project.afterEvaluate {
                withType<SonarQubeTask> {
                    extensions.configure<SonarQubeExtension>() {
                        if (project.hasProperty("sonar-test")) {
                            properties {
                                property("sonar.sources", "src/test")
                                property("sonar.tests", "")
                                property("sonar.coverage.exclusions", "src/**/*")
                                property("sonar.projectName", "${project.description} Tests")
                                property("sonar.projectKey", "${}.server:${}-tests")
                        } else {
                            properties {
                                property("sonar.projectName", "${project.description}")
                                property("sonar.projectKey", "${}.server:${}")

and see that it throws this error:

* What went wrong:
A problem occurred configuring root project 'spring'.
> Extension of type 'SonarQubeExtension' does not exist. Currently registered extension types: [ExtraPropertiesExtension]

According to a slack user,

By looking at the plugin source, they defer it by using the allprojects block:

I also noticed they are relying on a static map in their class; unsure how nicely that will play when different projects have different buildscript classpaths (i.e. if they have different classloaders, they may not share static state; if using the `plugins {}` block it might be alright, but if using `apply plugin:` it may not be).

To fix your problem, you need to defer when you try to access the extension.  I'd put in a request for _them_ to ditch the allprojects block there.  By my read, once one project has the plugin added, _only that project_ will get the task, and no others will (since they are using the extension as a marker to decide whether to add the task or not)

In any case, this block makes it impossible to create a company wide buildSrc or gradle plugin in order to simplify sonar property setting.


Sure, I’ll do the change to add the extension to all projects without using passing a closure to allprojects.
However, I would like to understand why it doesn’t work. My understanding is that the closure will be resolved immediately by doing a “cross configuration” of all projects with it.
Any idea what’s happening in your case?