I want to develop a Groovy AST transformation to add some methods on certain classes. So I write an annotation class and corresponding transformation class. Then I annotate a java class with my Groovy AST annotation.
When I compile the java annotated class with embedded groovy compiler (for example by this snippet: Class enhancedClass = new GroovyClassLoader().parseClass(new File("..."));
), the transformation is performed and methods are added to the compiled class which is called enhancedClass
in the snippet.
But I cann't compile the java class with Gradle groovy plugin and Intellij IDEA correctly.
QUESTION: Can everyone help me to working with Groovy AST transformation in Gradle and Intellij IDEA?
NOTE 1: I use Intellij IDEA 14 ultimate edition.
NOTE 2: My Groovy AST classes and the java annotated class and my "build.gradle" file are somethings like the followings:
Annotation class:
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
@GroovyASTTransformationClass(classes = {MyASTTransformation.class})
public @interface MyAST {
}
and Transformation class:
@CompileStatic
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
public class MyASTTransformation implements ASTTransformation {
@Override
public void visit(ASTNode[] nodes, SourceUnit sourceUnit) {
...
}
}
The java annotated class:
@MyAST
public class A {
...
}
The "build.gradle" file:
apply plugin: 'groovy'
sourceSets {
main {
groovy {
srcDirs = ['src/main/groovy', 'src/main/java']
}
java {
srcDirs = []
}
}
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.4'
}
I created my first custom AST transformation and I also ran into similar issues so sharing my limited experience. I'm using Groovy 2.4.7 and IntelliJ IDEA 2016.3.2. I was only able to use the custom transform annotation if:
I had first attempted doing it in the same project but that didn't work. I believe it's because the AST transformation occurs at compile time. Here's my example:
AST transformation project
Annotation
@Retention (RetentionPolicy.SOURCE)
@Target ([ElementType.TYPE, ElementType.METHOD])
@GroovyASTTransformationClass (classes = [SqlAssistTransform])
@interface SqlAssist {
}
Transformation
@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)
class SqlAssistTransform extends AbstractASTTransformation {
...
}
settings.gradle
rootProject.name = 'groovy-sql-transform'
build.gradle
...
group = 'com.company.groovy.transform'
version = '1.0-groovy-2.4'
description = 'Groovy AST transformation for SQL syntax'
...
Project using AST annotation
Annotated class
@SqlAssist
class Something {
...
}
Dependency example #1 - dependency on AST artifact from repository
build.gradle
... dependencies { ... // As long as your local repository (or remote repository) has the AST transformation project installed. ie Run '.\\gradlew install' in AST project to install to local repository compile group:'com.company.groovy.transform', name:'groovy-sql-transform', version: '1.0.0-groovy-2-4' ... } ...
Dependency example #2 - dependency on AST project
build.gradle
... dependencies { ... compile project(':groovy-sql-transform') ... } ...
settings.gradle
rootProject.name = 'project-name' // Assumption that AST project lives at the same level as this project include "groovy-sql-transform" project(":groovy-sql-transform").projectDir = new File("../groovy-sql-transform")
Testing
I didn't create a proper unit test, but I did use the following to test and debugged in IntelliJ so I could look at the AST in different places in my AST transformation code. Example test Groovy script that I had within the AST transformation project:
new GroovyShell(getClass().classLoader).evaluate '''
import com.company.groovy.transform.SqlAssist
@SqlAssist
class Testing {
...
}
'''
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.