Handler Execution Order Debugging #25

Merged
kske merged 1 commits from f/handler-introspection into develop 2021-11-02 09:03:10 +01:00
2 changed files with 57 additions and 5 deletions

View File

@ -109,7 +109,7 @@ public final class EventBus {
// Increment nesting count (becomes > 1 during nested dispatches) // Increment nesting count (becomes > 1 during nested dispatches)
++state.nestingCount; ++state.nestingCount;
Iterator<EventHandler> handlers = getHandlersFor(event.getClass()); Iterator<EventHandler> handlers = getHandlersFor(event.getClass()).iterator();
if (handlers.hasNext()) { if (handlers.hasNext()) {
while (handlers.hasNext()) while (handlers.hasNext())
if (state.isCancelled) { if (state.isCancelled) {
@ -155,10 +155,10 @@ public final class EventBus {
* that are bound to a supertype of the event class. * that are bound to a supertype of the event class.
* *
* @param eventClass the event class to use for the search * @param eventClass the event class to use for the search
* @return an iterator over the applicable handlers in descending order of priority * @return a navigable set containing the applicable handlers in descending order of priority
* @since 0.0.1 * @since 1.2.0
*/ */
private Iterator<EventHandler> getHandlersFor(Class<?> eventClass) { private NavigableSet<EventHandler> getHandlersFor(Class<?> eventClass) {
// Get handlers defined for the event class // Get handlers defined for the event class
TreeSet<EventHandler> handlers = bindings.getOrDefault(eventClass, new TreeSet<>()); TreeSet<EventHandler> handlers = bindings.getOrDefault(eventClass, new TreeSet<>());
@ -170,7 +170,7 @@ public final class EventBus {
if (handler.isPolymorphic()) if (handler.isPolymorphic())
handlers.add(handler); handlers.add(handler);
return handlers.iterator(); return handlers;
} }
/** /**
@ -275,6 +275,39 @@ public final class EventBus {
registeredListeners.clear(); registeredListeners.clear();
} }
/**
* Generates a string describing the event handlers that would be executed for a specific event
* type, in order and without actually executing them.
*
* @apiNote Using this method is only recommended for debugging purposes, as the output depends
* on implementation internals which may be subject to change.
* @implNote Nested dispatches are not accounted for, as this would require actually executing
* the handlers.
* @param eventType the event type to generate the execution order for
* @return a human-readable event handler list suitable for debugging purposes
* @since 1.2.0
*/
public String printExecutionOrder(Class<?> eventType) {
var handlers = getHandlersFor(eventType);
var sj = new StringJoiner("\n");
// Output header line
sj.add(String.format("Event handler execution order for %s (%d handler(s)):", eventType,
handlers.size()));
sj.add(
"==========================================================================================");
// Individual handlers
for (var handler : handlers)
sj.add(handler.toString());
// Bottom line
sj.add(
"==========================================================================================");
return sj.toString();
}
/** /**
* Provides an unmodifiable view of the event listeners registered at this event bus. * Provides an unmodifiable view of the event listeners registered at this event bus.
* *

View File

@ -40,6 +40,25 @@ class DispatchTest {
bus.dispatch(new SimpleEvent()); bus.dispatch(new SimpleEvent());
} }
/**
* Tests {@link EventBus#printExecutionOrder(Class)} based on the currently registered handlers.
*
* @since 1.2.0
*/
@Test
void testPrintExecutionOrder() {
String executionOrder = bus.printExecutionOrder(SimpleEvent.class);
System.out.println(executionOrder);
assertEquals(
"Event handler execution order for class dev.kske.eventbus.core.SimpleEvent (3 handler(s)):\n"
+ "==========================================================================================\n"
+ "EventHandler[method=void dev.kske.eventbus.core.DispatchTest.onSimpleEventFirst(), eventType=class dev.kske.eventbus.core.SimpleEvent, useParameter=false, polymorphic=true, priority=200]\n"
+ "EventHandler[method=static void dev.kske.eventbus.core.DispatchTest.onSimpleEventSecond(), eventType=class dev.kske.eventbus.core.SimpleEvent, useParameter=false, polymorphic=false, priority=150]\n"
+ "EventHandler[method=void dev.kske.eventbus.core.DispatchTest.onSimpleEventThird(dev.kske.eventbus.core.SimpleEvent), eventType=class dev.kske.eventbus.core.SimpleEvent, useParameter=true, polymorphic=false, priority=100]\n"
+ "==========================================================================================",
executionOrder);
}
@Event(SimpleEvent.class) @Event(SimpleEvent.class)
@Priority(200) @Priority(200)
void onSimpleEventFirst() { void onSimpleEventFirst() {