Подтвердить что ты не робот

Как проверить, существует ли пакет изнутри обработчика аннотаций (во время компиляции)?

Я создаю Аннотационный процессор для Android (ради будущих объяснений, позвоните ему TestProcessor).

План предназначен для работы процессора в двух режимах:

  • Mode 1: генерация кода A

  • Mode 2: генерация кода A и B


Mode 2 следует выбирать, только если дополнительный (дополнительный) пакет существует в среде, для которой процессор генерирует код.

Есть ли способ узнать в методе обработки аннотаций process, если существует дополнительный пакет?


РЕДАКТИРОВАТЬ 1:

Небольшое уточнение в пакете "(необязательно)". Под дополнительным пакетом я подразумеваю пакет java, который может, но не должен существовать в проекте (который использует процессор). Дополнительный пакет может представлять собой, например, содержимое внешней библиотеки. Внешняя библиотека может, но не должна быть включена в проект.

Позвольте мне сделать небольшой пример:

  • Предположим, что мы имеем (одномодульный) проект Sample.
  • Sample использует мой TestProcessor.
  • Возьмем Square's Picasso в качестве примера внешней библиотеки
  • Если Sample HAS Square's Picasso как одна из его зависимостей, TestProcessor работает в Mode 2 и генерирует код A и B. Другими словами: если вы без проблем можете использовать классы из com.square.picasso (in Sample), то процессор должен работать в Mode 2.
  • Если в Sample's зависимостей нет Square's Picasso, TestProcessor работает в Mode 1 и генерирует только код A.

ИЗМЕНИТЬ 2:

Я думал о двух обходных решениях для этой проблемы:

  • Использование двух типов аннотаций для двух processor Modes (пример: @DoStuffModeOne, @DoStuffModeTwo)
  • Используя второй тип аннотации (который должен использоваться, например, для Application), который запускает использование Mode 2 (пример: @TriggerModeTwo)

В моем случае второе решение намного предпочтительнее, но все же намного хуже, чем было бы, если бы сам TestProcessor мог решить, какой Mode выбрать.

4b9b3361

Ответ 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");

У меня не было успеха с использованием метода Elements.getPackageElement(), потому что он успешно вернулся для несуществующих пакетов (по крайней мере, в Eclipse), и запуск метода PackageElement.getEnclosedElements() на созданных пакетах был пуст даже для непустых пакеты. Я предлагаю вам перейти к определенному классу в интересующем вас пакете, как в моем предыдущем примере, потому что он работал как ожидалось для существующих элементов типа и возвращал null для несуществующих типов.

В настоящее время я не нашел метод на основе API обработки аннотаций, чтобы решить, будет ли найденный таким образом элемент типа основан на файле исходного кода на исходном пути вашего проекта или двоичном файле класса в пути к классам компиляции. Может быть метод для этого, включающий processingEnvironment.getFiler().getResource(StandardLocation.SOURCE_PATH, ...), но, к сожалению, не переносимый, потому что StandardLocation.SOURCE_PATH не поддерживается в Eclipse.

Надеюсь, это поможет.

Ответ 3

В дополнение к предложению JBirdVegas; Эта функция может использоваться для проверки того, существует ли пакет во внешних библиотеках во время выполнения.

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

Использование:

packageExists("apackage/innerpackage")