Интерфейс Обработчик Аннотаций
- Все известные реализующие классы:
AbstractProcessor
public interface Processor
Интерфейс для обработчика аннотаций.
Обработка аннотаций происходит в последовательности раундов. В каждом раунде обработчик может быть запрошен на обработку подмножества аннотаций, найденных в исходных и классных файлах, произведённых предыдущим раундом. Входные данные для первого раунда обработки являются начальными входными данными для выполнения инструмента; эти начальные входные данные могут рассматриваться как выходные данные виртуального нулевого раунда обработки. Если обработчик был запрошен на обработку в данном раунде, он будет запрошен на обработку в последующих раундах, включая последний раунд, даже если для него нет аннотаций для обработки. Инфраструктура инструмента также может попросить обработчик обработать файлы, сгенерированные неявно в результате работы инструмента.
Каждая реализация Processor должна предоставлять публичный конструктор без аргументов, который будет использоваться инструментами для создания экземпляра обработчика. Инфраструктура инструмента будет взаимодействовать с классами, реализующими этот интерфейс, следующим образом:
- Если существующий объект
Processorне используется, для создания экземпляра обработчика инструмент вызывает конструктор без аргументов класса обработчика. - Далее, инструмент вызывает метод
initс подходящейProcessingEnvironment. - После этого инструмент вызывает
getSupportedAnnotationTypes,getSupportedOptionsиgetSupportedSourceVersion. Эти методы вызываются только один раз за выполнение, а не в каждом раунде. - По мере необходимости, инструмент вызывает метод
processобъектаProcessor; новый объектProcessorне создаётся для каждого раунда.
Инструмент использует процесс обнаружения для поиска обработчиков аннотаций и принятия решения о том, следует ли их запускать. Настройка инструмента позволяет управлять набором потенциальных обработчиков. Например, для JavaCompiler список кандидатов в обработчики для запуска может быть установлен напрямую или контролироваться путем поиска, используемым для поиска по типу служб. Другие реализации инструментов могут иметь различные механизмы конфигурации, такие как опции командной строки; для получения подробностей обратитесь к документации конкретного инструмента. Какие обработчики инструмент запросит на запуск, зависит от типов аннотаций присутствующих на корневых элементах, от того, какие типы аннотаций поддерживает обработчик и от того, требует ли обработчик обработки типов аннотаций. Обработчик будет запрошен на обработку подмножества типов аннотаций, которые он поддерживает, возможно, пустого множества. Для данного раунда инструмент вычисляет множество типов аннотаций, которые присутствуют в элементах, вложенных в корневые элементы. Если присутствует хотя бы один тип аннотации, то по мере того, как обработчики заявляют о типах аннотаций, они удаляются из набора несопоставленных типов аннотаций. Когда набор становится пустым или больше нет доступных обработчиков, раунд завершён. Если типов аннотаций нет, обработка аннотаций всё равно происходит, но только универсальные обработчики, которые поддерживают обработку всех типов аннотаций, "*", могут заявить о (пустом) наборе типов аннотаций.
Тип аннотации считается присутствующим, если присутствует хотя бы одна аннотация этого типа на элементе, вложенном в корневые элементы раунда. В этой связи параметр типа считается вложенным в его обобщённый элемент. Для этой цели элемент пакета не считается содержащим верхнеуровневые типы в этом пакете. (Корневой элемент, представляющий пакет, создаётся при обработке файла package-info). Аналогично, для этой цели элемент модуля не считается содержащим пакеты в этом модуле. (Корневой элемент, представляющий модуль, создаётся при обработке файла module-info). Аннотации на использованиях типов, в отличие от аннотаций на элементах, игнорируются при вычислении наличия или отсутствия типа аннотации.
Аннотация присутствует, если она соответствует определению присутствия, данному в AnnotatedConstruct. Вкратце, аннотация считается присутствующей для целей обнаружения, если она напрямую присутствует или присутствует через наследование. Аннотация не считается присутствующей в силу того, что она обернута в контейнерную аннотацию. Оперативно это эквивалентно тому, что аннотация присутствует на элементе, если и только если она будет включена в результаты вызова Elements.getAllAnnotationMirrors(Element) для этого элемента. Поскольку аннотации внутри контейнерных аннотаций не считаются присутствующими, для правильной обработки повторяемых типов аннотаций, обработчикам рекомендуется включать как тип повторяемой аннотации, так и её контейнерный тип аннотации в набор поддерживаемых типов аннотаций обработчика.
Обратите внимание, что если обработчик поддерживает "*" и возвращает
true, все аннотации считаются затребованными. Поэтому универсальный обработчик, используемый, например, для реализации дополнительных проверок валидности, должен возвращать false, чтобы не препятствовать работе других таких проверок.
Если обработчик генерирует необработанное исключение, инструмент может прекратить работу других активных обработчиков аннотаций. Если обработчик вызывает ошибку, текущий раунд завершится, а последующий раунд укажет, что возникла ошибка. Поскольку обработчики аннотаций выполняются в кооперативной среде, обработчик должен генерировать необработанное исключение только в ситуациях, когда восстановление или отчёт об ошибках невозможны.
Среда инструмента не обязана поддерживать обработчики аннотаций, которые обращаются к ресурсам среды, как в пределах каждого раунда, так и между раундами, в многопоточном режиме.
Если методы, возвращающие конфигурационную информацию об обработчике аннотаций, возвращают null, возвращают другие недопустимые данные или генерируют исключение, инфраструктура инструмента должна рассматривать это как ошибку.
Чтобы обеспечить надёжность при работе с различными реализациями инструментов, обработчик аннотаций должен иметь следующие свойства:
- Результат обработки заданного входного значения не зависит от наличия или отсутствия других входных значений (ортогональность).
- Обработка одного и того же входного значения даёт один и тот же результат (согласованность).
- Обработка входного значения A, за которой следует обработка входного значения B, эквивалентна обработке B, за которой следует обработка A (коммутативность)
- Обработка входного значения не зависит от наличия выходных данных других обработчиков аннотаций (независимость)
Интерфейс 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
- 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:
-
.*
- Примечание API:
- При выполнении в среде, поддерживающей модули, процессоры рекомендуют включать префикс модуля при описании поддерживаемых типов аннотаций. Метод
AbstractProcessor.getSupportedAnnotationTypesпредоставляет поддержку для удаления префикса модуля при выполнении в среде без модулей. - Возвращает:
- имена типов аннотаций, поддерживаемых этим процессором
- См. также:
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; если у процессора нет дополнений, которые можно предложить на основе предоставленной информации, может быть возвращен пустой итерируемый набор. Процессор также может вернуть одно дополнение со значением строки в качестве пустой строки и сообщением, объясняющим, почему нет дополнений.
Дополнительная информация отражает дополнительные проверки допустимости, выполненные процессорами аннотаций. Например, рассмотрим простую аннотацию:
@MersennePrime {
int value();
} (Простое число Мерсенна — простое число вида 2n - 1.) При данном AnnotationMirror для этого типа аннотации может быть возвращён список всех таких простых чисел в диапазоне int без проверки других аргументов getCompletions: import static javax.annotation.processing.Completions.*;
...
return Arrays.asList(of("3"),
of("7"),
of("31"),
of("127"),
of("8191"),
of("131071"),
of("524287"),
of("2147483647")); Более информативный набор дополнений включит количество каждого простого числа: return Arrays.asList(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, 2020, 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://docs.oracle.com/en/java/javase/11/docs/api/java.compiler/javax/annotation/processing/Processor.html