Gradle 创建 Task 的写法不是 Groovy 的标准语法吧?
任务名居然是以标识符的形式写出来的,你们难道没有觉得奇怪吗?
1 | task clean(type: Delete) { |
它定义了一个叫做 “clean” 的任务,这个任务的类型是 Delete。
其中 Delete 是一个类的名字,这是 Groovy 的语法,相当于 Delete.class。这个还好,至少人家语法上支持这样做。
后面的 { … } 有 Kotlin 经验的小伙伴们自然也不会觉得陌生,这肯定是接收一个 Lambda (在 Groovy 当中就是 Closure)作为参数,里面的 delete rootProject.buildDir
则等价于 delete(rootProject.buildDir)
,这也是 Groovy 的语法,在 Groovy 当中只要不引起歧义,函数的调用是可以去掉括号的,类似的例子有很多:
1 | dependencies { |
这里的 classpath 也是如此。
这都很容易理解。那么问题来了,task clean(...){ ... }
这是个什么语法?我们定义一个名叫 “clean” 的任务,这个任务名不应该是一个字符串字面量吗,但现在按照 Groovy 的语法,它应该等价于 task(clean(...){ ... })
,这个 clean 看上去其实是个方法名,而不是一个常量。
如果大家跟我一样一开始就绞尽脑汁地去研究这个玩意究竟是什么 Groovy 语法,那你从一开始就错了。这个答案直到我们在翻阅 Gradle 源码的时候,看到有一个叫做 TaskDefinitionScriptTransformer 的类,这个类在 Gradle 脚本编译运行的第二个阶段时被调用,它和其他几个类似的 Transformer 一样,作用就是对源代码的语法树做了一些转换。
大家在 Gradle 源码当中找到这个类之后就会发现,注释已经写的非常清晰了,例如:
1 | if (args.getExpression(0) instanceof MapExpression && args.getExpression(1) instanceof VariableExpression) { |
通过注释我们可以看到,task 实际上是被当做函数来调用的,我们也确实可以在 Project 当中找到它的定义:
这个映射实际上就是给 identifier 加了个引号,变成字符串字面量。注意到 transformVariableExpression(call, 1);
的第二个参数 1 对应的就是 <identifier>
,第二个分支里面的位置则是 0。
这个方法的实现也很显而易见:
1 | private void transformVariableExpression(MethodCallExpression call, int index) { |
除了这个转换以外,还有很多其他的情况,现在我们的问题是文章一开始提到的 task clean(...){ ... }
应当属于那种转换?属于嵌套方法调用的转换。前面我们已经分析到这个写法其实可以等价于 task(clean(...){ ... })
,对应的转换在 maybeTransformNestedMethodCall
方法当中给出了实现,我们摘录一部分给大家了解一下:
1 | private boolean maybeTransformNestedMethodCall(MethodCallExpression nestedMethod, MethodCallExpression target) { |
mapArg 是否为 null,对应了 task 方法的两个重载版本:
1 | Task task(String name, Closure configureClosure); |
这么来看,文章开头提到的创建任务的写法,实际上相当于:
1 | task(type: Delete, "clean") { |
其他类似的 Transformer 大家可以自行分析。
C 语言是所有程序员应当认真掌握的基础语言,不管你是 Java 还是 Python 开发者,欢迎大家关注我的新课 《C 语言系统精讲》:
扫描二维码或者点击链接《C 语言系统精讲》即可进入课程
Kotlin 协程对大多数初学者来讲都是一个噩梦,即便是有经验的开发者,对于协程的理解也仍然是懵懵懂懂。如果大家有同样的问题,不妨阅读一下我的新书《深入理解 Kotlin 协程》,彻底搞懂 Kotlin 协程最难的知识点:
扫描二维码或者点击链接《深入理解 Kotlin 协程》购买本书
如果大家想要快速上手 Kotlin 或者想要全面深入地学习 Kotlin 的相关知识,可以关注我基于 Kotlin 1.3.50 全新制作的入门课程:
扫描二维码或者点击链接《Kotlin 入门到精通》即可进入课程
Android 工程师也可以关注下《破解Android高级面试》,这门课涉及内容均非浅尝辄止,除知识点讲解外更注重培养高级工程师意识:
扫描二维码或者点击链接《破解Android高级面试》即可进入课程