当处理器依赖注释值中的类时,选择Gradle增量注释处理器类别

时间:2019-09-09 23:04:38

标签: java gradle annotation-processing

我有一个简单的annotation processor,其用法如下:

@DiffElement(diffReceiver = Renderer.class)
class ViewState {
  String getHello();
  int getWorld();
}

class Renderer {
  void renderHello(String hello);
  void renderWorld(int world);
}

要使此处理器正常工作,get-函数的名称和Renderer-接口函数的参数必须匹配。它会对此进行检查,并使用批注的参数查看所提供的类,并基于该类进行一些代码生成。

它生成一个文件。

我已经阅读了Incremental annotation processing上的文档,但无法决定将哪个类别应用于此处理器。这是我的注意事项:

  • 它不能为isolating,因为它不能从带注释的元素的AST派生所有内容,因为它还从注释参数中检查一个类
  • 它不能为aggregating,因为它在Renderer类上没有任何注释,因此根据上述文档,每当Renderer类时都不会调用处理器进行更改,因为处理器尚未注册处理该文件,所以这将导致生成结果中的错误。

问题:

  • 我是否正确理解文档?还是可以将某些类别应用于此处理器
  • 如果它不在任何类别中,我怎么能告诉Gradle它不是增量的,所以“ kotlin kapt”之类的工具不会向用户抱怨我的处理器不是增量的

2 个答案:

答案 0 :(得分:2)

我是否正确理解文档?还是可以将某些类别应用于此处理器

关于处理器类别的文档确实很简短,并且我认为缺少示例。我花了很多时间弄清楚这些文档,它们为实验构建了一些简单的项目。因此,据我所知,如果我最终弄清楚了它们,可以应用一个类别:)

你这么说

它不能隔离,因为它不是从带注释的元素的AST派生所有内容,因为它还从注释参数中检查一个类

这并不完全正确,我将解释原因。 如documentation中所述,隔离处理器

必须根据其AST可获得的信息,为带注释的类型做出所有决策(代码生成,验证消息)。这意味着您可以甚至可传递地分析类型的超类,方法返回类型,注释等。

“甚至传递”这一短语在这里非常重要-这意味着,您不仅可以分析带注释的类型的AST,而且还可以分析方法的某些类型(例如返回类型的AST),然后再分析一个超类。该类型...

据我了解,您可以通过AST漫游从带注释的元素中发现的每种类型都是带注释的类型的依赖项(或通常称为元素)。而且,如果更改了依赖项,则依赖项类型需要重新编译。因此,当Renderer类更改时,{strong> {strong>将重新编译并因此被重新处理,因为它引用 ViewState 作为其注释论点。超类型,超接口,方法的返回类型,方法参数的类型,注释类参数,...-所有这些都被视为依赖类型。

因此,您的注释处理器实际上可以隔离


P.S。。如果隔离不起作用,则无论出于何种原因,请确保注释保留为Renderer或更高。

P.P.S。我发现注释处理中的增量是一个非常阴暗的主题,充满了惊喜和水下岩石。我为自己发现的经验法则是,几乎每个经过一些调整的处理器都可以隔离,除非它确实需要根据许多输入生成一个实体。而且,重要的是,只有这些输入在引用方面可以完全彼此无关,甚至可以在不同的库中。

答案 1 :(得分:0)

  

它不能聚合,因为它在Renderer类上没有任何注释,因此根据上述文档,Renderer类更改时将不会调用处理器,因为处理器尚未注册处理该文件,因此会导致生成结果出错。

这不是直接的答案,但是我认为它仍然可以回答您的问题:据我所知,这句话是您问题的真正根源。任何轻度增量系统都会使您失望,而不仅仅是Gradle的“聚合”模式(例如,尽管在这里我有不同的结果,但尝试在一个简单的Eclipse项目中甚至在IntelliJ中使用您的处理器)。

如果您实际上要强制执行对未注释类型的更改将导致注释处理器再次运行,则不得将注释处理器限制为该注释,而必须从{返回神奇的"*"值{1}},表示任何更改的类都必须触发处理器才能重新运行。 From the Javadoc for this method

  

最后,“ *”本身代表所有注释类型的集合,包括空集合。注意,除非处理器实际上正在处理所有文件,否则不应声明“ *”;声称不必要的注释可能会导致某些环境下的性能下降。

理想情况下,您只需做第二个(或第三个等)注释来提供此提示,但这并不总是可行的,这就是为什么允许使用此通配符选项的原因