generics - GroovyAST 在编译时添加通用字段

标签 generics groovy abstract-syntax-tree bytecode groovyc

我想在编译时向某些类添加通用字段。为了这个目标,我按照官方 documentation 实现了自己的 AST 注释和转换类。并使用 AST 注释来注释所需的类。

但是我在编译时收到此错误:

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.

我是不是搞错了?

示例代码

例如,假设我想添加 HashSet<Long>字段,名为 x ,对于每个由 MyAST 注释的类注释。

我的 AST 注释类:

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

我的 AST 转换类:

@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[]); 时,一切正常,但类型为 xHashSet而不是HashSet<Long>在运行时。

最佳答案

您应该使用ClassHelperGenericUtils来创建ClassNode:

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

...

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

关于generics - GroovyAST 在编译时添加通用字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38668346/

相关文章:

java - 在泛型列表的 Java 中传递 Class<T>?

java - Java 类定义中重载类型参数

swift - 创建一个 [字符串 : Class] dictionary in Swift 4

c# - 使用泛型的 WPF View/ViewModels - 如何?

Groovy - 从字符串中提取并显示子字符串

sql - 如何在 Grails/Hibernate : Message. countBy 中计数

grails - 如何使用grails 3.3.9在RestBuilder的post请求中发送 header

从表达式转换为图形 (DAG) 表示的算法

grails - 为什么 GORM 使用 methodMissing

haskell - 在 Haskell 中以通用方式扩充复杂数据类型