Skip to content

Commit c7c6558

Browse files
authored
Cleanup unchecked casts (#100)
Cuts down on the amount of unchecked casts and raw types in the internals, reducing the need for `@SuppressWarnings`. The suppressions have also been narrowed in scope to more clearly show what it's suppressing.
1 parent 8febfe0 commit c7c6558

File tree

8 files changed

+54
-63
lines changed

8 files changed

+54
-63
lines changed

src/main/java/net/minecraftforge/eventbus/internal/BusGroupImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public void unregister(Collection<EventListener> listeners) {
7979
"the BusGroup#register method.");
8080

8181
for (var listener : listeners) {
82-
getOrCreateEventBus((Class<? extends Event>) listener.eventType()).removeListener(listener);
82+
getOrCreateEventBus(listener.eventType()).removeListener(listener);
8383
}
8484
}
8585

src/main/java/net/minecraftforge/eventbus/internal/CancellableEventBusImpl.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,23 +47,20 @@ public CancellableEventBusImpl(String busGroupName, Class<T> eventType, ArrayLis
4747
}
4848

4949
@Override
50-
@SuppressWarnings({"unchecked", "rawtypes"}) // T extends Event, so this is safe.
5150
public EventListener addListener(Consumer<T> listener) {
52-
return addListener(new EventListenerImpl.WrappedConsumerListener(eventType, Priority.NORMAL, (Consumer<Event>) (Consumer) listener));
51+
return addListener(new EventListenerImpl.WrappedConsumerListener<>(eventType, Priority.NORMAL, listener));
5352
}
5453

5554
@Override
56-
@SuppressWarnings({"unchecked", "rawtypes"}) // T extends Event, so this is safe.
5755
public EventListener addListener(byte priority, Consumer<T> listener) {
5856
return addListener(
5957
priority == Priority.MONITOR
60-
? new EventListenerImpl.MonitoringListener(eventType, (Consumer<Event>) (Consumer) listener)
61-
: new EventListenerImpl.WrappedConsumerListener(eventType, priority, (Consumer<Event>) (Consumer) listener)
58+
? new EventListenerImpl.MonitoringListener<>(eventType, listener)
59+
: new EventListenerImpl.WrappedConsumerListener<>(eventType, priority, listener)
6260
);
6361
}
6462

6563
@Override
66-
@SuppressWarnings({"unchecked", "rawtypes"}) // T extends Event, so this is safe
6764
public EventListener addListener(byte priority, boolean alwaysCancelling, Consumer<T> listener) {
6865
if (!alwaysCancelling) {
6966
throw new IllegalArgumentException("If you never cancel the event, call addListener(byte, Consumer<T>)" +
@@ -75,28 +72,25 @@ public EventListener addListener(byte priority, boolean alwaysCancelling, Consum
7572
if (priority == Priority.MONITOR)
7673
throw new IllegalArgumentException("Monitoring listeners cannot cancel events");
7774

78-
return addListener(new EventListenerImpl.WrappedConsumerListener(eventType, priority, true, (Consumer<Event>) (Consumer) listener));
75+
return addListener(new EventListenerImpl.WrappedConsumerListener<>(eventType, priority, true, listener));
7976
}
8077

8178
@Override
82-
@SuppressWarnings({"unchecked", "rawtypes"}) // T extends Event, so this is safe
8379
public EventListener addListener(Predicate<T> listener) {
84-
return addListener(new EventListenerImpl.PredicateListener(eventType, Priority.NORMAL, (Predicate<Event>) (Predicate) listener));
80+
return addListener(new EventListenerImpl.PredicateListener<>(eventType, Priority.NORMAL, listener));
8581
}
8682

8783
@Override
88-
@SuppressWarnings({"unchecked", "rawtypes"}) // T extends Event, so this is safe
8984
public EventListener addListener(byte priority, Predicate<T> listener) {
9085
if (priority == Priority.MONITOR)
9186
throw new IllegalArgumentException("Monitoring listeners cannot cancel events");
9287

93-
return addListener(new EventListenerImpl.PredicateListener(eventType, priority, (Predicate<Event>) (Predicate) listener));
88+
return addListener(new EventListenerImpl.PredicateListener<>(eventType, priority, listener));
9489
}
9590

9691
@Override
97-
@SuppressWarnings({"unchecked", "rawtypes"}) // T extends Event, so this is safe
9892
public EventListener addListener(ObjBooleanBiConsumer<T> monitoringListener) {
99-
return addListener(new EventListenerImpl.MonitoringListener(eventType, (ObjBooleanBiConsumer<Event>) (ObjBooleanBiConsumer) monitoringListener));
93+
return addListener(new EventListenerImpl.MonitoringListener<>(eventType, monitoringListener));
10094
}
10195

10296
@Override
@@ -112,7 +106,7 @@ public T fire(T event) {
112106

113107
@Override
114108
public boolean hasListeners() {
115-
return ((Predicate<?>) getInvoker()) != NO_OP_PREDICATE;
109+
return ((Predicate<? extends Event>) getInvoker()) != NO_OP_PREDICATE;
116110
}
117111

118112
//region Invoker
@@ -137,7 +131,7 @@ public Predicate<T> buildInvoker() {
137131
backingList.sort(PRIORITY_COMPARATOR);
138132

139133
if (Constants.isSelfDestructing(eventCharacteristics()))
140-
monitorBackingList.add(new EventListenerImpl.MonitoringListener(eventType, (event, wasCancelled) -> dispose()));
134+
monitorBackingList.add(new EventListenerImpl.MonitoringListener<>(eventType, (event, wasCancelled) -> dispose()));
141135

142136
Predicate<T> invoker = setInvoker(InvokerFactory.createCancellableMonitoringInvoker(
143137
eventType, eventCharacteristics, backingList, monitorBackingList

src/main/java/net/minecraftforge/eventbus/internal/Constants.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ private Constants() {}
6363
}
6464

6565
@SuppressWarnings("unchecked")
66-
static <T> Consumer<T> getNoOpConsumer() {
66+
static <T extends Event> Consumer<T> getNoOpConsumer() {
6767
return (Consumer<T>) NO_OP_CONSUMER;
6868
}
6969

7070
@SuppressWarnings("unchecked")
71-
static <T> Predicate<T> getNoOpPredicate(boolean alwaysCancelling) {
71+
static <T extends Event> Predicate<T> getNoOpPredicate(boolean alwaysCancelling) {
7272
return (Predicate<T>) (alwaysCancelling ? ALWAYS_TRUE_PREDICATE : NO_OP_PREDICATE);
7373
}
7474

src/main/java/net/minecraftforge/eventbus/internal/EventBusImpl.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,16 @@ public EventBusImpl(String busGroupName, Class<T> eventType, ArrayList<EventList
4444
}
4545

4646
@Override
47-
@SuppressWarnings({"unchecked", "rawtypes"}) // T extends Event, so this is safe.
4847
public EventListener addListener(Consumer<T> listener) {
49-
return addListener(new EventListenerImpl.ConsumerListener(eventType, Priority.NORMAL, (Consumer<Event>) (Consumer) listener));
48+
return addListener(new EventListenerImpl.ConsumerListener<>(eventType, Priority.NORMAL, listener));
5049
}
5150

5251
@Override
53-
@SuppressWarnings({"unchecked", "rawtypes"}) // T extends Event, so this is safe.
5452
public EventListener addListener(byte priority, Consumer<T> listener) {
5553
return addListener(
5654
priority == Priority.MONITOR
57-
? new EventListenerImpl.MonitoringListener(eventType, (Consumer<Event>) (Consumer) listener)
58-
: new EventListenerImpl.ConsumerListener(eventType, priority, (Consumer<Event>) (Consumer) listener)
55+
? new EventListenerImpl.MonitoringListener<>(eventType, listener)
56+
: new EventListenerImpl.ConsumerListener<>(eventType, priority, listener)
5957
);
6058
}
6159

src/main/java/net/minecraftforge/eventbus/internal/EventListenerFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ private EventListenerFactory() {}
3838

3939
private static final Map<Method, MethodHandle> LMF_CACHE = new ConcurrentHashMap<>();
4040

41-
@SuppressWarnings({"unchecked", "rawtypes"})
4241
public static Collection<EventListener> register(BusGroupImpl busGroup, MethodHandles.Lookup callerLookup,
4342
Class<?> listenerClass, @Nullable Object listenerInstance) {
4443
Method[] declaredMethods = listenerClass.getDeclaredMethods();
@@ -70,6 +69,7 @@ public static Collection<EventListener> register(BusGroupImpl busGroup, MethodHa
7069
if (!Event.class.isAssignableFrom(parameterTypes[0]))
7170
throw new IllegalArgumentException("First parameter of a @SubscribeEvent method must be an event");
7271

72+
@SuppressWarnings({"unchecked"})
7373
Class<? extends Event> eventType = (Class<? extends Event>) parameterTypes[0];
7474
var subscribeEventAnnotation = method.getAnnotation(SubscribeEvent.class);
7575

@@ -97,7 +97,6 @@ else if (listeners.size() == 1)
9797
* checks at compile-time.</p>
9898
* @see Constants#STRICT_REGISTRATION_CHECKS
9999
*/
100-
@SuppressWarnings({"unchecked"})
101100
public static Collection<EventListener> registerStrict(BusGroupImpl busGroup, MethodHandles.Lookup callerLookup,
102101
Class<?> listenerClass, @Nullable Object listenerInstance) {
103102
Class<? extends Event> firstValidListenerEventType = null;
@@ -141,6 +140,7 @@ public static Collection<EventListener> registerStrict(BusGroupImpl busGroup, Me
141140
if (!firstParamExtendsEvent)
142141
throw fail(method, "First parameter of a @SubscribeEvent method must be an event");
143142

143+
@SuppressWarnings({"unchecked"})
144144
var eventType = (Class<? extends Event>) parameterTypes[0];
145145

146146
if (returnType != void.class && returnType != boolean.class)

src/main/java/net/minecraftforge/eventbus/internal/EventListenerImpl.java

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package net.minecraftforge.eventbus.internal;
66

7+
import net.minecraftforge.eventbus.api.event.characteristic.Cancellable;
78
import net.minecraftforge.eventbus.api.listener.EventListener;
89
import net.minecraftforge.eventbus.api.listener.ObjBooleanBiConsumer;
910
import net.minecraftforge.eventbus.api.listener.Priority;
@@ -12,35 +13,35 @@
1213
import java.util.function.Predicate;
1314

1415
public sealed interface EventListenerImpl extends EventListener {
15-
sealed interface HasConsumer<T> extends EventListenerImpl {
16+
sealed interface HasConsumer<T extends Event> extends EventListenerImpl {
1617
Consumer<T> consumer();
1718
}
1819

19-
sealed interface HasPredicate<T> extends EventListenerImpl {
20+
sealed interface HasPredicate<T extends Event> extends EventListenerImpl {
2021
Predicate<T> predicate();
2122
}
2223

23-
record ConsumerListener(
24-
Class<? extends Event> eventType,
24+
record ConsumerListener<T extends Event>(
25+
Class<T> eventType,
2526
byte priority,
26-
Consumer<Event> consumer
27-
) implements HasConsumer<Event> {}
27+
Consumer<T> consumer
28+
) implements HasConsumer<T> {}
2829

29-
record PredicateListener(
30-
Class<? extends Event> eventType,
30+
record PredicateListener<T extends Event & Cancellable>(
31+
Class<T> eventType,
3132
byte priority,
32-
Predicate<Event> predicate
33-
) implements HasPredicate<Event> {
33+
Predicate<T> predicate
34+
) implements HasPredicate<T> {
3435
public PredicateListener {
3536
assert priority != Priority.MONITOR : "Monitoring listeners cannot cancel events";
3637
}
3738
}
3839

39-
record MonitoringListener(
40-
Class<? extends Event> eventType,
41-
ObjBooleanBiConsumer<Event> booleanBiConsumer
40+
record MonitoringListener<T extends Event>(
41+
Class<T> eventType,
42+
ObjBooleanBiConsumer<T> booleanBiConsumer
4243
) implements EventListenerImpl {
43-
public MonitoringListener(Class<? extends Event> eventType, Consumer<Event> listener) {
44+
public MonitoringListener(Class<T> eventType, Consumer<T> listener) {
4445
this(eventType, (event, wasCancelled) -> listener.accept(event));
4546
}
4647

@@ -50,18 +51,18 @@ public byte priority() {
5051
}
5152
}
5253

53-
record WrappedConsumerListener(
54-
Class<? extends Event> eventType,
54+
record WrappedConsumerListener<T extends Event>(
55+
Class<T> eventType,
5556
byte priority,
5657
boolean alwaysCancelling,
57-
Consumer<Event> consumer,
58-
Predicate<Event> predicate
59-
) implements HasConsumer<Event>, HasPredicate<Event> {
60-
public WrappedConsumerListener(Class<? extends Event> eventType, byte priority, Consumer<Event> consumer) {
58+
Consumer<T> consumer,
59+
Predicate<T> predicate
60+
) implements HasConsumer<T>, HasPredicate<T> {
61+
public WrappedConsumerListener(Class<T> eventType, byte priority, Consumer<T> consumer) {
6162
this(eventType, priority, false, consumer, wrap(false, consumer));
6263
}
6364

64-
public WrappedConsumerListener(Class<? extends Event> eventType, byte priority, boolean alwaysCancelling, Consumer<Event> consumer) {
65+
public WrappedConsumerListener(Class<T> eventType, byte priority, boolean alwaysCancelling, Consumer<T> consumer) {
6566
this(eventType, priority, alwaysCancelling, consumer, wrap(alwaysCancelling, consumer));
6667
}
6768

@@ -73,7 +74,7 @@ public WrappedConsumerListener(Class<? extends Event> eventType, byte priority,
7374
* @implNote We avoid capturing the alwaysCancelling field in the lambda so that the bytecode is generated as a
7475
* {@code ICONST_1} or {@code ICONST_0} instruction, rather than a field load.
7576
*/
76-
public static Predicate<Event> wrap(boolean alwaysCancelling, Consumer<Event> consumer) {
77+
public static <T extends Event> Predicate<T> wrap(boolean alwaysCancelling, Consumer<T> consumer) {
7778
if (alwaysCancelling) {
7879
return event -> {
7980
consumer.accept(event);
@@ -90,7 +91,7 @@ public static Predicate<Event> wrap(boolean alwaysCancelling, Consumer<Event> co
9091
// Don't factor in the wrapped predicate for equals() and hashCode()
9192
@Override
9293
public boolean equals(Object obj) {
93-
return obj instanceof WrappedConsumerListener that
94+
return obj instanceof WrappedConsumerListener<?> that
9495
&& this.eventType == that.eventType
9596
&& this.priority == that.priority
9697
&& this.alwaysCancelling == that.alwaysCancelling

src/main/java/net/minecraftforge/eventbus/internal/InvokerFactory.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ static <T extends Event & Cancellable> Predicate<T> createCancellableMonitoringI
124124
throw new UnsupportedOperationException("This version of EventBus only supports " +
125125
"EventCharacteristics.MonitorAware on MutableEvent");
126126

127-
// If there's only one monitoring listener, invoke it directly without setting up an iterator/loop
127+
// If there's only one monitoring listener, invoke it directly without setting up a loop on a mutable array
128128
if (monitoringListeners.size() == 1) {
129129
var firstMonitor = unwrappedMonitors.getFirst();
130130
return event -> {
@@ -172,12 +172,10 @@ static <T extends Event & Cancellable> Predicate<T> createCancellableMonitoringI
172172
}
173173
}
174174

175-
@SuppressWarnings("unchecked")
176175
private static <T extends Event> Consumer<T> createInvoker(List<EventListener> listeners) {
177-
return createInvokerFromUnwrapped((List<Consumer<T>>) (List) InvokerFactoryUtils.unwrapConsumers(listeners));
176+
return createInvokerFromUnwrapped(InvokerFactoryUtils.unwrapConsumers(listeners));
178177
}
179178

180-
@SuppressWarnings("unchecked")
181179
private static <T extends Event & Cancellable> Predicate<T> createCancellableInvoker(List<EventListener> listeners) {
182180
// If none of the listeners are able to cancel the event, we can remove the overhead of checking for cancellation entirely
183181
// by treating it like a non-cancellable event.
@@ -195,14 +193,14 @@ private static <T extends Event & Cancellable> Predicate<T> createCancellableInv
195193
// Maybe JEP 402 can save us from this workaround in the future? https://openjdk.java.net/jeps/402
196194

197195
return createCancellableInvokerFromUnwrappedNoChecks(
198-
(List<Consumer<T>>) (List) InvokerFactoryUtils.unwrapAlwaysCancellingConsumers(listeners),
196+
InvokerFactoryUtils.unwrapAlwaysCancellingConsumers(listeners),
199197
listeners.stream()
200198
.map(EventListenerImpl.WrappedConsumerListener.class::cast)
201199
.anyMatch(EventListenerImpl.WrappedConsumerListener::alwaysCancelling)
202200
);
203201
}
204202

205-
return createCancellableInvokerFromUnwrapped((List<Predicate<T>>) (List) InvokerFactoryUtils.unwrapPredicates(listeners));
203+
return createCancellableInvokerFromUnwrapped(InvokerFactoryUtils.unwrapPredicates(listeners));
206204
}
207205

208206
private static <T extends Event> Consumer<T> createInvokerFromUnwrapped(List<Consumer<T>> listeners) {

src/main/java/net/minecraftforge/eventbus/internal/InvokerFactoryUtils.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package net.minecraftforge.eventbus.internal;
66

7+
import net.minecraftforge.eventbus.api.event.characteristic.Cancellable;
78
import net.minecraftforge.eventbus.api.listener.EventListener;
89
import net.minecraftforge.eventbus.api.listener.ObjBooleanBiConsumer;
910

@@ -15,7 +16,7 @@
1516
final class InvokerFactoryUtils {
1617
private InvokerFactoryUtils() {}
1718

18-
static <T> List<Consumer<T>> unwrapConsumers(List<EventListener> listeners) {
19+
static <T extends Event> List<Consumer<T>> unwrapConsumers(List<EventListener> listeners) {
1920
return listeners.stream()
2021
.map(listener -> {
2122
if (listener instanceof EventListenerImpl.HasConsumer<?> consumerListener) {
@@ -28,7 +29,7 @@ static <T> List<Consumer<T>> unwrapConsumers(List<EventListener> listeners) {
2829
.toList();
2930
}
3031

31-
static <T> List<Consumer<T>> unwrapAlwaysCancellingConsumers(List<EventListener> listeners) {
32+
static <T extends Event> List<Consumer<T>> unwrapAlwaysCancellingConsumers(List<EventListener> listeners) {
3233
var unwrappedConsumers = new ArrayList<Consumer<T>>(listeners.size());
3334
for (var listener : listeners) {
3435
if (listener instanceof EventListenerImpl.HasConsumer<?> consumerListener) {
@@ -37,7 +38,7 @@ static <T> List<Consumer<T>> unwrapAlwaysCancellingConsumers(List<EventListener>
3738
throw new IllegalStateException("Unexpected listener type: " + listener.getClass());
3839
}
3940

40-
if (listener instanceof EventListenerImpl.WrappedConsumerListener wrappedConsumerListener
41+
if (listener instanceof EventListenerImpl.WrappedConsumerListener<?> wrappedConsumerListener
4142
&& wrappedConsumerListener.alwaysCancelling()) {
4243
unwrappedConsumers.trimToSize();
4344
break;
@@ -46,12 +47,12 @@ static <T> List<Consumer<T>> unwrapAlwaysCancellingConsumers(List<EventListener>
4647
return unwrappedConsumers;
4748
}
4849

49-
static <T> List<Predicate<T>> unwrapPredicates(List<EventListener> listeners) {
50+
static <T extends Event & Cancellable> List<Predicate<T>> unwrapPredicates(List<EventListener> listeners) {
5051
var unwrappedPredicates = new ArrayList<Predicate<T>>(listeners.size());
5152
for (var listener : listeners) {
5253
if (listener instanceof EventListenerImpl.HasPredicate<?> predicateListener) {
5354
unwrappedPredicates.add(uncheckedCast(predicateListener.predicate()));
54-
} else if (listener instanceof EventListenerImpl.ConsumerListener consumerListener) {
55+
} else if (listener instanceof EventListenerImpl.ConsumerListener<?> consumerListener) {
5556
// EventBus#90 hotfix
5657
// Todo: Figure out a smarter way to handle this, such as when the listener is added to the EventBus and converted to an EventListener.
5758
// Refer to the GitHub issue for more details.
@@ -62,7 +63,7 @@ static <T> List<Predicate<T>> unwrapPredicates(List<EventListener> listeners) {
6263

6364
// Skip the rest of the listeners if we know this one will always cancel the event (and thus prevent further
6465
// non-monitoring listeners from being called anyway).
65-
if (listener instanceof EventListenerImpl.WrappedConsumerListener wrappedConsumerListener
66+
if (listener instanceof EventListenerImpl.WrappedConsumerListener<?> wrappedConsumerListener
6667
&& wrappedConsumerListener.alwaysCancelling()) {
6768
unwrappedPredicates.trimToSize();
6869
break;
@@ -71,11 +72,10 @@ static <T> List<Predicate<T>> unwrapPredicates(List<EventListener> listeners) {
7172
return unwrappedPredicates;
7273
}
7374

74-
static <T> List<ObjBooleanBiConsumer<T>> unwrapMonitors(List<EventListener> monitoringListeners) {
75+
static <T extends Event> List<ObjBooleanBiConsumer<T>> unwrapMonitors(List<EventListener> monitoringListeners) {
7576
return monitoringListeners.stream()
7677
.map(EventListenerImpl.MonitoringListener.class::cast)
77-
.map(EventListenerImpl.MonitoringListener::booleanBiConsumer)
78-
.<ObjBooleanBiConsumer<T>>map(InvokerFactoryUtils::uncheckedCast)
78+
.<ObjBooleanBiConsumer<T>>map(EventListenerImpl.MonitoringListener::booleanBiConsumer)
7979
.toList();
8080
}
8181

0 commit comments

Comments
 (0)