gradle 你是否想过task hello为什么不会报错?

2 篇文章 0 订阅
2 篇文章 0 订阅

先来看一段代码,这是一个最简单常见的task

task hello{
	doLast{
		println'hello world!'
	}
}

hello是什么?它也不是String,之前也没有任何地方定义过hello。为什么不会报错?

书上《Android gradle权威指南》其中3.4中对于gradle task的说法错误有些多。
在这里插入图片描述

(a)task是Project类的create方法。

首先Project类中没有叫做create的方法,task是Project类中task方法的。只有在TaskContainer中才有create方法。

(b)对于task taskName { closure}此类语法的错误理解。

其文中对task hello{closure }的表述为

若是了解Groovy的相关知识,咱们能够知道,若是最后一个参数是闭包的时候,能够放到括号外面,而后方法的括号能够省略,就生成了上面咱们的写法,很简洁。

//模拟的task方法
def task(arg,closure){
    closure()
}

task "hello" {
    println "hello world!"//抛异常 groovy.lang.MissingMethodException: No signature of method:
}
//正确的groovy语法如下所示
task "hello",{
    println "hello world!"
}

task ("hello"){
    println "hello world!"

}

那么为什么是task taskName { closure}这样的语法。这和我之前学的任何groovy语法都对不上。

实际上这是gradle AST(抽象语法树)的功劳。它类似于java中注解Processor对功能类似,实际上是编译时,gradle替我们做了刚刚的两件事情。

先来看hello怎么变成了"hello"?

源码在TaskDefinitionScriptTransformer类中,源码地址

主要代码

						// 判断task后面的有几个表达式 如果是大于1个 例如 task hello {} 这种就有两个表达式匹配第一个if
						// Matches: task <arg>{1, 3} 
            if (args.getExpressions().size() > 1) {
            		//用于判断是否有<name-value-pairs>,identifier就是taskname,这里就是将taskname的索引传入transformVariableExpression方法
            		//<name-value-pairs>暂时不管是什么东西
                if (args.getExpression(0) instanceof MapExpression && args.getExpression(1) instanceof VariableExpression) {
                    // Matches: task <name-value-pairs>, <identifier>, <arg>?
                    // Map to: task(<name-value-pairs>, '<identifier>', <arg>?)
                    transformVariableExpression(call, 1);
                } else if (args.getExpression(0) instanceof VariableExpression) {
                    // Matches: task <identifier>, <arg>?
                    transformVariableExpression(call, 0);
                }
                return;
            }

            // Matches: task <arg> or task(<arg>) 
            // 下面就是匹配task hello 或者 task("hello") 这里主要看第一种情况所以后续代码就不贴了

再看调用的方法transformVariableExpression

				private void transformVariableExpression(MethodCallExpression call, int index) {
            ArgumentListExpression args = (ArgumentListExpression) call.getArguments();
            //获取到taskName的表达式
            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?)
            //获取taskname的string值
            String taskName = arg.getText();
            //调用task方法
            call.setMethod(new ConstantExpression("task"));
            //将taskName的字符串替换掉原本的表达式,从而实现了hello->"hello"的转化
            args.getExpressions().set(index, new ConstantExpression(taskName));
        }

到这里你应该明白,实际上会将task hello {} 映射成task(‘hello’,{})。

有人会问是什么?看task的几个重载方法,其中有一个是

Task task(Map<String,?> args,
          String name,
          Closure configureClosure)

对应的args的解释就是

A map of creation options can be passed to this method to control how the task is created.

也就是用于创建task的一些option可选的属性值。至于有哪些属性,可以看后面的Task 属性的第三点 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值