【问题标题】:what does the groovy compiler make of gradle dependsOn syntaxgroovy 编译器对 gradle 依赖语法做了什么
【发布时间】:2019-10-05 17:29:42
【问题描述】:

我了解 gradle DSL

task doTask { logger.info "some text" }

实际上将调用 Project 委托对象上的方法 task(String,Closure)。这或多或少是一种短手

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

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

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

我认为 groovy 会从 (dependsOn: 'otherTask') 创建一个映射,并且以某种方式使用 Project 方法

task(Map args, String name, Closure config)

将被调用。但是这些额外的括号是如何发挥作用的,为什么它们是必要的,groovy 是如何找出我们想要的呢?以我最小的常规技能,语法对我来说完全违反直觉。我永远不会想到我必须这样做才能使其发挥作用。

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

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

【问题讨论】:

  • groovy 中的 Gradle 构建脚本是 DSL,而不是普通的 groovy
  • @tim_yates:感谢您链接到另一个问题。那里的答案并没有为我的问题添加任何新内容,因此我不会认为它是重复的,尽管差异确实在于细微差别。 Marco R. 下面的回答实际上解决了我的问题。

标签: gradle groovy


【解决方案1】:

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

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

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

    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. 可以使用named parameters 语法调用接受单个MapMap 和闭包作为参数的方法;这会将每个 named 参数转换为映射中的一个条目,最后一个参数将是一个闭包。这将创建以下直观的语法变体:

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

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

Complete code on GitHub

希望这会有所帮助。

【讨论】:

  • 谢谢,太好了。我研究了你的例子,这对我有很大帮助!非常感谢!
猜你喜欢
  • 2014-04-05
  • 1970-01-01
  • 2019-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多