理解 gradle 任务定义中的常规语法

我对 Gradle 和 Groovy 还是个新手,试图理解在 Groovy 层面上定义分级任务时会发生什么。

task hello  {
println "configuring task hello"
doLast {
println "hello there"
}
}

通过阅读“ Gradle In Action”一书,我知道 task hello {}实际上是对常规 Project接口的 task()方法的调用。在第77页,它显示了在 Project接口上有4个称为 task 的方法

task(args: Map<String,?>, name:String)
task(args: Map<String,?>, name:String, c:Closure)
task(name: String)
task(name: String, c:Closure)

我知道 {}是闭合体。

我不明白的是,groovy 是如何根据 https://stackoverflow.com/a/25592665/438319解释 task hello { }中的 hello的? 有一个 groovy 编译器插件可以将 task hello { }转换成 task('hello', { })

我的问题:

  • 我在哪里可以找到关于做转换的 Gradle Groovy 编译器插件的信息?

  • 是否声称 Gradle 脚本是 Groovy 程序在技术上是不正确的,因为 Gradle 以某种方式扩展了 Groovy 编程语言?

  • 有没有办法让 gradle命令打印出编译器插件运行后生成的基础 groovy 代码?

7730 次浏览

Gradle uses AST Transformations to extend the Groovy syntax. The task definition syntax you mention is just one of the transformations Gradle applies. You can find the implementation for that transform here. To answer your specific questions:

  • The individual transforms that Gradle applies are not specifically documented anywhere that I'm aware of. You could however look at the other classes in the same package of the link above.

  • Gradle scripts support a super-set of Groovy syntax. Any valid Groovy is also valid in a Gradle script, however, a Gradle script is not necessarily (and typically not) valid "default" Groovy.

  • There isn't a way to get an output of the equivalent Groovy code since it's the actual abstract syntax tree that is being manipulated in-memory.

If you want to know more about it check transformVariableExpression function in the gradle source code in TaskDefinitionScriptTransformer class

private void transformVariableExpression(MethodCallExpression call, int index) {
ArgumentListExpression args = (ArgumentListExpression) call.getArguments();
VariableExpression arg = (VariableExpression) args.getExpression(index);
if (!isDynamicVar(arg)) {
return;
}


// Matches: task args?, <identifier>, args? or task(args?, <identifier>, args?)
// Map to: task(args?, '<identifier>', args?)
String taskName = arg.getText();
call.setMethod(new ConstantExpression("task"));
args.getExpressions().set(index, new ConstantExpression(taskName));
}

it converts task args?, <identifier>, args? or task(args?, <identifier>, args?) to task(args?, '<identifier>', args?) it finds the task definition in the build.gradle and add quotes around the identifier(task name) so groovy can compile it without problem.