mercredi 20 octobre 2021

Introspect referenced type of an annotated class

I'm developing an annotation processor aiming to generate code by introspecting annotated class return types methods. I have 2 modules:

  • app: containing my annotated classes
  • processor: containing my annotation and the relative processor

These are my gradle files:

app/build.gradle

plugins {
    id 'java'
}

dependencies {

    testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'

    implementation project(':processor')
    annotationProcessor project(':processor')
}

compileJava {
    options.annotationProcessorPath = configurations.annotationProcessor
}

processor/build.gradle

plugins {
    id 'java-library'
}

repositories {
    mavenCentral()
}

dependencies {

    testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'
}

settings.gradle

rootProject.name = 'MyProject'
include('app')
include('processor')

I have this annotation (processor module)

@Target(ElementType.TYPE)
public @interface MyAnnotation {

}

This is an annotated class

@MyAnnotation
public class DogGenerator {

    public Dog getDog() {
        return new Dog("Brutus");
    }
}

This is my processor

@SupportedSourceVersion(SourceVersion.RELEASE_11)
@SupportedAnnotationTypes("com.myann.MyAnnotation")
public class MyAnnotationProcessor extends AbstractProcessor {

    private Filer filer;
    private Messager messager;
    private Elements elementUtils;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        filer = processingEnv.getFiler();
        messager = processingEnv.getMessager();
        elementUtils = processingEnv.getElementUtils();
    }

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

        final Set<? extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(
                MyAnnotation.class);

        for (Element annotatedElement : elementsAnnotatedWith) {
            if (annotatedElement.getKind() != ElementKind.CLASS) {

                messager.printMessage(Kind.ERROR, "Only classes and method can be annotated with " + MyAnnotation.class.getSimpleName(), annotatedElement);
                return false;
            }

            TypeElement typeEl = elementUtils.getTypeElement(annotatedElement.asType().toString());
            final Element method = typeEl.getEnclosedElements()
                    .stream()
                    .filter(o -> o.getKind() == ElementKind.METHOD)
                    .findFirst()
                    .get();

            TypeMirror returnType = ((ExecutableElement)method).getReturnType();
            messager.printMessage(Kind.WARNING,"return type " + returnType.toString());

        }

        return false;
    }
}

With this code I'm able to print the return type com.myann.Dog, but how can I introspect it in order to get its fields or methods?

If I try to load the class with Class.forName, I receive a ClassNotFoundException. If I add app module as a dependency of the processor module I hit a circular dependency error.





Aucun commentaire:

Enregistrer un commentaire