如何使我的注解处理器实现增量编译?

13
我创建了一个注解处理器叫做EasyPrefs,但是当我尝试在我的项目中使用它时,会显示以下警告:

增量注释处理已请求,但由于以下处理器不是增量的,因此已禁用支持:net.androidcart.easyprefs.EasyPrefsProcessor(NON_INCREMENTAL)。

我进行了一些研究,但找不到任何关于如何使其增量的教程。是否需要任何Gradle配置,或者需要重写某些函数等?

推荐我喜好注解处理器: Metaline | 元线模块。我使用标志来保存布尔值(或短整型)的偏好设置。我正在尝试为Metaline启用增量编译,并通过使用Java反射绕过答案中提到的一些限制。 - KnIfER
1个回答

9
为了使您的注释处理器具有增量功能,您必须在 META-INF 中声明它,在 incremental.annotation.processors 文件中:
your.fully.qualified.annotation.processor.name,category

有三种选择注解处理器的类别:动态、隔离和聚合。

基本上在高层次上:

  • 动态:当您的处理器只能在运行时决定是否增量
  • 隔离:当您的处理器将与每个带有您注释的类型隔离地工作(一个输入对应一个或多个输出)
  • 聚合:当您的处理器需要聚合几个输入(带有您的注释的类型)以生成一个或多个输出时

但是,每个类别都有您必须考虑的限制:

动态限制

他们必须使用Filer API生成文件。以其他方式编写文件将导致后续的静默失败,因为这些文件不会被正确清除。如果您的处理器这样做,则无法进行增量处理。
他们不能依赖于特定于编译器的API,例如com.sun.source.util.Trees。Gradle包装处理API,因此尝试转换为特定于编译器的类型将失败。如果您的处理器这样做,则无法进行增量处理,除非您有某种回退机制。
如果他们使用Filer#createResource,则location参数必须是StandardLocation中的以下值之一:CLASS_OUTPUT、SOURCE_OUTPUT或NATIVE_HEADER_OUTPUT。任何其他参数都将禁用增量处理。
他们必须基于从其AST可达的信息来做出所有决策(代码生成、验证消息)来注释类型。这意味着您可以分析类型的超类、方法返回类型、注释等,甚至是传递的。但是,您不能基于RoundEnvironment中的不相关元素做出决策。这样做会导致静默失败,因为稍后将重新编译太少的文件。如果处理器需要根据否则不相关的元素组合做出决策,请将其标记为“聚合”。

他们必须为使用Filer API生成的每个文件提供一个确切的起始元素。如果提供了零个或多个起始元素,则Gradle将重新编译所有源文件。

聚合限制

他们只能读取CLASSRUNTIME保留注释

只有在用户传递-parameters编译器参数时,才能读取参数名称。

摘自Gradle documentation

PS:对于动态内容,您还需要重写 getSupportedOptions() 方法来指定类别:隔离或聚合。有关更多详细信息,请参见 Gradle 文档


文档中提到两个类别都有以下限制(不能使用Trees等)... - KnIfER

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接