Gradle 属性在扩展容器闭包内不可见

Gradle properties not visible inside extension container closure

我正在尝试为 Gradle 编写这个自定义插件,但我无法正确地将参数传递给插件。

在插件中,我正在创建如下扩展:

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

然后在 MyPluginData 中处理 def propertyMissing(String name, value) 以接收我期望的客户参数。

最后在客户端应用程序中 build.gradle 我正在尝试配置数据:

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 是在我的项目 gradle.properties 上定义的,我在构建过程中得到了以下日志:

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

当然,当收到 data_1 时 SOME_VALUE 为空,data_2 具有正确的值,数据 3 是我传递的硬​​编码字符串。


我的问题:

我做错了什么或者我的插件缺少哪个配置,以便客户端应用程序可以直接引用其 gradle.properties 文件中的属性?


编辑: 根据评论的要求

MyPluginData 只是 extends HashMap<String, MyPluginDataSet>MyPluginDataSet 只是几个字符串。

所以在 propertyMissing 中,我只是将 属性 名称添加到映射中,并使用字符串创建 MyPluginDataSet(稍后用于生成自定义任务) .

缺少的属性函数:

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()
}

通过使 MyPluginData 继承自 Map<>,我认为您以某种方式 "break" 属性 解析过程(参见 ExtensionAware)和 Gradle 不会尝试在不同范围内搜索 "SOME_VALUE" 属性(因此它不会从 gradle 属性扩展中找到此 属性)

也许您可以尝试通过存储内部映射而不是从 Map 继承来简化您 MyPluginData class?类似的东西:

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()
    }
}