summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/ftbsc/geb/processor/GEBProcessor.java86
1 files changed, 76 insertions, 10 deletions
diff --git a/src/main/java/ftbsc/geb/processor/GEBProcessor.java b/src/main/java/ftbsc/geb/processor/GEBProcessor.java
index d464549..37d6072 100644
--- a/src/main/java/ftbsc/geb/processor/GEBProcessor.java
+++ b/src/main/java/ftbsc/geb/processor/GEBProcessor.java
@@ -1,6 +1,9 @@
package ftbsc.geb.processor;
import com.squareup.javapoet.*;
+import ftbsc.geb.api.IEvent;
+import ftbsc.geb.api.IEventDispatcher;
+import ftbsc.geb.api.IListener;
import ftbsc.geb.api.annotations.Listen;
import javax.annotation.processing.AbstractProcessor;
@@ -17,38 +20,77 @@ import java.util.*;
import java.util.stream.Collectors;
/**
- *
+ * GEB's {@link javax.annotation.processing.Processor annotation processor},
+ * which takes care of generating the {@link IEventDispatcher dispatchers}.
*/
@SupportedAnnotationTypes({"ftbsc.geb.api.annotations.*"})
public class GEBProcessor extends AbstractProcessor {
+ /**
+ * A {@link Map} tying each event class to a {@link Set} of listeners.
+ */
private final Map<TypeMirror, Set<ListenerContainer>> listenerMap = new HashMap<>();
+ /**
+ * A {@link Set} containing the fully-qualified names of the generated classes.
+ */
private final Set<String> generatedClasses = new HashSet<>();
+ /**
+ * The starting point of the processor.
+ * It calls {@link #processListener(Element)} on all elements annotated with
+ * the {@link Listen} annotation.
+ * @param annotations the annotation types requested to be processed
+ * @param env environment for information about the current and prior round
+ * @return whether the set of annotation types are claimed by this processor
+ */
@Override
- public boolean process(Set<? extends TypeElement> set, RoundEnvironment env) {
- for(TypeElement ann : set)
- if(ann.getQualifiedName().contentEquals(Listen.class.getName()))
- for(Element e : env.getElementsAnnotatedWith(ann))
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
+ boolean claimed = false;
+ for(TypeElement ann : annotations) {
+ if(ann.getQualifiedName().contentEquals(Listen.class.getName())) {
+ claimed = true;
+ for(Element e : env.getElementsAnnotatedWith(ann)) {
this.processListener(e);
- if(!this.listenerMap.isEmpty()) {
- this.generateClasses();
- this.generateServiceProvider();
- return true;
- } else return false;
+ if(!this.listenerMap.isEmpty()) {
+ this.generateClasses();
+ this.generateServiceProvider();
+ }
+ }
+ }
+ }
+ return claimed;
}
+ /**
+ * A {@link TypeMirror} representing the {@link IListener} interface.
+ */
private final TypeMirror listenerInterface = this.processingEnv.getElementUtils()
.getTypeElement("ftbsc.geb.api.IListener").asType();
+ /**
+ * A {@link TypeMirror} representing the {@link IEvent} interface.
+ */
private final TypeMirror eventInterface = this.processingEnv.getElementUtils()
.getTypeElement("ftbsc.geb.api.IEvent").asType();
+ /**
+ * A {@link TypeMirror} representing the {@link IEventDispatcher} interface.
+ */
private final TypeMirror dispatcherInterface = this.processingEnv.getElementUtils()
.getTypeElement("ftbsc.geb.api.IEventDispatcher").asType();
+ /**
+ * Verifies that the annotated method is valid and, if it is, adds it to
+ * the list. See the annotation's javadoc for details on what's considered
+ * a valid listener.
+ * @see Listen
+ * @param target the {@link Element} that was annotated with {@link Listen}
+ */
private void processListener(Element target) {
+ if(!(target instanceof ExecutableElement))
+ return; //TODO throw error
+
ExecutableElement listener = (ExecutableElement) target; //this cast will never fail
//ensure the parent is instance of IListener
@@ -69,6 +111,9 @@ public class GEBProcessor extends AbstractProcessor {
this.listenerMap.get(event).add(new ListenerContainer(listener));
}
+ /**
+ * Uses JavaPoet to generate the classes dispatcher classes.
+ */
private void generateClasses() {
this.listenerMap.forEach((event, listeners) -> {
TypeElement eventClass = (TypeElement) this.processingEnv.getTypeUtils().asElement(event);
@@ -131,6 +176,8 @@ public class GEBProcessor extends AbstractProcessor {
} catch(IOException e) {
throw new RuntimeException(e);
}
+
+ this.generatedClasses.add(resultingClassName);
});
}
@@ -149,11 +196,30 @@ public class GEBProcessor extends AbstractProcessor {
}
}
+ /**
+ * A container class to carry information about a listener method.
+ */
private static class ListenerContainer {
+ /**
+ * The actual listener, the annotated method.
+ */
public final ExecutableElement method;
+
+ /**
+ * The parent which implements {@link IListener}.
+ */
public final TypeMirror parent;
+
+ /**
+ * The {@link Listen} annotation on the method.
+ */
public final Listen annotation;
+ /**
+ * The public constructor.
+ * @param method the annotated method, assumed to be valid
+ * and already checked
+ */
public ListenerContainer(ExecutableElement method) {
this.method = method;
this.parent = method.getEnclosingElement().asType();