2

I have an annotation which marks classes that contain an inner class which implements a named interface.

Here's an example of how this annotation is used:

public interface Implementable {}

@Deserializable(Implementable.class)
public class ImplementableFactory {
    public static Implementable getImplementable() {
        return new Impl();
    }
    private class Impl implements Implementable {}
}

And here's the annotation itself:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public @interface Deserializable {
    Class value();
}

I'd like to do some annotation processing to ensure this contract. I've created an annotation processor class for that purpose:

public class DeserializableProcessor extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        for(Element element : roundEnv.getElementsAnnotatedWith(Deserializable.class)){
            TypeMirror expected = getDeserializableValue(element);
            if (expected != null) {
                Boolean found = false;
                for (Element enclosed : element.getEnclosedElements()) {
                    if (enclosed.getKind().equals(ElementKind.CLASS)) {
                        //This next bit doesn't compile.
                        //I'm looking for the same functionality.
                        if (expected.isAssignableFrom(enclosed)) {
                            found = true;
                            break;
                        }
                    }
                }
                if (!found) {
                    String message = String.format("Classes marked with the Deserializable annotation must contain an inner class with implements the value of the annotation. %s does not contain a class which implements %s.",
                            element.getSimpleName().toString(),
                            expected.toString());
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, message);
                }
            }
        }
        return true;
    }

    private TypeMirror getDeserializableValue(Element element) {
        ...
    }
}

How can I achieve similar functionality to Class::isAssignableFrom within reflection possible via annotation processing?

1 Answer 1

3

This can be done with the aid of AbstractProcessor's protected processingEnvironment. It exposes an implementation of TypeUtils, a utility class that enables a lot of reflection functionality.

if (processingEnv.getTypeUtils().isAssignable(enclosed.asType(), expected)) {
    found = true;
    break;
}
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.