aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author zaaarf <zaaarf@proton.me>2023-08-24 01:50:14 +0200
committer zaaarf <zaaarf@proton.me>2023-08-24 01:50:14 +0200
commitca13fffd0e356a4a0c73563ff90a145acb5d7706 (patch)
tree99b87027ece6858339d7da2d8e030d3977ee85e8
parent17398e89db3b4c505a2a65130baf5cd28e20cc1c (diff)
feat: proper error handling
-rw-r--r--src/main/java/ftbsc/geb/exceptions/BadListenerArgumentsException.java52
-rw-r--r--src/main/java/ftbsc/geb/exceptions/MissingInterfaceException.java17
-rw-r--r--src/main/java/ftbsc/geb/processor/GEBProcessor.java32
3 files changed, 94 insertions, 7 deletions
diff --git a/src/main/java/ftbsc/geb/exceptions/BadListenerArgumentsException.java b/src/main/java/ftbsc/geb/exceptions/BadListenerArgumentsException.java
new file mode 100644
index 0000000..a15b4e5
--- /dev/null
+++ b/src/main/java/ftbsc/geb/exceptions/BadListenerArgumentsException.java
@@ -0,0 +1,52 @@
+package ftbsc.geb.exceptions;
+
+/**
+ * Thrown when there is something wrong with a listener method.
+ */
+public class BadListenerArgumentsException extends RuntimeException {
+
+ /**
+ * The constructor. It's not meant to be used as is, refer to the subclasses
+ * @param message the message to pass along to the superclass
+ */
+ protected BadListenerArgumentsException(String message) {
+ super(message);
+ }
+
+ /**
+ * Thrown when the number of arguments is off.
+ */
+ public static class Count extends BadListenerArgumentsException {
+
+ /**
+ * The public constructor.
+ * @param clazz the fully-qualified name of the parent class
+ * @param method the annotated listener method
+ * @param count the number of arguments found
+ */
+ public Count(String clazz, String method, int count) {
+ super(String.format(
+ "An error occurred while evaluating method %s::%s: found %d arguments, expected 1!",
+ clazz, method, count));
+ }
+ }
+
+ /**
+ * Thrown when the argument is of the wrong type.
+ */
+ public static class Type extends BadListenerArgumentsException {
+
+ /**
+ * The public constructor.
+ * @param clazz the fully-qualified name of the parent class
+ * @param method the annotated listener method
+ * @param parameterName the name of the parameter
+ */
+ public Type(String clazz, String method, String parameterName) {
+ super(String.format(
+ "The parameter %s of %s::%s does not implement the IEvent interface!",
+ parameterName, clazz, method
+ ));
+ }
+ }
+}
diff --git a/src/main/java/ftbsc/geb/exceptions/MissingInterfaceException.java b/src/main/java/ftbsc/geb/exceptions/MissingInterfaceException.java
new file mode 100644
index 0000000..e792729
--- /dev/null
+++ b/src/main/java/ftbsc/geb/exceptions/MissingInterfaceException.java
@@ -0,0 +1,17 @@
+package ftbsc.geb.exceptions;
+
+/**
+ * Thrown when a parent of a listener method does not implement the
+ * appropriate interface,
+ */
+public class MissingInterfaceException extends RuntimeException {
+
+ /**
+ * The public constructor.
+ * @param clazz the fully-qualified name of the parent class
+ * @param method the annotated listener method
+ */
+ public MissingInterfaceException(String clazz, String method) {
+ super(String.format("The parent of %s::%s does not implement the IListener interface!", clazz, method));
+ }
+}
diff --git a/src/main/java/ftbsc/geb/processor/GEBProcessor.java b/src/main/java/ftbsc/geb/processor/GEBProcessor.java
index 37d6072..5ea4c38 100644
--- a/src/main/java/ftbsc/geb/processor/GEBProcessor.java
+++ b/src/main/java/ftbsc/geb/processor/GEBProcessor.java
@@ -5,12 +5,16 @@ import ftbsc.geb.api.IEvent;
import ftbsc.geb.api.IEventDispatcher;
import ftbsc.geb.api.IListener;
import ftbsc.geb.api.annotations.Listen;
+import ftbsc.geb.exceptions.BadListenerArgumentsException;
+import ftbsc.geb.exceptions.MissingInterfaceException;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.*;
+import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
+import javax.tools.Diagnostic;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;
@@ -88,23 +92,37 @@ public class GEBProcessor extends AbstractProcessor {
* @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
TypeMirror parentType = listener.getEnclosingElement().asType();
if(!this.processingEnv.getTypeUtils().isAssignable(parentType, this.listenerInterface))
- return; //TODO throw error, parent doesn't implement the interface
+ throw new MissingInterfaceException(
+ listener.getEnclosingElement().getSimpleName().toString(),
+ listener.getSimpleName().toString());
- //ensure the listener method has only a single IEvent parameter
+ //ensure the listener method has only one parameter
List<? extends VariableElement> params = listener.getParameters();
if(listener.getParameters().size() != 1)
- return; //TODO throw error, bad parameter amount
+ throw new BadListenerArgumentsException.Count(
+ listener.getEnclosingElement().getSimpleName().toString(),
+ listener.getSimpleName().toString(),
+ params.size());
+
+ //ensure said parameter implements IEvent
TypeMirror event = params.get(0).asType();
if(!this.processingEnv.getTypeUtils().isAssignable(event, this.eventInterface))
- return; //TODO throw error, bad parameter type
+ throw new BadListenerArgumentsException.Type(
+ listener.getEnclosingElement().getSimpleName().toString(),
+ listener.getSimpleName().toString(),
+ params.get(0).getSimpleName().toString());
+
+ //warn about return type
+ if(!listener.getReturnType().getKind().equals(TypeKind.VOID))
+ this.processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, String.format(
+ "The method %s::%s has a return type: please note that it will be ignored.",
+ listener.getEnclosingElement().getSimpleName().toString(),
+ listener.getSimpleName().toString()));
if(!this.listenerMap.containsKey(event))
this.listenerMap.put(event, new HashSet<>());