确定 Java 注释处理器中类型的稳定性

Identify stability of types in Java annotation processor

我想编写一个注释处理器,它根据已处理类型的一组 JavaBeans 属性生成源代码。

这通常有效,但如果周围有其他注释处理器,我很难正确地做到这一点。具体来说,此类其​​他处理器可能会为我的处理器处理的类型生成一个 super-class,因此我还需要考虑该超类型的属性。在随后的一轮中,可能会生成该超级class的超级class,依此类推。

这意味着在我感兴趣的类型的层次结构稳定之前我不能生成我的源代码,即在后续轮次中不会生成更多的超类型(或在同一轮中,在我的处理器已经运行) 由其他处理器。

我怎样才能知道是否是这种情况?我知道 RoundEnvironment#processingOver() 以及在最后一轮中生成我的代码的可能性,但我知道这是一种不好的做法(编译器会发出警告)。

当您说要基于 JavaBeans 属性集触发源代码生成时,我假设您指的是 getter/setter 对,无论如何这不是您问题的主题。

一般不制定 JSR 269 规范,以便协调多个注释处理器。这是设计使然,所有处理器都应该是幂等的(意味着相同的输入 -> 相同的输出)。

所以像 "I must not generate my source code until the hierarchy of the type is stable" 这样的事情是不可能在不破解法律程序的情况下实现的。检测稳定性是javac的职责。

禁止在最后一轮生成代码,因为最后一轮的唯一目的是让您的处理器释放未释放的资源。如果其他处理器做同样的事情,你就有危险了!所以这对我来说是不行的。

我能想到的唯一可能的解决方案是声明您的处理器正在处理所有注释(这可以通过指定 "*"" 作为您处理的注释来实现)。我不确定这是否会阻止必须验证的其他处理器。但如果可行,每次生成新文件时都会调用您的处理器。然后你会正常处理它们,convergence 东西会被 javac 正常检测到。

我不是 100% 确定这些解决方案,但它们可能值得一试。

回答我自己的问题:

如果注释类型的所有超类型都没有错误,则可以认为注释类型是稳定的或完整的。一个例子:

@GenClass("Base")
class MyAnnotatedType extends Base {}

我们假设 @GenBase 有一个注解处理器 A,它在本例中生成指定的 class、Base。另一个处理器 B 对 MyAnnotatedType 的整个层次结构感兴趣,例如它想为所有 MyAnnotatedType 方法生成某种描述符,包括继承的方法。

如果B先于A运行,Baseclass还不存在,所以当B查看MyAnnotatedType的层级时,super-class类型的镜像将具有类型 ERROR。 B 可以以此为指示将 MyAnnotatedType 的处理推迟到下一轮。

A 运行时,它会生成 Base class,导致另一轮处理。

如果现在B第二次运行,它可以处理上一轮延迟的所有类型。由于 Base 现在存在,它将不再具有类型 kind ERROR。为此,我注意到(使用 javac)重要的是获得一个新的 Element 表示类型,而不是保留第一轮中仍然包含对错误超类型的引用的那个。

如果Base本身没有错误的超类型,MyAnnotatedType的层次结构就完成了,B可以继续处理它。否则,处理将不得不再次推迟,直到层次结构最终完成。如果永远不会生成超类型,无论如何编译都会以错误结束,对于 B,在这种情况下不生成它的代码也应该没问题。