From ab018451787787cf7fa007a1143cc8e77ae9b55b Mon Sep 17 00:00:00 2001 From: kske Date: Sun, 14 Feb 2021 21:29:06 +0100 Subject: [PATCH] Refactor EventProcessor for improved readability --- .gitignore | 3 + .../dev/kske/eventbus/ap/EventProcessor.java | 75 +++++++++++++------ 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 6cfda9f..db59885 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ # Maven build directories target/ +# Dependency reduced POM from Maven Shade Plugin +dependency-reduced-pom.xml + # Eclipse settings directories .settings/ diff --git a/event-bus-ap/src/main/java/dev/kske/eventbus/ap/EventProcessor.java b/event-bus-ap/src/main/java/dev/kske/eventbus/ap/EventProcessor.java index 6fb5da3..53ad735 100644 --- a/event-bus-ap/src/main/java/dev/kske/eventbus/ap/EventProcessor.java +++ b/event-bus-ap/src/main/java/dev/kske/eventbus/ap/EventProcessor.java @@ -21,51 +21,80 @@ import dev.kske.eventbus.core.*; @SupportedSourceVersion(SourceVersion.RELEASE_11) public class EventProcessor extends AbstractProcessor { + @SuppressWarnings("unchecked") @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { - for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(Event.class)) { - ExecutableElement method = (ExecutableElement) annotatedElement; - Event eventAnnotation = method.getAnnotation(Event.class); - boolean useParameter = false; + if (!roundEnv.errorRaised() && !roundEnv.processingOver()) + processRound( + (Set) roundEnv.getElementsAnnotatedWith(Event.class)); + + // Do not claim the processed annotations + return false; + } + + private void processRound(Set eventHandlers) { + for (ExecutableElement eventHandler : eventHandlers) { + TypeElement eventListener = (TypeElement) eventHandler.getEnclosingElement(); + Event eventAnnotation = eventHandler.getAnnotation(Event.class); // Determine how the event type is defined + boolean useParameter; try { eventAnnotation.eventType(); + throw new EventBusException( + "Could not determine event type of handler " + eventHandler); } catch (MirroredTypeException e) { // Task failed successfully useParameter = processingEnv.getTypeUtils().isSameType(e.getTypeMirror(), - processingEnv.getElementUtils() - .getTypeElement(Event.USE_PARAMETER.class.getCanonicalName()).asType()); + getTypeMirror(Event.USE_PARAMETER.class)); } // Check for correct method signature and return type - if (method.getParameters().size() == 0 && useParameter) - error(method, "The method or the annotation should define the event type"); + if (eventHandler.getParameters().size() == 0 && useParameter) + error(eventHandler, "The method or the annotation must define the event type"); - if (method.getParameters().size() == 1 && !useParameter) - error(method, "Either the method or the annotation should define the event type"); + if (eventHandler.getParameters().size() == 1 && !useParameter) + error(eventHandler, + "Either the method or the annotation must define the event type"); - if (method.getParameters().size() > 1) - error(method, "Method should not have more than one parameter"); + if (eventHandler.getParameters().size() > 1) + error(eventHandler, "Method must not have more than one parameter"); - if (!method.getReturnType().getKind().equals(TypeKind.VOID)) - error(method, "Method needs a return type of void"); + if (eventHandler.getReturnType().getKind() != TypeKind.VOID) + error(eventHandler, "Method must return void"); - // Check event type - var paramType = ((ExecutableType) method.asType()).getParameterTypes().get(0); + // Get first parameter as type and element + var paramElement = eventHandler.getParameters().get(0); + var paramType = paramElement.asType(); + + // Check for valid event type if (useParameter && !processingEnv.getTypeUtils().isAssignable(paramType, - processingEnv.getElementUtils() - .getTypeElement(IEvent.class.getCanonicalName()).asType())) - error(method.getParameters().get(0), "Parameter should implement IEvent"); + getTypeMirror(IEvent.class))) + error(paramElement, "Parameter must implement IEvent"); + + // Check for handlers for abstract types that don't include subtypes + if (!eventAnnotation.includeSubtypes() && paramType.getKind() == TypeKind.DECLARED) { + var declaredElement = ((DeclaredType) paramType).asElement(); + if (declaredElement.getKind() == ElementKind.INTERFACE + || declaredElement.getModifiers().contains(Modifier.ABSTRACT)) + warning(paramElement, + "Parameter should be instantiable or handler should include subtypes"); + } // Check listener for interface implementation - if (!((TypeElement) method.getEnclosingElement()).getInterfaces().contains(processingEnv - .getElementUtils().getTypeElement(EventListener.class.getCanonicalName()).asType())) - warning(method.getEnclosingElement(), + if (!eventListener.getInterfaces().contains(getTypeMirror(EventListener.class))) + warning(eventHandler.getEnclosingElement(), "Class should implement EventListener interface"); } - return true; + } + + private TypeMirror getTypeMirror(Class clazz) { + return getTypeElement(clazz).asType(); + } + + private TypeElement getTypeElement(Class clazz) { + return processingEnv.getElementUtils().getTypeElement(clazz.getCanonicalName()); } private void warning(Element e, String msg, Object... args) {