Spec-Zone.ru › OpenJDK 24

Интерфейс обработчика аннотаций

Все известные реализующие классы:
AbstractProcessor
public interface Processor
Интерфейс для обработчика аннотаций.

Обработка аннотаций происходит в последовательности раундов. На каждом раунде обработчик может быть запрошен для обработки подмножества аннотаций, найденных в файлах исходного кода и классе, сгенерированных предыдущим раундом. Входные данные для первого раунда обработки — это исходные данные для выполнения инструмента; эти исходные данные можно рассматривать как выходные данные виртуального нулевого раунда обработки. Если обработчик был запрошен для обработки в данном раунде, он будет запрошен для обработки в последующих раундах, включая последний раунд, даже если для обработки нет никаких аннотаций. Инфраструктура инструмента также может попросить обработчик обработать файлы, сгенерированные неявно в ходе работы инструмента.

Каждая реализация обработчика должна предоставлять публичный конструктор без аргументов, который будет использоваться инструментами для создания экземпляра обработчика. Инфраструктура инструмента будет взаимодействовать с классами, реализующими этот интерфейс, следующим образом:

  1. Если существующий объект обработчика не используется, для создания экземпляра обработчика инструмент вызывает конструктор без аргументов класса обработчика.
  2. Затем инструмент вызывает метод init с соответствующей ProcessingEnvironment.
  3. После этого инструмент вызывает getSupportedAnnotationTypes, getSupportedOptions и getSupportedSourceVersion. Эти методы вызываются только один раз за запуск, а не на каждом раунде.
  4. По мере необходимости инструмент вызывает метод process для объекта обработчика; для каждого раунда не создается новый объект обработчика.
Если объект обработчика создается и используется без соблюдения вышеуказанного протокола, то поведение обработчика не определено этим спецификацией интерфейса.

Инструмент использует процесс обнаружения для поиска обработчиков аннотаций и определения того, следует ли их запускать. Настроив инструмент, можно управлять набором потенциальных обработчиков. Например, для JavaCompiler список кандидатных обработчиков для запуска можно установить непосредственно или управлять им с помощью пути поиска, используемого для поиска по типу службы. Другие реализации инструмента могут иметь различные механизмы конфигурации, такие как параметры командной строки; для получения подробной информации обратитесь к документации конкретного инструмента. Какие обработчики инструмент запросит для выполнения, зависит от интерфейсов аннотаций присутствующих в корневых элементах, от того, какие интерфейсы аннотаций поддерживает обработчик, и от того, требует ли обработчик интерфейсов аннотаций, которые он обрабатывает. Обработчик будет запрошен для обработки подмножества поддерживаемых им интерфейсов аннотаций, возможно, пустого набора. Для данного раунда инструмент вычисляет набор интерфейсов аннотаций, присутствующих в элементах, заключенных в корневые элементы. Если присутствует хотя бы один интерфейс аннотации, то по мере того, как обработчики заявляют о поддержке интерфейсов аннотаций, они удаляются из набора несопоставленных интерфейсов аннотаций. Когда набор пуст или больше нет доступных обработчиков, раунд завершен. Если интерфейсы аннотаций отсутствуют, обработка аннотаций все же происходит, но только универсальные обработчики, которые поддерживают обработку всех интерфейсов аннотаций, "*", могут претендовать на (пустой) набор интерфейсов аннотаций.

Интерфейс аннотации считается присутствующим, если по крайней мере одна аннотация этого интерфейса присутствует в элементе, заключенном в корневые элементы раунда. Для этой цели параметр типа считается заключенным в его обобщенный элемент. Для этой цели элемент пакета не считается содержащим классы и интерфейсы верхнего уровня в этом пакете. (Корневой элемент, представляющий пакет, создается при обработке файла package-info.) Аналогично, для этой цели элемент модуля не считается содержащим пакеты в этом модуле. (Корневой элемент, представляющий модуль, создается при обработке файла module-info.) Аннотации на использовании типов, в отличие от аннотаций на элементах, игнорируются при вычислении наличия интерфейса аннотации.

Аннотация считается присутствующей, если она соответствует определению наличия, данному в AnnotatedConstruct. Кратко, аннотация считается присутствующей для целей обнаружения, если она непосредственно присутствует или присутствует через наследование. Аннотация не считается присутствующей благодаря тому, что она обернута контейнерной аннотацией. В операционном плане это эквивалентно тому, что аннотация присутствует на элементе, если и только если она будет включена в результаты вызова Elements.getAllAnnotationMirrors(Element) для этого элемента. Поскольку аннотации внутри контейнерных аннотаций не считаются присутствующими, для правильной обработки повторяемых интерфейсов аннотаций, обработчики должны включать как интерфейс повторяемой аннотации, так и интерфейс содержащей аннотации в набор поддерживаемых интерфейсов аннотаций обработчика.

Обратите внимание, что если обработчик поддерживает "*" и возвращает true, все аннотации заявляются. Следовательно, универсальный обработчик, используемый, например, для реализации дополнительных проверок на валидность, должен возвращать false, чтобы не препятствовать выполнению других подобных проверок.

Если обработчик генерирует незахваченное исключение, инструмент может прекратить работу других активных обработчиков аннотаций. Если обработчик вызывает ошибку, текущий раунд завершится, а последующий раунд укажет на возникновение ошибки. Поскольку обработчики аннотаций выполняются в кооперативной среде, обработчик должен генерировать незахваченное исключение только в ситуациях, когда восстановление или отчет об ошибке невозможны.

Среда инструмента не обязана поддерживать обработчики аннотаций, которые обращаются к ресурсам среды, как в пределах каждого раунда, так и межраундово, в многопоточном режиме.

Если методы, возвращающие конфигурационную информацию об обработчике аннотаций, возвращают null, возвращают другие недопустимые входные данные или генерируют исключение, инфраструктура инструмента должна рассматривать это как условие ошибки.

Для повышения устойчивости при работе в разных реализациях инструмента обработчик аннотаций должен обладать следующими свойствами:

  1. Результат обработки заданного входного значения не зависит от наличия или отсутствия других входных значений (ортогональность).
  2. Обработка одного и того же входного значения порождает одинаковый результат (согласованность).
  3. Обработка входного значения A, за которой следует обработка входного значения B, эквивалентна обработке B, а затем A (коммутативность)
  4. Обработка входного значения не зависит от наличия выходного значения других обработчиков аннотаций (независимость)

Интерфейс Filer обсуждает ограничения на то, как обработчики могут работать с файлами.

Примечание к API:
Реализаторам этого интерфейса может быть удобно расширить AbstractProcessor, а не реализовывать этот интерфейс напрямую.
С:
1.6

Краткое описание методов

Модификатор и тип Метод Описание
Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText)
Возвращает инфраструктуре инструмента перечислитель предлагаемых завершений аннотации.
Set<String> getSupportedAnnotationTypes()
Возвращает имена интерфейсов аннотаций, поддерживаемых этим обработчиком.
Set<String> getSupportedOptions()
Возвращает параметры, распознаваемые этим обработчиком.
SourceVersion getSupportedSourceVersion()
Возвращает последнюю поддерживаемую версию исходного кода этим обработчиком аннотаций.
void init(ProcessingEnvironment processingEnv)
Инициализирует обработчик с помощью среды обработки.
boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
Обрабатывает набор интерфейсов аннотаций в корневых элементах, полученных из предыдущего раунда, и возвращает, были ли эти интерфейсы аннотаций приняты этим обработчиком.

Подробное описание методов

getSupportedOptions

Set<String> getSupportedOptions()
Возвращает опции, распознаваемые этим процессором. Реализация инструмента обработки должна предоставить способ передачи опций, специфичных для процессора, отличных от опций, передаваемых самому инструменту, см. getOptions.

Каждая возвращаемая строка должна быть последовательностью идентификаторов, разделённых точкой:

SupportedOptionString:
Identifiers
Identifiers:
Identifier
Identifier . Identifiers
Identifier:
Синтаксический идентификатор, включая ключевые слова и литералы

Инструмент может использовать эту информацию для определения того, являются ли какие-либо предоставленные пользователем опции нераспознанными ни одним процессором, в этом случае он может захотеть сообщить об этом предупреждением.

Возвращает:
опции, распознаваемые этим процессором, или пустой набор, если таких нет
См. также:
  • SupportedOptions

getSupportedAnnotationTypes

Set<String> getSupportedAnnotationTypes()
Возвращает имена поддерживаемых этим процессором интерфейсов аннотаций. Элемент результата может быть каноническим (полностью квалифицированным) именем поддерживаемого интерфейса аннотации. В качестве альтернативы, он может иметь вид "name.*", представляющий набор всех интерфейсов аннотаций с каноническими именами, начинающимися с "name.". В любом из этих случаев имя интерфейса аннотации может быть необязательно предваряемо именем модуля, за которым следует символ "/". Например, если процессор поддерживает "a.B", это может включать несколько интерфейсов аннотаций с именами a.B, которые находятся в разных модулях. Чтобы поддерживать только a.B в модуле foo, используйте "foo/a.B". Если имя модуля указано, то сопоставляется только аннотация в этом модуле. В частности, если имя модуля указано в среде, где модули не поддерживаются, например, в среде обработки аннотаций, настроенной для версии исходного кода источника без модулей, то интерфейсы аннотаций с именем модуля не сопоставляются. Наконец, "*" само по себе представляет набор всех интерфейсов аннотаций, включая пустой набор. Обратите внимание, что процессор не должен заявлять о поддержке "*", если он фактически не обрабатывает все файлы; объявление ненужных аннотаций может привести к замедлению производительности в некоторых средах.

Каждая возвращаемая строка должна приниматься следующей грамматикой:

SupportedAnnotationTypeString:
ModulePrefixopt TypeName DotStaropt
*
ModulePrefix:
ModuleName /
DotStar:
. *
где TypeName и ModuleName определены в Спецификации языка Java (6.5 Определение значения имени).
Примечание API:
При выполнении в среде, поддерживающей модули, процессорам рекомендуется включать префикс модуля при описании поддерживаемых интерфейсов аннотаций. Метод AbstractProcessor.getSupportedAnnotationTypes предоставляет поддержку для удаления префикса модуля при выполнении в среде без модулей.
Возвращает:
имена интерфейсов аннотаций, поддерживаемых этим процессором, или пустой набор, если таких нет
См. Спецификацию языка Java:
3.8 Идентификаторы
См. также:
  • SupportedAnnotationTypes

getSupportedSourceVersion

SourceVersion getSupportedSourceVersion()
Возвращает последнюю поддерживаемую версию исходного кода для этого процессора аннотаций.
Возвращает:
последнюю поддерживаемую версию исходного кода для этого процессора аннотаций
См. также:
  • SupportedSourceVersion
  • ProcessingEnvironment.getSourceVersion()

init

void init(ProcessingEnvironment processingEnv)
Инициализирует процессор с помощью среды обработки.
Параметры:
processingEnv - среда для средств, предоставляемых инструментом платформы процессору

process

boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
Обрабатывает набор интерфейсов аннотаций по корневым элементам, полученным с предыдущего раунда, и возвращает, заявлены ли эти интерфейсы аннотаций этим процессором. Если true возвращено, интерфейсы аннотаций заявлены, и последующим процессорам не будет предложено их обрабатывать; если false возвращено, интерфейсы аннотаций не заявлены, и последующим процессорам может быть предложено их обработать. Процессор может всегда возвращать то же булево значение или изменять результат в соответствии со своими критериями.

Вводной набор будет пустым, если процессор поддерживает "*", а корневые элементы не содержат аннотаций. Процессор Processor должен корректно обрабатывать пустой набор аннотаций.

Параметры:
annotations - интерфейсы аннотаций, запрошенные для обработки
roundEnv - среда для получения информации о текущем и предыдущих раундах
Возвращает:
являются ли интерфейсы аннотаций заявленными данным процессором

getCompletions

Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText)
Возвращает инфраструктуре инструмента набор предложенных дополнений к аннотации. Поскольку требуются дополнения, информация о предоставленной аннотации может быть неполной, как если бы речь шла о фрагменте исходного кода. Процессор может вернуть пустой итерируемый набор. Процессоры аннотаций должны сосредоточиться на предоставлении дополнений для членов аннотации с дополнительными ограничениями, известными процессору, например, для члена int, значение которого должно находиться в пределах от 1 до 10, или для строкового члена, который должен быть распознан известной грамматикой, такой как регулярное выражение или URL.

Поскольку моделируются неполные программы, некоторые из параметров могут содержать только частичную информацию или быть null. По крайней мере, один из element и userText должен быть не-null. Если element не является null, annotation и member могут быть null. Процессоры не должны выбрасывать NullPointerException, если некоторые параметры являются null; если у процессора нет дополнений, которые можно предложить на основе предоставленной информации, может быть возвращён пустой итерируемый набор. Процессор также может вернуть одно дополнение со строкой значения null и сообщением, описывающим причину отсутствия дополнений.

Дополнения информативны и могут отражать дополнительные проверки валидности, выполняемые процессорами аннотаций. Например, рассмотрим простую аннотацию:

 @MersennePrime {
    int value();
 }
 
(Простое число Мерсенна — простое число вида 2n - 1.) Учитывая AnnotationMirror для этого интерфейса аннотации, может быть возвращён список всех таких простых чисел в диапазоне int без проверки каких-либо других аргументов для getCompletions:
 import static javax.annotation.processing.Completions.*;
 ...
 return List.of(of("3"),
                of("7"),
                of("31"),
                of("127"),
                of("8191"),
                of("131071"),
                of("524287"),
                of("2147483647"));
 
Более информативный набор дополнений включал бы количество каждого простого числа:
 return List.of(of("3",          "M2"),
                of("7",          "M3"),
                of("31",         "M5"),
                of("127",        "M7"),
                of("8191",       "M13"),
                of("131071",     "M17"),
                of("524287",     "M19"),
                of("2147483647", "M31"));
 
Однако, если userText доступна, можно проверить, являются ли только подмножество простых чисел Мерсенна допустимыми. Например, если пользователь набрал
@MersennePrime(1
значение userText будет "1"; и возможны только два простых числа:
 return Arrays.asList(of("127",        "M7"),
                      of("131071",     "M17"));
 
Иногда ни одно дополнение не является допустимым. Например, нет простых чисел Мерсенна в заданном диапазоне, начинающихся с 9:
@MersennePrime(9
Соответствующим ответом в этом случае является либо возвращение пустого списка дополнений,
 return Collections.emptyList();
 
либо одно пустое дополнение с полезным сообщением
 return Arrays.asList(of("", "No in-range Mersenne primes start with 9"));
 
Параметры:
element - аннотируемый элемент
annotation - (возможно, частичная) аннотация, применяемая к элементу
member - член аннотации, для которого требуются возможные дополнения
userText - текст исходного кода, который должен быть дополнен
Возвращает:
предлагаемые дополнения к аннотации

© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://download.java.net/java/early_access/jdk24/docs/api/java.compiler/javax/annotation/processing/Processor.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API