Я хочу добавить общее поле в некоторые классы во время компиляции. С этой целью я реализовал свои собственные классы аннотации и трансформации АСТ, следуя официальному 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>
во время выполнения.
Спасибо. Он работает, но если я изменю 'make (HashSet)' на 'новый ClassNode (HashSet)', я получаю сообщение об ошибке. Что между ними другое? – vahidreza
Честно говоря, я не знаю, но ClassNode не следует напрямую инициировать. эти методы обрабатывают кеширование, сглаживание и другие вещи, необходимые при создании байт-кодов. –