Fix several edge cases in EventProcessor
When encountering an event handler with an invalid signature, the processor doesn't crash anymore. Also, event parameters that aren't objects are now reported as errors.
This commit is contained in:
parent
1dd9e05c38
commit
ff35e7f37d
@ -157,9 +157,9 @@ If you intend to use event handlers that are inaccessible to Event Bus by means
|
|||||||
opens my.module to dev.kske.eventbus.core;
|
opens my.module to dev.kske.eventbus.core;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Compile-Time Error Checking with Event Bus AP
|
## Compile-Time Error Checking with Event Bus Proc
|
||||||
|
|
||||||
To assist you with writing event listeners, the Event Bus AP (Annotation Processor) module enforces correct usage of the `@Event` annotation during compile time.
|
To assist you with writing event listeners, the Event Bus Proc (Annotation Processor) module enforces correct usage of the `@Event` annotation during compile time.
|
||||||
This reduces difficult-to-debug bugs that occur during runtime to compile-time errors which can be easily fixed.
|
This reduces difficult-to-debug bugs that occur during runtime to compile-time errors which can be easily fixed.
|
||||||
|
|
||||||
The event annotation processor detects invalid event handlers and event type issues with more to come in future versions.
|
The event annotation processor detects invalid event handlers and event type issues with more to come in future versions.
|
||||||
|
@ -35,8 +35,9 @@ public class EventProcessor extends AbstractProcessor {
|
|||||||
private void processRound(Set<ExecutableElement> eventHandlers) {
|
private void processRound(Set<ExecutableElement> eventHandlers) {
|
||||||
for (ExecutableElement eventHandler : eventHandlers) {
|
for (ExecutableElement eventHandler : eventHandlers) {
|
||||||
Event eventAnnotation = eventHandler.getAnnotation(Event.class);
|
Event eventAnnotation = eventHandler.getAnnotation(Event.class);
|
||||||
|
TypeMirror eventType;
|
||||||
|
|
||||||
// Determine how the event type is defined
|
// Determine the event type and how it is defined
|
||||||
boolean useParameter;
|
boolean useParameter;
|
||||||
try {
|
try {
|
||||||
eventAnnotation.value();
|
eventAnnotation.value();
|
||||||
@ -45,35 +46,48 @@ public class EventProcessor extends AbstractProcessor {
|
|||||||
} catch (MirroredTypeException e) {
|
} catch (MirroredTypeException e) {
|
||||||
|
|
||||||
// Task failed successfully
|
// Task failed successfully
|
||||||
useParameter = processingEnv.getTypeUtils().isSameType(e.getTypeMirror(),
|
eventType = e.getTypeMirror();
|
||||||
|
useParameter = processingEnv.getTypeUtils().isSameType(eventType,
|
||||||
getTypeMirror(Event.USE_PARAMETER.class));
|
getTypeMirror(Event.USE_PARAMETER.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for correct method signature and return type
|
// Check handler signature
|
||||||
if (eventHandler.getParameters().size() == 0 && useParameter)
|
boolean pass = false;
|
||||||
|
if (useParameter && eventHandler.getParameters().size() == 0)
|
||||||
error(eventHandler, "The method or the annotation must define the event type");
|
error(eventHandler, "The method or the annotation must define the event type");
|
||||||
|
else if (!useParameter && eventHandler.getParameters().size() == 1)
|
||||||
if (eventHandler.getParameters().size() == 1 && !useParameter)
|
|
||||||
error(eventHandler,
|
error(eventHandler,
|
||||||
"Either the method or the annotation must define the event type");
|
"Either the method or the annotation must define the event type");
|
||||||
|
else if (eventHandler.getParameters().size() > 1)
|
||||||
if (eventHandler.getParameters().size() > 1)
|
|
||||||
error(eventHandler, "Method must not have more than one parameter");
|
error(eventHandler, "Method must not have more than one parameter");
|
||||||
|
else if (eventHandler.getReturnType().getKind() != TypeKind.VOID)
|
||||||
if (eventHandler.getReturnType().getKind() != TypeKind.VOID)
|
|
||||||
error(eventHandler, "Method must return void");
|
error(eventHandler, "Method must return void");
|
||||||
|
else
|
||||||
|
pass = true;
|
||||||
|
|
||||||
// Get first parameter as type and element
|
// Abort checking if the handler signature is incorrect
|
||||||
var paramElement = eventHandler.getParameters().get(0);
|
if (!pass)
|
||||||
var paramType = paramElement.asType();
|
continue;
|
||||||
|
|
||||||
|
// Additional checks if parameter is used
|
||||||
|
if (useParameter) {
|
||||||
|
VariableElement paramElement = eventHandler.getParameters().get(0);
|
||||||
|
eventType = paramElement.asType();
|
||||||
|
|
||||||
|
// Check if parameter is object
|
||||||
|
// Abort checking otherwise
|
||||||
|
if (eventType.getKind() != TypeKind.DECLARED) {
|
||||||
|
error(paramElement, "Event must be an object");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check for handlers for abstract types that aren't polymorphic
|
// Check for handlers for abstract types that aren't polymorphic
|
||||||
|
Element eventElement = ((DeclaredType) eventType).asElement();
|
||||||
if (eventHandler.getAnnotation(Polymorphic.class) == null
|
if (eventHandler.getAnnotation(Polymorphic.class) == null
|
||||||
&& paramType.getKind() == TypeKind.DECLARED) {
|
&& (eventElement.getKind() == ElementKind.INTERFACE
|
||||||
var declaredElement = ((DeclaredType) paramType).asElement();
|
|| eventElement.getModifiers().contains(Modifier.ABSTRACT))) {
|
||||||
if (declaredElement.getKind() == ElementKind.INTERFACE
|
warning(eventHandler,
|
||||||
|| declaredElement.getModifiers().contains(Modifier.ABSTRACT))
|
|
||||||
warning(paramElement,
|
|
||||||
"Parameter should be instantiable or handler should use @Polymorphic");
|
"Parameter should be instantiable or handler should use @Polymorphic");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user