2016-07-29 5 views
2

Я хочу добавить общее поле в некоторые классы во время компиляции. С этой целью я реализовал свои собственные классы аннотации и трансформации АСТ, следуя официальному documentation и комментируя желаемые классы с аннотацией AST.GroovyAST добавить общее поле во время компиляции

Но я получаю эту ошибку во время компиляции:

org.codehaus.groovy.control.MultipleCompilationErrorsException: запуск не удалось: /home/.../groovy/Sample.groovy: -1: Преобразование использовало генерические файлы, содержащие ClassNode java.util.HashSet для поля x напрямую. Вы не должны это делать. Создайте новый ClassNode со ссылкой на старый класс ClassNode и используйте новый ClassNode вместо старого. В противном случае компилятор создаст неверные дескрипторы и потенциальное исключение NullPointerException в TypeResolver в OpenJDK. Если это не ваше собственное дело, сообщите об этом ошибке писателю преобразования. @ строка -1, столбец -1.

Я допустил ошибку?

Примеры кодов

Например, предположим, что я хочу, чтобы добавить HashSet<Long> поле, названное x, к каждому классу аннотированный по MyAST аннотацию.

Мой класс АСТ аннотаций:

@Retention(RetentionPolicy.SOURCE) 
@Target(ElementType.TYPE) 
@GroovyASTTransformationClass(classes = [MyASTTransformation.class]) 
public @interface MyAST { 
} 

Мой класс преобразования АСТ:

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

@Override 
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)); 
    clazz.addField(field); 
} 
} 

Образец аннотированный класс:

@MyAST 
public class Sample { 
} 

Примечание

Когда я удаляю линию longHashSetClass.setGenericsTypes([new GenericsType(new ClassNode(Long.class))] as GenericsType[]);, все в порядке, но тип x - HashSet вместо HashSet<Long> во время выполнения.

ответ

2

Вы должны использовать ClassHelper или GenericUtils для того, чтобы создать ClassNode:

import static org.codehaus.groovy.ast.ClassHelper.make 
import static org.codehaus.groovy.ast.tools.GenericsUtils.makeClassSafeWithGenerics 

... 

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

Спасибо. Он работает, но если я изменю 'make (HashSet)' на 'новый ClassNode (HashSet)', я получаю сообщение об ошибке. Что между ними другое? – vahidreza

+0

Честно говоря, я не знаю, но ClassNode не следует напрямую инициировать. эти методы обрабатывают кеширование, сглаживание и другие вещи, необходимые при создании байт-кодов. –