在Android Studio(以及可能的任何)Gradle文件中,以下代码有效:
task build {
}
即使只有一处微小的更改,也可能导致整个系统崩溃:
task build
{
}
这个问题在其他帖子中也提到过,但是在修复构建文件的上下文中。我的问题是为什么Gradle/Groovy不能处理两种括号样式?许多其他语言都可以很好地处理,那么这里有什么大不了的呢?
task build {
}
即使只有一处微小的更改,也可能导致整个系统崩溃:
task build
{
}
这个问题在其他帖子中也提到过,但是在修复构建文件的上下文中。我的问题是为什么Gradle/Groovy不能处理两种括号样式?许多其他语言都可以很好地处理,那么这里有什么大不了的呢?
实际上,错误信息中已经包含了所有信息:
build file '.../build.gradle': 80: Ambiguous expression could be a parameterless closure expression, an isolated open code block, or it may continue a previous statement;
solution: Add an explicit parameter list, e.g. {it -> ...}, or force it to be treated as an open block by giving it a label, e.g. L:{...}, and also either remove the previous newline, or add an explicit semicolon ';' @ line 80, column 1.
由于Groovy语法糖使得最后一个参数为lambda的方法看起来像语言结构一样,因此以下代码块:
task build {}
task build2(type: Copy) {}
等于它们更常见的形式:
task build({})
task build(type: Copy, {})
现在,你不希望使用大括号来界定普通的代码块,而是 Groovy lambda,该 lambda 应作为参数传递给 build
方法。
但从外观上看,当你在两行之间加入一个换行符时,Groovy 无法确定它是否真正作为前一行中传递给方法的 lambda,还是一个不相关的代码块。这就是错误消息中描述的歧义所在。
按照错误消息中的建议,您也可以使用以下语法,而不是使用转义换行符的语法:
task build
{ ->
}
build
)的task
关键字不是Groovy特定的,而是Gradle DSL功能。task build \
{
}
doLast \n{ ...
是可以工作的... 我认为这更多是在解析任务定义时的DSL问题。 - tim_yatesstatic
),它总是需要一个单一的闭包参数(https://docs.gradle.org/3.5/dsl/org.gradle.api.Task.html),而在gradle中跟随`task`关键字调用的方法都是动态的,所以无法确定它们应该具有什么参数? - Michal Mbuildscript
,plugins
等都是调用静态定义的方法,接受一个单一的Closure
类型参数。知道没有参数就不完整,所以没有歧义。task
有点特殊,因为它有一个Action
参数,这个参数是通过调用动态方法(这里是build
,但名称完全是任意的,没有区别)创建的,其确切的参数列表未定义,因此存在歧义。将动态方法调用强制转换为Action
实例的方式是Gradle DSL的复杂性。 - Michal M