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

时间:2015-12-30 18:19:48

标签: java android annotation-processing

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

计划是让处理器以两种模式运行:

  • Mode 1 :生成代码 A

  • Mode 2 :生成代码 A B

只有在处理器生成代码的环境中存在附加(可选)包时,才应选择

Mode 2

如果可选包存在,有没有办法在注释处理器的process方法中找到

编辑1:

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

我举一个小例子:

  • 假设我们有一个(单模块)项目Sample
  • Sample正在使用我的TestProcessor
  • 我们以Square's Picasso作为外部库的示例
  • 如果SampleSquare's Picasso作为其依赖项之一,则TestProcessor Mode 2 中运行并生成代码{{ 1}}和A。换句话说:如果您可以使用Bcom.square.picasso)中的类而没有任何问题,那么处理器应该在 Sample 中运行。
  • 如果Mode 2个依赖关系中没有Square's Picasso,则Sample's TestProcessor 中运行,并仅生成代码{{ 1}}。

编辑2:

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

  1. 为两个Mode 1 A 使用两种类型的注释(例如:processorModes
  2. 使用第二种类型的注释(应该在@DoStuffModeOne上使用)触发 @DoStuffModeTwo 的使用(例如:Application
  3. 对于我的情况,第二种解决方法更为可取,但仍然很多Mode 2本身可以决定哪个 @TriggerModeTwo <更糟糕 / strong>选择。

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

您可以使用此代码来确定注释处理环境中是否存在类。

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

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

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

我希望这会有所帮助。

答案 2 :(得分:0)

除了JBirdVegas建议的解决方案;此函数可用于在运行时检查外部库中是否存在包

public static boolean packageExists(String packagePath) {
  return Thread.currentThread().getContextClassLoader().getResource(packagePath) != null;
}

用法:

packageExists("apackage/innerpackage")