Pregunta

I am trying to write a custom Anntoation processor. The annotation processor will process each class file at compile time to check annotations, But how am i able to get the class that it is currently processing? I am only able to get the class name in the following codes.

public class AnnotationProcessor extends AbstractProcessor {
  ......
    @Override
     public boolean process(Set<? extends TypeElement> annotations,
        RoundEnvironment roundEnv) {

     Set<? extends Element> rootE=roundEnv.getRootElements();
       for(Element e: rootE) {
        if(e.getKind()==ElementKind.CLASS) {
            String className= e.getSimpleName().toString();
            processingEnv.getMessager().printMessage( javax.tools.Diagnostic.Kind.WARNING,className, e); 
        }
     }
}
¿Fue útil?

Solución

You are unable to access the Class the Annotation Processor is processing because the Class has not been compiled yet. Instead Java offers the analogous Elements api for reflection-style inspection of the input source.

The Element (which you found by using roundEnv.getRootElements()) has much more information about the class being compiled than just its name. A ton of useful information can be found by using the ElementVisitors:

http://docs.oracle.com/javase/6/docs/api/javax/lang/model/element/ElementVisitor.html http://docs.oracle.com/javase/6/docs/api/javax/lang/model/util/ElementKindVisitor6.html

Including the classes constructor, methods, fields, etc.

Here's how to use it:

public class AnnotationProcessor extends AbstractProcessor {
......
    @Override
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {

         Set<? extends Element> rootE=roundEnv.getRootElements();
         for(Element e: rootE) {
             for(Element subElement : e.getEnclosedElements()){
                 subElement.accept(new ExampleVisitor(), null); // implement ExampleVisitor
             }
        }
    }
}

Otros consejos

  1. This is NOT how AnnotationProcessing works. You cannot get a Class<?> object during processing becuase the classes that you want definition of are being compiled right NOW! If you call getClass() on an unknown class or use Class<?> clazz = Class.forName("com.your.fancy.Class") you'll get java.lang.ClassNotFoundException which is completely fine.
  2. You need to use classes such as javax.lang.model.element.Element and javax.lang.model.element.ExecutableElement to describe/read your class definitions.
  3. The javax.lang.model.* has javax.lang.model.type.TypeMirror to describe classes, their fields, methods etc.
  4. If you need more insight, just include tools.jar from the java compiler (JAVA SDK) to get more type definitions which are used during compilation. But most probably - you DON'T need to add this jar dependency!
  5. You'll get ClassNotFoundException even after roundEnvironment.processingOver() is true.
  6. IN SHORT: USE TypeMirror in all the places where you wanted to use the Class type.

Examples:

  • get list of methods from a class:
public static @Nonnull List getMethods(@Nonnull Element annotationElem, @Nonnull RoundEnvironment roundEnvironment) {
    List outList = new ArrayList();

    String simpleName = annotationElem.getSimpleName().toString();
    for (Element elem  : roundEnvironment.getRootElements())
        if (elem.getSimpleName().toString().equals(simpleName))
            for (Element methodDeclaration :elem.getEnclosedElements())
                if (methodDeclaration instanceof ExecutableElement)
                    outList.add((ExecutableElement)methodDeclaration);

    return outList;
}
  • get method name from method declaration:
public static TypeMirror getMethodFirstParam(@Nonnull ExecutableElement method, int n) {
     List parameters = ((ExecutableElement) method).getParameters();
     if (parameters != null && parameters.size() > 0)
         return parameters.get(n).asType();
     return null;
}

sometimes you can use: subElement.getEnclosingElement() so you can get parent element which may be the class element as you want.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top