Gradle 的时髦编译器如何取决于语法



我知道 gradle DSL

task doTask { logger.info "some text" }

实际上将在项目委托对象上调用方法任务(字符串,闭包)。这或多或少是

task("doTaks", {logger.info("some text")})

没事。但是当我试图理解我在第三方构建脚本中看到的一些gradle DSL语法时,事情变得复杂了:

task doTask (dependsOn: 'otherTask'){logger.info "some text"}

我认为 groovy 将从中创建地图(取决于:"otherTask"),并且以某种方式使用 Project 方法

task(Map args, String name, Closure config)

将被召唤。但是这些额外的括号是如何发挥作用的,为什么它们是必要的,groovy 如何弄清楚我们在这里想要什么?语法对我来说看起来完全违反直觉,以我最小的时髦技能。我永远不会想到我必须这样做才能让它工作。

所以,这就是问题所在:groovy 如何弄清楚如何处理这个命令:

task doTask (dependsOn: 'otherTask'){ // some code }

您可以使用以下语法之一调用 groovy 方法:

  1. 参数必须全部用逗号分隔在括号内:

    method(arg1, arg2, ..., argN, argClosure)
    
  2. 参数必须全部以逗号分隔,不带括号:

    method arg1, arg2, ..., argN, argClosure
    
  3. 如果最后一个参数是闭包,则所有前面的参数都必须在括号内以逗号分隔,并且右括号后面的代码块(在大括号内{...})将被解释为最后一个Closure参数argClosure

    method(arg1, arg2, ..., argN) { ... }
    

    如果您不希望将大括号中的代码块解释为上述方法调用的Closure参数;则以分号结束方法调用:

    // Because of `;` following { ... } is not a Closure argument for `method`
    method(arg1, arg2, ..., argN); { ... }
    
  4. 可以使用命名参数语法调用接受单个MapMap和闭包作为参数的方法;它将每个命名参数转换为映射中的一个条目,最后一个参数将是闭包。这将创建以下直观的语法变体:

    method(name1: arg1, name2: arg2, ..., nameN: argN, argClosure)
    method name1: arg1, name2: arg2, ..., nameN: argN, argClosure
    method(name1: arg1, name2: arg2, ..., nameN: argN) { ... }
    

Groovy提供了大量的语法糖,所以可以围绕这一点找到其他直观的变体;但这让你感受到Groovy处理Closure参数的方式。

以下是执行方法调用的这些不同方法的工作演示:

import java.time.LocalDateTime
def handleWithClosure(data1, data2, closure) {
closure("$data1. $data2")
}
def logger = { println "${LocalDateTime.now()} - $it" }
handleWithClosure(1, 'All within parenthesis', logger)
handleWithClosure 2, 'All without parenthesis', logger
handleWithClosure(3, 'List of arguments within parenthesis and closure outside') { logger(it) }
def handleMapWithClosure(map, closure) {
handleWithClosure(map['num'], "[Named Arguments/Map based] ${map['msg']}", closure)
}
handleMapWithClosure(msg: 'All within parenthesis', num: 1, logger)
handleMapWithClosure msg: 'All without parenthesis', num: 2, logger
handleMapWithClosure(msg: 'List of arguments within parenthesis and closure outside', num: 3) { logger(it) }

运行它,您可以看到它如何处理所有这些语法选项。

GitHub 上的完整代码

希望这有帮助。

最新更新