Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking for absence of super class in annotation processor

When obtaining a TypeElement in an annotation processor, you can ask for its super class (or more specifically, the TypeMirror of it) using method getSuperClass(). According to the JavaDoc, a type that doesn't explicity extend anything (in other words, Object is the super class) or that is an interface will return a NoType with NONE as TypeKind.

Disregarding the fact that the whole model/mirror API thing seems to go out of its way to confuse you at every opportunity for a moment, how would I reliably check for this? Here's some code extracts:

//Cast is safe since TypeKind is checked before this
final TypeElement el = (TypeElement)annotatedElement;
...
final TypeMirror parent = el.getSuperclass();
//Checking whether "nothing" is extended
if(parent.getKind().equals(TypeKind.NONE) && parent instanceof NoType) {
    ...         
}

Is this the proper manner? It seems rather clunky. Since the equals method of TypeMirror should not be used for semantic equality checks, I'm wondering whether it is safe to use it for TypeKind. My gut feeling says yes since it's an enum, but then I'm having doubts about that instanceof.

Is there a better way of doing this? The whole javax.lang.model package and its children have cross-references all over the shop and it's never really clear to me what the best method for something is. There's useful utility methods for some stuff, and then there are seemingly simple tasks that require dubious acrobatics like the above.

like image 248
G_H Avatar asked Oct 12 '11 09:10

G_H


People also ask

What is annotationprocessor?

An annotation processor is a class which extends AbstractProcessor (in the package javax. annotation. processing ) providing the functionality needed to generate whatever it needs to generate, such as classes in the case of mapstruct.

How annotation processor works Java?

Annotation Processing APIEach annotation processor, in turn, is called on the corresponding sources. If any files are generated during this process, another round is started with the generated files as its input. This process continues until no new files are generated during the processing stage.

What is Eclipse annotation processing?

A Java annotation processor is a compiler plug-in that can gather information about source code as it is being compiled, generate additional Java types or other resource files, and post warnings and errors.

Can classes be annotated in Java?

Annotations can be applied to declarations: declarations of classes, fields, methods, and other program elements. When used on a declaration, each annotation often appears, by convention, on its own line. As of the Java SE 8 release, annotations can also be applied to the use of types.


1 Answers

I just did a test and realized I misinterpreted the documentation. It returns a NoType with kind NONE for java.lang.Object and interfaces, not for something implicitly extending Object. Silly me. I won't need the check since an earlier one checks if the annotated element is a class in the strict sense (not an enum or interface) and will return if so. In other words, checking if the canonical name is java.lang.Object or maybe using Types.isSameType should do the trick.

Sorry folks. I've decided not to delete since others might arrive with the same question. Feel free to vote delete if you believe it's appropriate.

EDIT: Here's what I eventually went with...

boolean superTypeValid = true;
final TypeMirror parent = el.getSuperClass();
if(!parent.getKind().equals(TypeKind.DECLARED)) {
    messager.printMessage(Kind.ERROR, "May only inherit from a class; not enums, annotations or other declared kinds.", annotatedElement, mirror);
    superTypeValid = false;
} else {
    final DeclaredType parentType = (DeclaredType)parent;
    final Element parentEl = parentType.asElement();
    if(!parentEl.getKind().equals(ElementKind.CLASS)) {
        messager.printMessage(Kind.ERROR, "May only inherit from a class; not enums, annotations or other declared kinds.", annotatedElement, mirror);
        superTypeValid = false;
    }
}
...
if(superTypeValid) {
    if(typeUtils.isSameType(parent, elUtils.getTypeElement("java.lang.Object").asType())) {
        messager.printMessage(Kind.ERROR, "Inherit must not be set to true if the class doesn't extend.", annotatedElement, mirror);
        valid = false;
    } else {
        ...
    }
}

If some of those error messages seem weird, it's because I left some project-specific stuff out.

like image 62
G_H Avatar answered Sep 30 '22 07:09

G_H