Skip to content

Commit

Permalink
Throw if @subscribe is applied to a method that takes a primitive par…
Browse files Browse the repository at this point in the history
…ameter.

Fixes #3992.

RELNOTES=Prevent @subscribe being applied to a method that takes a primitive, as that will never be called.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=328195519
  • Loading branch information
netdpb committed Aug 25, 2020
1 parent 9b972a2 commit 554546c
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 10 deletions.
Expand Up @@ -289,6 +289,18 @@ public void call(String s) {
assertEquals(1, calls.get());
}

public void testPrimitiveSubscribeFails() {
class SubscribesToPrimitive {
@Subscribe
public void toInt(int i) {}
}
try {
bus.register(new SubscribesToPrimitive());
fail("should have thrown");
} catch (IllegalArgumentException expected) {
}
}

/** Records thrown exception information. */
private static final class RecordingSubscriberExceptionHandler
implements SubscriberExceptionHandler {
Expand Down
7 changes: 4 additions & 3 deletions android/guava/src/com/google/common/eventbus/Subscribe.java
Expand Up @@ -23,9 +23,10 @@
/**
* Marks a method as an event subscriber.
*
* <p>The type of event will be indicated by the method's first (and only) parameter. If this
* annotation is applied to methods with zero parameters, or more than one parameter, the object
* containing the method will not be able to register for event delivery from the {@link EventBus}.
* <p>The type of event will be indicated by the method's first (and only) parameter, which cannot
* be primitive. If this annotation is applied to methods with zero parameters, or more than one
* parameter, the object containing the method will not be able to register for event delivery from
* the {@link EventBus}.
*
* <p>Unless also annotated with @{@link AllowConcurrentEvents}, event subscriber methods will be
* invoked serially by each event bus that they are registered with.
Expand Down
Expand Up @@ -16,6 +16,7 @@

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.throwIfUnchecked;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
Expand All @@ -31,6 +32,7 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.primitives.Primitives;
import com.google.common.reflect.TypeToken;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.j2objc.annotations.Weak;
Expand Down Expand Up @@ -170,7 +172,12 @@ private Multimap<Class<?>, Subscriber> findAllSubscribers(Object listener) {
}

private static ImmutableList<Method> getAnnotatedMethods(Class<?> clazz) {
return subscriberMethodsCache.getUnchecked(clazz);
try {
return subscriberMethodsCache.getUnchecked(clazz);
} catch (UncheckedExecutionException e) {
throwIfUnchecked(e.getCause());
throw e;
}
}

private static ImmutableList<Method> getAnnotatedMethodsNotCached(Class<?> clazz) {
Expand All @@ -183,11 +190,20 @@ private static ImmutableList<Method> getAnnotatedMethodsNotCached(Class<?> clazz
Class<?>[] parameterTypes = method.getParameterTypes();
checkArgument(
parameterTypes.length == 1,
"Method %s has @Subscribe annotation but has %s parameters."
"Method %s has @Subscribe annotation but has %s parameters. "
+ "Subscriber methods must have exactly 1 parameter.",
method,
parameterTypes.length);

checkArgument(
!parameterTypes[0].isPrimitive(),
"@Subscribe method %s's parameter is %s. "
+ "Subscriber methods cannot accept primitives. "
+ "Consider changing the parameter to %s.",
method,
parameterTypes[0].getName(),
Primitives.wrap(parameterTypes[0]).getSimpleName());

MethodIdentifier ident = new MethodIdentifier(method);
if (!identifiers.containsKey(ident)) {
identifiers.put(ident, method);
Expand Down
12 changes: 12 additions & 0 deletions guava-tests/test/com/google/common/eventbus/EventBusTest.java
Expand Up @@ -289,6 +289,18 @@ public void call(String s) {
assertEquals(1, calls.get());
}

public void testPrimitiveSubscribeFails() {
class SubscribesToPrimitive {
@Subscribe
public void toInt(int i) {}
}
try {
bus.register(new SubscribesToPrimitive());
fail("should have thrown");
} catch (IllegalArgumentException expected) {
}
}

/** Records thrown exception information. */
private static final class RecordingSubscriberExceptionHandler
implements SubscriberExceptionHandler {
Expand Down
7 changes: 4 additions & 3 deletions guava/src/com/google/common/eventbus/Subscribe.java
Expand Up @@ -23,9 +23,10 @@
/**
* Marks a method as an event subscriber.
*
* <p>The type of event will be indicated by the method's first (and only) parameter. If this
* annotation is applied to methods with zero parameters, or more than one parameter, the object
* containing the method will not be able to register for event delivery from the {@link EventBus}.
* <p>The type of event will be indicated by the method's first (and only) parameter, which cannot
* be primitive. If this annotation is applied to methods with zero parameters, or more than one
* parameter, the object containing the method will not be able to register for event delivery from
* the {@link EventBus}.
*
* <p>Unless also annotated with @{@link AllowConcurrentEvents}, event subscriber methods will be
* invoked serially by each event bus that they are registered with.
Expand Down
20 changes: 18 additions & 2 deletions guava/src/com/google/common/eventbus/SubscriberRegistry.java
Expand Up @@ -16,6 +16,7 @@

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.throwIfUnchecked;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
Expand All @@ -31,6 +32,7 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.primitives.Primitives;
import com.google.common.reflect.TypeToken;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.j2objc.annotations.Weak;
Expand Down Expand Up @@ -170,7 +172,12 @@ private Multimap<Class<?>, Subscriber> findAllSubscribers(Object listener) {
}

private static ImmutableList<Method> getAnnotatedMethods(Class<?> clazz) {
return subscriberMethodsCache.getUnchecked(clazz);
try {
return subscriberMethodsCache.getUnchecked(clazz);
} catch (UncheckedExecutionException e) {
throwIfUnchecked(e.getCause());
throw e;
}
}

private static ImmutableList<Method> getAnnotatedMethodsNotCached(Class<?> clazz) {
Expand All @@ -183,11 +190,20 @@ private static ImmutableList<Method> getAnnotatedMethodsNotCached(Class<?> clazz
Class<?>[] parameterTypes = method.getParameterTypes();
checkArgument(
parameterTypes.length == 1,
"Method %s has @Subscribe annotation but has %s parameters."
"Method %s has @Subscribe annotation but has %s parameters. "
+ "Subscriber methods must have exactly 1 parameter.",
method,
parameterTypes.length);

checkArgument(
!parameterTypes[0].isPrimitive(),
"@Subscribe method %s's parameter is %s. "
+ "Subscriber methods cannot accept primitives. "
+ "Consider changing the parameter to %s.",
method,
parameterTypes[0].getName(),
Primitives.wrap(parameterTypes[0]).getSimpleName());

MethodIdentifier ident = new MethodIdentifier(method);
if (!identifiers.containsKey(ident)) {
identifiers.put(ident, method);
Expand Down

0 comments on commit 554546c

Please sign in to comment.