首页 > 解决方案 > Gradle 任务语法:如何从 Groovy 的角度进行解释?

问题描述

我很难理解 Gradle 的 Groovy DSL 是如何工作的。

不幸的是,Gradle 是我在日常工作中遇到的 Groovy 的主要用例,而且我注意到对于许多开发人员来说,他们完全通过 Gradle 接触到 Groovy。因此,大多数 Gradle 用户对 Groovy 的掌握非常有限。

在我对 Groovy 的有限理解中,以下tokenA tokenB { tokenC }所有标记都不是语言关键字的 sintaxtokenA将是我们使用参数调用的方法,tokenB最后一个参数是闭包。我想我是正确的,但我知道我错了,因为在 tokenB 之后可能需要一个逗号才能使分析正确。

正如您已经知道的那样,我绝不是 Groovy 开发人员,而且我认为在不学习 Groovy 基础知识的情况下使用 Gradle 是一件坏事,因为它限制了我充分利用其功能。但我唯一可行的选择是通过示例学习而不不幸地学习理论。

我确实检查了一些类似的问题,例如这个问题,但没有对我来说足够清晰或完整的答案。

TL;博士

  1. task myTask { doLast {} }Groovy 中如何解释标记?
  2. Gradle 是否使用标准的 Groovy 解释器?
  3. myTask当有task和没有def或后面有类型时,如何将其解释为标识符?
  4. 如果稍后在文件中我添加myTask { dependsOn myOtherTask }了如何解释?

标签: gradlegroovydsl

解决方案


我相信这一切都很时髦,没有什么特别的。这是您需要了解的常规概念。

  1. 如果方法的最后一个参数是闭包,则可以将闭包放在方法参数的右括号之后。
class MyClass {
   void doStuff(String name, Closure c) {
      c.call()
   } 
} 

def o = new MyClass() 
o.doStuff('x') {
   println "hello" 
} 
  1. 您可以在您的对象上实现缺少的方法。如果有人试图调用一个不存在的方法,你可以做一些事情
class MyClass {
    def methodMissing(String name, args) {
        println "You invoked ${name}(${args})" 
    }
} 
def o = new MyClass() {
   o.thisMethodDoesNotExist('foo')
}
  1. 您可以在闭包上设置委托
class MyBean {
   void include(String pattern) {...} 
   void exclude(String pattern) {...} 
} 
class MyClass {
   private MyBean myBean = new MyBean() 
   void doStuff(Closure c) {
      c.setDelegate(myBean)
      c.call()
   } 
} 

def o = new MyClass() 
o.doStuff {
   include 'foo' 
   exclude 'bar' 
} 

这 3 个 groovy 特性几乎解释了 gradle 脚本中发生的让 Java 开发人员摸不着头脑的“神奇”行为。

所以,让我们分解你的片段

task myTask(type:Foo) { 
   doLast {...} 
}

让我们添加一些括号并添加隐式项目引用。让我们也将闭包提取到一个变量中

Closure c = { 
   doLast {...} 
}
project.task(project.myTask([type: Foo.class], c)) 

project.myTask(...)方法不存在,行为最终通过methodMissing功能实现。Gradle 会将闭包上的委托设置为任务实例。因此闭包中的任何方法都将委托给新创建的任务。

最终,这就是逻辑上所说的

Action<? extends Task> action = { task ->
   task.doLast {...} 
}
project.tasks.create('myTask', Foo.class, action)

参见TaskContainer.create(String, Class, Action)


推荐阅读