看懂Gradle脚本(3)- Groovy AST转换
来源:互联网 发布:软件开发兼职协议 编辑:程序博客网 时间:2024/05/21 06:29
延续上一篇文章
上篇文章末尾有一段脚本,定义了一个Task:
task 'myTask' { doLast { println 'hello world!' } }我们已经知道,这段脚本其实是调用Project的task方法,并且传入两个参数:一个是Task的名字,另外一个是闭包,用来配置Task(在这段脚本中,给Task添加了一个Action)。
Task名的引号去哪儿了?
但是Gradle官方推荐的写法,是像下面这样定义Task:
task myTask { // <-- doLast { println 'hello world!' } }那么这个语法怎么解释呢?
用GroovyConsole观察AST
所谓AST,就是抽象语法树,简单的说,就是编译器分析完代码之后,生成的一个树形数据结构。我们用Groovy自带的GroovyConsole就可以观察AST。打开GroovyConsole,把脚本复制到编辑器中,然后按ctrl+t就可以看到AST,如下图所示:
可以看出来,上面的脚本会被编译器解释成下面这样:
task(myTask({ doLast({ println('hello world!') })}))也就是说,先调用myTask方法,然后再把返回结果当成参数,调用task方法。那么到底是不是这样呢?
AST转换
没有定义过myTask方法?这个好说,因为Groovy提供了强大的元编程机制,比如methodMissing方法,可以做到这一点。那么到底是不是这样呢?一番搜索之后,我认为我找到了正确答案:Gradle是利用AST转换来实现这种特殊语法的。为了给出确凿的证据,我找出了相关的Gradle源代码。最主要的两个类是org.gradle.groovy.scripts.internal.TaskDefinitionScriptTransformer 和org.gradle.groovy.scripts.internal.AstUtils。下面列出TaskDefinitionScriptTransformer的transformVariableExpression方法以供参考:
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)); }
结论
Gradle是通过AST转换来实现task定义特殊语法的,下面这三行代码完全等价:
task myTask {...}task 'myTask' {...}task('myTask', {...})
0 0
- 看懂Gradle脚本(3)- Groovy AST转换
- 看懂Gradle脚本(6)- Hello Groovy, Goodbye Getters&Setters
- 看懂Gradle脚本(1)- Groovy语言的Map语法糖
- 看懂Gradle脚本(2)- Groovy语言的闭包语法
- 看懂Gradle脚本(4)- Groovy语法之运算符重载
- 看懂Gradle脚本
- gradle-groovy脚本
- 看懂Gradle脚本(5)- 跟Gradle学领域驱动设计
- Gradle----Groovy
- nGrinder 的 Groovy 脚本使用指南(Groovy 脚本结构)
- gradle 知识(2) -- groovy语法
- groovy脚本
- nGrinder 的 Groovy 脚本使用指南(Groovy maven 结构)
- Groovy 1.8 新特性: 增强的 AST
- gradle学习(7)-groovy
- Gradle详解+Groovy
- Gradle与Groovy
- Groovy&Gradle总结
- Android 有趣架构
- Log4net学习笔记
- Intellij idea+maven创建项目
- Android中的Activity四种启动模式(launchMode)
- CORS实现跨域请求
- 看懂Gradle脚本(3)- Groovy AST转换
- ubuntu常用命令总结
- php 操作 mogodb
- Mysql----查看数据库大小
- springMVC 返回类型选择 以及 SpringMVC中model,modelMap.request,session取值顺序
- Linux下Java调用C
- SQL Profile 总结(一)
- [Python]socket使用
- 浅析count(1) count(*) count(col)的区别和性能