Gradle Settings plugin extension

Viewed 101

I want to create a settings plugin (not project plugin) to simplify some stuff, but I cannot get the configuration clause to work.

This is my plugin (Java code)

public class SettingsPlugin implements Plugin<Settings> {
    @Override
    public void apply(Settings target) {
        target.getExtensions()
              .create("modules", IncludeModulesExtension.class, target);

        System.err.println("Applied settings plugin");
    }
}

public class IncludeModulesExtension {
    private final Settings _settings;

    public IncludeModulesExtension(Settings settings) {
        _settings = settings;
    }

    public void include(String path) {
    }
}

My problem is, that gradle is not picking up the "modules" dynamic function in my settings.gradle.kts:

pluginManagement {
    ...
}

plugins {
    id("com.ieffects.gradle-tools.settings-server") version ("7.0.23-SNAPSHOT")
}

modules {
    
}

I omitted the pluginManagement, the plugin is found and applied, however the "modules" is not picked up. What is it I'm doing wrong?

Starting Gradle Daemon...
Gradle Daemon started in 2 s 396 ms
Applied settings plugin
e: /Volumes/Development/Git/server-framework-galcon/settings.gradle.kts:22:1: Unresolved reference: modules

FAILURE: Build failed with an exception.

* Where:
Settings file '/Volumes/Development/Git/server-framework-galcon/settings.gradle.kts' line: 22

* What went wrong:
Script compilation error:

  Line 22: modules {
           ^ Unresolved reference: modules

1 error
1 Answers

I faced the same issue when implementing a similar plugin, and although I didn't find out why, I did manage to work around it:

// SettingsExtensions.kt

import org.gradle.api.Action
import org.gradle.api.initialization.Settings
import org.gradle.api.plugins.ExtensionAware

/* WORKAROUND: for some reason a type-safe accessor is not generated for the extension,
* even though it is present in the extension container where the plugin is applied.
* This seems to work fine, and the extension methods are only available when the plugin
* is actually applied. */

/**
 * Retrieves the [modules][IncludeModulesExtension]
 * extension.
 */
val Settings.modules: IncludeModulesExtension
    get() =
        (this as ExtensionAware).extensions.getByName("modules") as IncludeModulesExtension

/**
 * Configures the [modules][IncludeModulesExtension] extension.
 */
fun Settings.modules(configure: Action<IncludeModulesExtension>): Unit =
    (this as ExtensionAware).extensions.configure("modules",
        configure)

As the comment explains, it behaves exactly the same as a generated type-safe accessor (same syntax and the extension is only available when the plugin is actually applied).

I didn't test if it works for the Groovy DSL, but since the extension methods are syntactically identical to the generated accessors, I assume it does.

Alternatively you can do without if instead of the modules DSL you do this in the settings script where the plugin is applied:

configure<IncludeModulesExtension> {
    ...
}

This also works because even though the type-safe accessor is not generated, the extension is properly initialized and added to the extensions container. But the DSL is obviously nicer.

Related