vahidreza vahidreza - 1 year ago 84
Groovy Question

GroovyAST add generic field at compile time

I want to add a generic field to some classes at compile time. To this objective, I was implement my own AST annotation and transformation classes by following the official documentation and annotate desired classes with AST annotation.

But I am getting this error at compile time:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
/home/.../groovy/Sample.groovy: -1: A transform used a generics containing ClassNode java.util.HashSet for the field x directly. You are not supposed to do this. Please create a new ClassNode referring to the old ClassNode and use the new ClassNode instead of the old one. Otherwise the compiler will create wrong descriptors and a potential NullPointerException in TypeResolver in the OpenJDK. If this is not your own doing, please report this bug to the writer of the transform.
@ line -1, column -1.

Have I made a mistake?

Sample codes

For example, suppose I want to add a
field, named
, to every class annotated by

My AST annotation class:

@GroovyASTTransformationClass(classes = [MyASTTransformation.class])
public @interface MyAST {

My AST transformation class:

@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
public class MyASTTransformation implements ASTTransformation {

public void visit(ASTNode[] nodes, SourceUnit sourceUnit) {
ClassNode clazz = (ClassNode) nodes[1];
ClassNode longHashSetClass = new ClassNode(HashSet.class);
longHashSetClass.setGenericsTypes([new GenericsType(new ClassNode(Long.class))] as GenericsType[]);
FieldNode field = new FieldNode("x", FieldNode.ACC_PRIVATE, longHashSetClass, clazz, new ConstantExpression(null));

Sample annotated class:

public class Sample {


When I eliminate the line
longHashSetClass.setGenericsTypes([new GenericsType(new ClassNode(Long.class))] as GenericsType[]);
, everything is OK but type of
instead of
at runtime.

Answer Source

You should use ClassHelper or GenericUtils in order to create a ClassNode :

import static org.codehaus.groovy.ast.ClassHelper.make
import static


ClassNode hashSet = makeClassSafeWithGenerics(HashSet, make(Long))