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

注释处理器是否有可能访问在前一轮中生成的类型?

漆雕令秋
2023-03-14
package tmp;

@MyAnnotation
public class Foo {
  private Foo me;
  private FooId myId;
}
@SupportedAnnotationTypes("tmp.proc.MyAnnotation")
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class CreateIdProcessor extends AbstractProcessor {
  @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    for (Element elem : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
      System.out.println("Writing ID for " + elem.getSimpleName());
      try {
        Writer file = processingEnv.getFiler().createSourceFile(elem + "Id").openWriter();
        file.write(String.format("package tmp; public class %sId {}", elem.getSimpleName()));
        file.close();
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
    return false;
  }
}
@SupportedAnnotationTypes("tmp.proc.MyAnnotation")
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class CheckIdProcessor extends AbstractProcessor {
  @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    for (Element elem : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
      for (Element element : elem.getEnclosedElements()) {
        System.out.printf("%s = %s (%s)\n", element.getSimpleName(), element.asType(), element.asType().getKind());
      }
    }
    return false;
  }
}
Writing ID for Foo
<init> = ()void (EXECUTABLE)
me = tmp.Foo (DECLARED)
myId = FooId (ERROR)

编译一切都很好,但是第二个处理器将myid类型视为错误,即使它是由第一个处理器生成的(而且FooId类确实在输出jar中)。这阻止了注释处理器分析fooid,例如找出它所属的包以便导入它。这个问题有什么解决办法吗?

共有1个答案

田柏
2023-03-14

Java注释过程以轮为单位执行其工作。在每一轮中,它将运行所有适用的注释处理器,然后编译输出。注释处理器API还跟踪处理了哪些类,并且只处理一次。您遇到的问题是,createidprocessor生成类的过程与checkidprocessor查找类的过程相同。因为fooidcheckidProcessory运行之前没有编译,所以调用getEncellseDelements()返回的元素是error元素。

简而言之,第二个处理器将fooid字段类型视为错误,因为fooid的源代码已经生成,但尚未编译。

你可以做一个实验。这个注释处理器将打印出在给定轮中处理的所有新类。fooid显示在round:1下,而foo显示在round:0下:

Round: 0
Foo = tmp.Foo (DECLARED)
<init> = ()void (EXECUTABLE)
me = tmp.Foo (DECLARED)
myId = FooId (ERROR)
Writing ID for Foo
Round: 1
FooId = tmp.FooId (DECLARED)
Round: 2
Round: 3
@SupportedAnnotationTypes("*")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class OutputRoundProcessor extends AbstractProcessor {
  private int round = 0;
  @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    System.out.println("Round: " + round);
    for (Element element : roundEnv.getRootElements()) {
      System.out.printf("%s = %s (%s)\n", element.getSimpleName(), element.asType(), element.asType().getKind());
    }
    round++;
    return false;
  }
}
 类似资料:
  • 问题内容: 我已经使用JAXB编写了许多类进行序列化,并且我想知道是否存在一种基于注释为每个对象生成XSD文件的方法。有这个工具吗? 喜欢的东西是 真棒 。有什么可以做的吗? 问题答案: 是的,您可以在JAXBContext上使用该方法: 您可以利用实现控制输出的位置:

  • 我必须在扩展Composite的GWT客户机类上实例化一个由我的自定义注释处理器生成的类。生成的类也与此视图位于同一个包中。但是,当我运行超级开发模式(SDM)时,我得到以下错误。 常规的GWT编译不会产生错误。但是,我在SDM编译时得到了错误。 如何使GWT SDM编译此视图?

  • 众所周知,我们可以像ProjectLombook的工作人员一样,使用自定义注释和Java注释处理器自动生成代码。但是我们可以从编译的源代码中删除带注释的代码吗? 我试着在网上搜索它,但只出现了“生成代码”主题和“如何生成带有一个注释的服务器”教程。当我在寻找从prod应用程序“编译”调试消息的方法时,我想到了这一点。我可以理解,拥有调试/测试和生产代码不是一个好的实践,但有时需要保持简单。我认为这

  • 我目前正在尝试用Kotlin为Android编写一个注释处理器。项目结构如下: 项目/构建.gradle 注释/build.gradle 样品/build.gradle Annotation.kt AnnotationProcessor.kt 使用kapt,构建在示例javaPreCompileDebug上中断,并显示以下消息: 当我用注释处理器替换 kapt 时,构建在示例:转换类上中断了以下消

  • 我正在使用注释处理器来处理方法参数的注释。 用于参数的注释类型有一个注释@参数 现在,当注释处理器运行时,我想检查参数注释()是否有参数注释。我通过执行以下代码来实现这一点。 由于某种原因,arg始终为空。是否有注释未返回的原因?