【问题标题】:GroovyAST add generic field at compile timeGroovyAST 在编译时添加通用字段
【发布时间】:2016-07-29 22:26:55
【问题描述】:

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

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

org.codehaus.groovy.control.MultipleCompilationErrorsException:启动失败: /home/.../groovy/Sample.groovy:-1:转换使用包含 ClassNode java.util.HashSet 的泛型直接用于字段 x。你不应该这样做。请参照旧的 ClassNode 创建一个新的 ClassNode 并使用新的 ClassNode 而不是旧的。否则编译器将在 OpenJDK 的 TypeResolver 中创建错误的描述符和潜在的 NullPointerException。如果这不是您自己做的,请将此错误报告给转换的作者。 @ 第 -1 行,第 -1 列。

我是不是搞错了?

示例代码

例如,假设我想将一个名为xHashSet<Long> 字段添加到每个由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[]); 行时,一切正常,但x 的类型在运行时是HashSet 而不是HashSet<Long>

【问题讨论】:

    标签: generics groovy abstract-syntax-tree bytecode groovyc


    【解决方案1】:

    您应该使用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))
    

    【讨论】:

    • 谢谢。它有效,但如果我将make(HashSet) 更改为new ClassNode(HashSet),我会收到错误消息。它们之间有什么不同?
    • 老实说,我不知道,但 ClassNode 不应该直接实例化。这些方法在生成字节码时处理缓存、别名和其他必要的事情。
    猜你喜欢
    • 1970-01-01
    • 2021-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多