Budius
Budius

Reputation: 39836

Gradle properties not visible inside extension container closure

I'm trying to write this custom plugin for Gradle but I'm stuck in properly passing parameters to the plugin.

inside the plugin I'm creating an extension like following:

@Override void apply(final Project p) {
    p.extensions.create('myPlugin', MyPluginData.class)

then inside MyPluginData I'm handling def propertyMissing(String name, value) to receive the customer parameters I expect.

And finally inside the client application build.gradle I'm trying to configure the data:

println("From root value is " + SOME_VALUE)

myPlugin {
    println("From plugin value is " + SOME_VALUE)
    println("But from plugin 'findProperty' value is " + findProperty("SOME_VALUE"))
    clientDataSet = {
        data_1 = SOME_VALUE
        data_2 = findProperty("SOME_VALUE")
        data_3 = "this is a string"

SOME_VALUE is defined on my project gradle.properties, and I got the following log during build:

From root value is correct value from properties
From plugin value is null
But from plugin 'findProperty' value is correct value from properties

and then of course, while receiving data_1 SOME_VALUE is null, data_2 have the correct value and data 3 is the hard-coded string I passed.


My question:

What am I doing wrong or which configuration is missing on my plugin, so that the client application can directly reference properties from their gradle.properties files?


Edit: as requested on the comments

MyPluginData is simply extends HashMap<String, MyPluginDataSet> and MyPluginDataSet is just a few strings.

So inside propertyMissing I'm simply adding the property name to the map, and creating the MyPluginDataSet with the strings, (that later is used to generate custom tasks).

The missing property function:

def propertyMissing(String name, value) {
    // Create the new data set and add to the map
    def data = new MyPluginDataSet()
    put(name, data)

    // setup and execute the client closure to configure the data
    def closure = value as Closure
    closure.delegate = data
    closure.resolveStrategy = Closure.DELEGATE_FIRST
    closure.run()
}

Upvotes: 0

Views: 595

Answers (1)

M.Ricciuti
M.Ricciuti

Reputation: 12106

By making MyPluginData inherit from Map<>, I think you somehow "break" the property resolution process ( see ExtensionAware) and Gradle will not try to search for "SOME_VALUE" property in the different scopes (so it will not find this property from gradle properties extension)

Maybe you can try to simplify you MyPluginData class by storing an internal map instead of inheriting from Map ? something like that:

class MyPluginData {
    Map<String, MyPluginDataSet> internalMap = new HashMap<>()

    def propertyMissing(String name, value) {
        println "Entering propertyMissing for name = $name"
        // Create the new data set and add to the map
        def data = new MyPluginDataSet()
        internalMap.put(name, data)

        // setup and execute the client closure to configure the data
        def closure = value as Closure
        closure.delegate = data
        closure.resolveStrategy = Closure.DELEGATE_FIRST
        closure.run()
    }
}

Upvotes: 3

Related Questions