Joba
Joba

Reputation: 817

Java annotation processor, annotation types with annotations

I am using a annotation processor to process annotations of method parameters.

public void multiply(@IntArg int a){
    ...
}

The annotations types used for the parameters have an annotation, @Argument

@Retention(RetentionPolicy.CLASS)
@Target({ElementType.PARAMETER})
@Argument
public @interface IntArg {
}

Now, when my annotation processor is running, I want to check if a parameter annotation (@IntArg) has the @Argument annotation. I do this by executing the following code.

VariableElement param = ... //The parameter
for (AnnotationMirror mirror : param.getAnnotationMirrors()) {
    Argument arg = mirror.getAnnotationType().getAnnotation(Argument.class);
    if(arg != null) {//Args is always null
        ...
    }
}

For some reason arg is always null. Is there a reason why the annotation is not returned?

Upvotes: 3

Views: 766

Answers (1)

Radiodef
Radiodef

Reputation: 37875

I think what you need is this:

VariableElement param = ...;
for (AnnotationMirror mirror : param.getAnnotationMirrors()) {
    DeclaredType t = mirror.getAnnotationType();
    // (Filter out ErrorType: see my addendum.)
    if (t.getKind() == TypeKind.DECLARED) {
        Element e = t.asElement();
        // (This should always be true.)
        if (e.getKind() == ElementKind.ANNOTATION_TYPE) {
            Argument a = e.getAnnotation(Argument.class);
            // ...
        }
    }
}

From DeclaredType and TypeElement:

While a TypeElement represents a class or interface element, a DeclaredType represents a class or interface type, the latter being a use (or invocation) of the former.

So if you want to examine a declaration somehow, you want the element rather than the type.

Note that I also could have casted e to a TypeElement in the above snippet; there was just no particular reason to.


Quick addendum regarding my edit: I think it's probably correct to check the TypeKind here because it's possible for getAnnotationType() to return an ErrorType. This could happen if I did something like this:

void m(@IntArg @TypeWhichDoesntExist int arg0) {
}

Where TypeWhichDoesntExist is a type which doesn't exist, for example because it's not imported, because it's an @interface which is generated by another annotation processor or because it's altogether a non-existent type. (Annotation processors may be invoked with code that doesn't compile.)

I don't think this would have caused a problem with the way my example was written before, but I think it's worthwhile to point out that this could happen.

Upvotes: 5

Related Questions