Как обрабатывать аннотации с помощью @Target(ElementType.TYPE_USE)?

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

@Documented
@Target(value = { ElementType.PARAMETER, ElementType.TYPE_USE })
@Retention(value = RetentionPolicy.RUNTIME)
public @interface AuditSubject {

}

public interface Auditable {
    // methods that provide data for writing a log entry...
}

public class Report implements Auditable {

}

Для аннотированных элементов должна быть создана запись в журнале после выполнения метода (с использованием AOP). Примеры:

@CreateLogEntry
public Result persist(@AuditSubject Report newReport) {
    // A log entry must be created with the incoming newReport.    
}

@CreateLogEntry
public UpdateResult<@AuditSubject Report> update(Report update) {
    // A log entry must be created with the updated report which is not the same instance as 'update' (cannot use it).
} 

@CreateLogEntry
public Result persistBatch(List<@AuditSubject Report> batch) {
    // A log entry must be created for each element in 'batch' after this method execution.
}

Записи журнала должны быть созданы при условии, что Report инвентарь Auditable; если это не так, генерируется исключение времени выполнения (Yikes, я забыл реализовать интерфейс!). Таким образом, процессор аннотаций помогает отлавливать ошибки программиста во время компиляции. До сих пор я успешно проверял все использования в параметрах, но не в использовании типов. Соответствующий код от процессора аннотаций выглядит следующим образом:

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    for (Element annotated : roundEnv.getElementsAnnotatedWith(AuditSubject.class)) {
        // Only prints elements with ElementKind.PARAMETER)!
        this.messager.printMessage(Kind.NOTE, TextUtils.replaceParams("annotated: {} ; Kind : {} ; enclosing : {}", annotated,  annotated.getKind(), annotated.getEnclosingElement()));

        if (annotated.getKind() == ElementKind.PARAMETER) {
            // Code here works as expected, raises errors for annotated parameters of classes that don't implement Auditable.
        } else if (annotated.getKind() == ElementKind.WHAT_TO_USE) {
            // What ElementKind do I need to use here?
        }
    }

    return false;
}

Только аннотированные элементы с видом ElementKind.PARAMETER распознаются (первая строка в цикле процесса () печатает только одну строку для 'newReport') Как я могу проверить, что аннотированные типы реализуют Auditable? Нет никаких "ElementKind.TYPE_USE"Постоянный в использовании. Я не смог найти никакой соответствующей информации по этому вопросу. Спасибо за ваше внимание.

1 ответ

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

Если вы хотите обрабатывать аннотации типов или аннотации в теле метода, вам необходимо написать собственный код для повторения типов или для проверки строк кода в методе.

Альтернативой этому является использование такого инструмента, как https://checkerframework.org/. Он реализует своих посетителей, и поэтому встроенный в него процессор аннотаций вызывается для каждого вхождения аннотации типа.

Почему бы не использовать TYPE_PARAMETER?javax.annotation.processing.Processor Документ API есть:

An annotation type is considered present if there is at least one annotation of that type present on an element enclosed within the root elements of a round. For this purpose, a type parameter is considered to be enclosed by its generic element. Annotations on type uses, as opposed to annotations on elements, are ignored when computing whether or not an annotation type is present.

javax.lang.model.element.TypeParameterElement
Element getGenericElement()
Returns the generic class, interface, method, or constructor that is parameterized by this type parameter.
Другие вопросы по тегам