3

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?

2
  • Well, your parameter does not have @Argument annotation, so arg will be always null... Commented Aug 29, 2017 at 20:49
  • 1
    I am not getting the @Argument annotation of the parameter, I'm getting the annotation of the AnnotationType, which is IntArg in this case. Commented Aug 29, 2017 at 20:56

1 Answer 1

5

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.