如何从注释处理器内部检查包是否存在(在编译时)?

2022-09-04 23:12:11

我正在为Android构建一个注释处理器(为了将来的解释,让我们称之为)。TestProcessor

该计划是让处理器在两种模式下运行:

  • 模式 1:生成代码 A

  • 模式 2:生成代码 AB


仅当处理器为其生成代码的环境中存在附加(可选)包时,才应选择模式 2

有没有办法在注释处理器的处理方法中找出可选包是否存在?


编辑1:

对“(可选)包”的小澄清。通过附加包,我的意思是一个java包,它可能但不必存在于项目中(即使用处理器)。例如,可选包可以表示外部库的内容。外部库可以但不必包含在项目中。

让我举个小例子:

  • 假设我们有一个(单模块)项目 。Sample
  • Sample正在使用我的 .TestProcessor
  • 让我们以外部库为例Square'sPicasso
  • 如果 HAS 作为其依赖项之一,则在模式 2 中运行并生成代码和 。换句话说:如果您可以使用(in)中的类而没有任何问题,那么处理器应该在模式2中运行。SampleSquare'sPicassoTestProcessorABcom.square.picassoSample
  • 如果依赖项中没有,则在模式 1 中运行并仅生成代码。Square'sPicassoSample'sTestProcessorA

编辑2:

我想到了这个问题的两个解决方法:

  1. 对两种模式使用两种类型的批注(例如:、processor@DoStuffModeOne@DoStuffModeTwo)
  2. 使用第二种类型的注释(例如,应在 上使用),这将触发模式 2 的使用(例如:Application@TriggerModeTwo)

对于我的情况,第二种解决方法更可取,但仍然比本身可以决定选择哪种模式要糟糕得多TestProcessor


答案 1

您可以检查应用程序类路径中的某个类。然后根据检查结果执行逻辑。ButterKnife

Class butterKnifeClass = null;
try {
    butterKnifeClass = Class.forName("butterknife.ButterKnife");
} catch (ClassNotFoundException e) {
    // no butterknife present
}
if (butterKnifeClass != null) {
    // blah... stuff with butterknife
}

答案 2

您可以使用此代码来查明批注处理环境中是否存在类。

TypeElement typeElement = processingEnvironment.getElementUtils().
    getTypeElement("com.squareup.picasso.Picasso");

我没有成功使用该方法,因为它成功地返回了不存在的包(至少在Eclipse下),并且在像这样创建的包上运行该方法即使对于非空包也是空的。我建议您在感兴趣的包中选择一个特定的类,就像我前面的示例一样,因为它对现有类型元素按预期工作,并为不存在的类型返回。Elements.getPackageElement()PackageElement.getEnclosedElements()null

我目前没有找到基于注释处理API的方法来确定以这种方式找到的类型元素是基于项目源路径上的源代码文件还是基于编译类路径上的二进制类文件。可能有一种方法可以解决这个问题,但不幸的是,它不是可移植的,因为在Eclipse中不受支持。processingEnvironment.getFiler().getResource(StandardLocation.SOURCE_PATH, ...)StandardLocation.SOURCE_PATH

我希望这有帮助。


推荐