Согласованность элементов среды обработки во время раундов компиляции - PullRequest
3 голосов
/ 03 ноября 2011

API обработки аннотаций Java в том виде, как он есть в JDK 6 и 7 (не API apt tool из 5), определяет жизненный цикл процессора аннотаций.Один экземпляр создается с помощью конструктора no-args, метод init вызывается с экземпляром ProcessingEnvironment, а затем этот процессор используется с помощью метода process.Только один экземпляр процессора создается и используется во всех последующих циклах обработки, если это применимо.

Поскольку мой класс процессора становился немного раздутым, я создал классы-обработчики для отдельных аннотаций, с которыми он должен иметь дело.В методах этих классов я всегда передаю Elements и Types экземпляры, которые я получил от ProcessingEnvironment для их служебных методов.Это делает мои сигнатуры методов довольно длинными.

Я бы предпочел просто сохранить ссылку на экземпляры Elements и Types в обработчиках, а также в экземпляре процессора.Я сделал это, передав их из ProcessingEnvironment, переданного в метод init.Теперь мне интересно, если это безопасно.JavaDoc для Processor дает понять, что некоторые методы вызываются только один раз для процессора, но init здесь не упоминается.Я предполагал, что это неявно понято, но я не уверен на 100%.

Я также хотел бы знать, если экземпляр Messager, который также может быть получен из ProcessingEnvironment,остается неизменным на всех этапах обработки.Я бы предпочел, чтобы предупреждения / ошибки не появлялись в одном раунде, а другие не учитывались.Я достаточно уверен, что было бы безопасно использовать одни и те же экземпляры между раундами, но просто хотел бы иметь определенную уверенность.

Ответы [ 2 ]

2 голосов
/ 06 ноября 2011

Я задавал себе тот же вопрос и решил всегда использовать утилиты ProcessingEnvironment текущего раунда, предоставленные init. Кажется, нет никакой разницы при использовании javac , но есть другие инструменты обработки аннотаций, которые могут показывать другое поведение. Я уже испытал несколько различий между инструментом обработки в javac и тем, который используется eclipse, поэтому я с большой осторожностью обрабатываю все, что не указано в документации. Вопрос в том, хотите ли вы протестировать все существующие инструменты обработки?

Кроме того, я думаю, что если бы эти вспомогательные инструменты обработки никогда не менялись, они были бы аргументами конструктора процессора.

1 голос
/ 30 июля 2012

Стоит упомянуть, что AbstractProcessor (который предлагается javadoc класса Process в качестве подкласса, который может использоваться разработчиками), выбрасывает IllegalStateException если его init метод вызывается более одного раза.

Это не означает, что переданный ProcessingEnvironment не может возвращать разные значения при последующих вызовах геттера или в разных раундах, хотя это не будет обычным. В любом случае, стоит проверить в начале метода process:

private ProcessingEnvironment processingEnv;
private Elements elementUtils;
private Types typeUtils;

public Processor() {
}

@Override
public synchronized void init(final ProcessingEnvironment processingEnv) {
    this.processingEnv = processingEnv;
    elementUtils = processingEnv.getElementUtils();
    typeUtils = processingEnv.getTypeUtils();
}

private void checkEnvironmentChange() {
    checkSame(elementUtils, processingEnv.getElementUtils(), "elementUtils");
    checkSame(typeUtils, processingEnv.getTypeUtils(), "typeUtils");
}

private <T> void checkSame(final T object1, final T object2, final String name) {
    if (object1 != object2) {
        throw new IllegalStateException(name + " should not change");
    }
}

@Override
public boolean process(final Set<? extends TypeElement> annotations, 
        final RoundEnvironment roundEnv) {
    checkEnvironmentChange();
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...