美文网首页
看懂Gradle脚本(3)- Groovy AST转换

看懂Gradle脚本(3)- Groovy AST转换

作者: zheting | 来源:发表于2018-01-01 12:33 被阅读61次
    task myTask { 
        doLast {    
            println 'hello world!'    
        }    
    }  
    

    这段脚本Task名 myTask 的引号去哪儿了?

    • 用GroovyConsole观察AST
      所谓AST,就是抽象语法树,简单的说,就是编译器分析完代码之后,生成的一个树形数据结构。我们用Groovy自带的GroovyConsole就可以观察AST。打开GroovyConsole,把脚本复制到编辑器中,然后按ctrl+t就可以看到AST,如下图所示:
      AST

    可以看出来,上面的脚本会被编译器解释成下面这样:

    task(myTask({   
        doLast({   
            println('hello world!')  
        })  
    })) 
    

    也就是说,先调用myTask方法,然后再把返回结果当成参数,调用task方法。

    • AST转换

      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', {...})  
    

    相关文章

      网友评论

          本文标题:看懂Gradle脚本(3)- Groovy AST转换

          本文链接:https://www.haomeiwen.com/subject/ykhtnxtx.html