升级到 Gradle 2.2 后,methodMissing 不再被调用

methodMissing no longer being called on extension after upgrading to Gradle 2.2

我们的构建使用 gradle 中的自定义插件扩展,它具有动态方法。这在 gradle 2.1 中工作正常,但在 2.2 中不再调用 methodMissing 并且我得到以下异常(这是部分原因):

Caused by: org.gradle.api.internal.MissingMethodException: Could not find method common() for arguments [api] on org.gradle.api.internal.artifacts.dsl.DefaultComponentModuleMetadataHandler_Decorated@1bef1304.
at org.gradle.api.internal.AbstractDynamicObject.methodMissingException(AbstractDynamicObject.java:68)
at org.gradle.api.internal.AbstractDynamicObject.invokeMethod(AbstractDynamicObject.java:56)
at org.gradle.api.internal.CompositeDynamicObject.invokeMethod(CompositeDynamicObject.java:172)
at org.gradle.api.internal.artifacts.dsl.DefaultComponentModuleMetadataHandler_Decorated.invokeMethod(Unknown Source)
...

如何使用 gradle 2.2 让动态函数在我们的构建系统中工作?

背景:

这些动态方法有多种用途,其中之一是简化项目对其他项目的依赖(这是一个非常大的系统,有超过 80 个子项目,每个子项目可能有多个命名 API(public,内部、附加组件等))。

这是我的插件应用:

void apply(Project project) {
   project.subprojects.each { subproject ->
      subproject.extensions.create("modules", ModuleExtension.class ) }
}

ModuleExtension 没有除 methodMissing 之外的变量或函数:

def methodMissing(String name, args)
{
    //return project dependency based on name/args. This no longer gets called in 2.2!
}

gradle 文件中的示例用法:

dependencies {
   compile module.nameOfModule( "name of api" )
}

我还在 ModuleExtension 中覆盖了以下内容,只是为了看看它们是否被调用,但它们没有:

def invokeMethod(String name, args)
def propertyMissing(String name)
def propertyMissing(String name, value)

我实际上无法在 Gradle 2.2 中重现此问题。但是,这是对 Gradle 扩展的某种滥用。如果你只是想要一个全局可用的对象,我会简单地将它添加为一个额外的项目 属性。这具有不必为每个子项目创建的额外好处,因为项目从其父项目继承属性。

ext {
    modules = new ModuleExtension()
}

编辑: 这是因为 Gradle 2.2 引入了对 module replacements 的新支持。 dependencies 块中的符号 modules 现在委托给 ComponentModuleMetadataHandler 而不是您的分机。您要么必须将分机重命名为 modules 以外的名称,要么使用 project.modules.nameOfModule.

限定呼叫