最近,我想在Gradle项目中构建并应用本地ast转换。 虽然我可以找到一些有关如何编写转换的示例,但找不到完整的示例来显示完整的构建过程。 转换必须单独编译,然后放在类路径中,因此其源代码不能简单地放在Groovy源代码树的其余部分中。 这是让我绊倒了一段时间的细节。
最初,我设置了一个单独的GroovyCompile任务来处理其余注释,然后再处理其余注释(摘自Peter Niederwieser在Gradle论坛上的有用建议)。 在此可行的同时,要应用转换的一个更简单的解决方案是设置多项目构建。 主项目依赖于具有ast转换源文件的子项目。 这是一个最小示例的目录结构:
ast/build.gradle
ast构建文件
ast/src/main/groovy/com/cholick/ast/Marker.groovy
标记界面 ast/src/main/groovy/com/cholick/ast/Transform.groovy
AST转型 build.gradle
主构建文件 settings.gradle
项目层次结构配置 src/main/groovy/com/cholick/main/Main.groovy
转换源
对于完整的工作源(具有简单的测试,没有*导入),请克隆https://github.com/cholick/gradle_ast_example
根build.gradle文件包含对ast项目的依赖项:
dependencies {...compile(project(':ast'))
}
根settings.gradle定义ast子项目:
include 'ast'
基础项目还具有src / main / groovy / com / cholick / main / Main.groovy,其中包含要转换的源文件。 在此示例中,我编写的ast转换将名为“ added”的方法添加到类中。
package com.cholick.mainimport com.cholick.ast.Marker@Marker
class Main {static void main(String[] args) {new Main().run()}def run() {println 'Running main'assert this.class.declaredMethods.find { it.name == 'added' }added()}
}
在ast子项目中,ast / src / main / groovy / com / cholick / ast / Marker.groovy定义一个接口来标记ast转换的类:
package com.cholick.astimport org.codehaus.groovy.transform.GroovyASTTransformationClassimport java.lang.annotation.*@Retention(RetentionPolicy.SOURCE)
@Target([ElementType.TYPE])
@GroovyASTTransformationClass(['com.cholick.ast.Transform'])
public @interface Marker {}
最后,ast转换类处理源类并添加一个方法:
package com.cholick.astimport org.codehaus.groovy.ast.*
import org.codehaus.groovy.ast.builder.AstBuilder
import org.codehaus.groovy.control.*
import org.codehaus.groovy.transform.*@GroovyASTTransformation(phase = CompilePhase.INSTRUCTION_SELECTION)
class Transform implements ASTTransformation {void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {if (!astNodes) returnif (!astNodes[0]) returnif (!astNodes[1]) returnif (!(astNodes[0] instanceof AnnotationNode)) returnif (astNodes[0].classNode?.name != Marker.class.name) returnClassNode annotatedClass = (ClassNode) astNodes[1]MethodNode newMethod = makeMethod(annotatedClass)annotatedClass.addMethod(newMethod)}MethodNode makeMethod(ClassNode source) {def ast = new AstBuilder().buildFromString(CompilePhase.INSTRUCTION_SELECTION, false,"def added() { println 'Added' }")return (MethodNode) ast[1].methods.find { it.name == 'added' }}
}
感谢Hamlet D'Arcy提供的一个出色的AST转换示例,并感谢Peter Niederwieser在论坛上回答了我的问题 。
翻译自: https://www.javacodegeeks.com/2014/09/using-gradle-to-build-apply-ast-transformations.html