当前位置: 首页 > 知识库问答 >
问题:

GroovyAST在编译时添加泛型字段

穆招
2023-03-14

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

但是我在编译时得到了这个错误:

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

我做错了吗?

示例代码

例如,假设我想添加一个< code>HashSet

我的 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 {
}

笔记

当我删除行长哈希集类.set一般类型([新泛型类型(新类节点(长.class)]]作为泛型类型[]);时,一切都很好,但x的类型是哈希集而不是哈希集


共有1个答案

慕宏儒
2023-03-14

您应该使用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))
 类似资料:
  • 问题内容: 在关于反射的本教程中,它指出: […]因为泛型是通过类型擦除实现的,因此在编译过程中会删除有关泛型类型的所有信息 我的知识是使用泛型,以便在编译时编译器可以检查类型安全性。即失败快速方法。但是该链接提到类型擦除会在编译期间删除通用信息。 问题答案: 您引用的语句是正确的:编译器在编译过程中在内部使用通用类型信息,在处理源时会生成与类型相关的错误。然后,一旦完成验证,编译器将生成类型擦除

  • 以下代码: 给出编译器错误: 此行有多个标记-类型列表中的方法add(capture#1-of?extends String)不适用于参数(String)-方法add(capture#1-of?)类型列表中的不适用于参数(字符串) 是什么导致了这个错误?我应该不能添加Strings或它的子类型,因为我正在类型参数中扩展String吗?

  • 问题内容: 有三种方法可以实现泛型: 只是用于编译时间检查的工具,但是每个模板实例都被编译为相同的字节/汇编代码实现(如注释“类型擦除”实现中所述的Java) 每个模板实例均被编译为专用代码(C ++,C#) #1和#2的组合 在Swift中实现哪一个? 问题答案: Swift首先会编译一个执行动态类型检查的实现,但是当速度与代码大小之间的权衡是有意义的时候,优化器可以选择为特定类型克隆专门的实现

  • 问题内容: 我正在尝试使用泛型实现以下结构。收到编译器错误,无法找出原因。 这个想法是译者使用T作为字典中键的类型。例如,可以是字符串或枚举。子类提供具体的字典。 但是它失败,因为:“类型’String’不符合协议’Hashable’” 但是String符合Hashable。它也不适用于Int,后者也符合Hashable。 如果删除类型约束,则仅用于测试(在此我还必须禁用字典,因为我不能在其中使用

  • 问题内容: 我不得不发现我的项目中有Java代码,该代码可以在Eclipse中编译并正常运行,但是会在javac中引发编译错误。 一个完整的代码段: javac中的编译返回: 现在,此错误阻止在Maven中构建项目。由于Eclipse编译器具有更高的容忍度,因此我现在不得不假设代码段的定义和用法如上所述,静态方法不是有效的Java吗? 问题答案: 似乎Sun的1.6 JDK无法推断正确的类型。以下

  • 我得到编译器错误在最后一行,我可以知道为什么吗?即使整数扩展了数字,我也会得到以下错误