aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorsameb <sameb@google.com>2015-02-10 15:37:44 -0800
committerSam Berlin <sameb@google.com>2015-02-24 18:28:17 -0500
commit7445e44ba8acbbfc09116fec71d59066cdae8721 (patch)
tree9f050682d94fe6569c98da54054c9076eeb19696 /core
parent9be698db4a8fa560cfae23795d629b018ad009cf (diff)
downloadguice-7445e44ba8acbbfc09116fec71d59066cdae8721.tar.gz
Fix ElementSource attribution for ModuleAnnotatedMethodScanner bindings.
------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=86029834
Diffstat (limited to 'core')
-rw-r--r--core/src/com/google/inject/internal/ProviderMethodsModule.java10
-rw-r--r--core/src/com/google/inject/spi/Elements.java18
-rw-r--r--core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java62
3 files changed, 87 insertions, 3 deletions
diff --git a/core/src/com/google/inject/internal/ProviderMethodsModule.java b/core/src/com/google/inject/internal/ProviderMethodsModule.java
index 98eb45d3..4ff3e9fd 100644
--- a/core/src/com/google/inject/internal/ProviderMethodsModule.java
+++ b/core/src/com/google/inject/internal/ProviderMethodsModule.java
@@ -114,6 +114,10 @@ public final class ProviderMethodsModule implements Module {
return new ProviderMethodsModule(object, skipFastClassGeneration, scanner);
}
+ public Module getDelegateModule() {
+ return delegate instanceof Module ? (Module) delegate : null;
+ }
+
@Override
public synchronized void configure(Binder binder) {
for (ProviderMethod<?> providerMethod : getProviderMethods(binder)) {
@@ -258,7 +262,11 @@ public final class ProviderMethodsModule implements Module {
@SuppressWarnings("unchecked") // Define T as the method's return type.
TypeLiteral<T> returnType = (TypeLiteral<T>) typeLiteral.getReturnType(method);
Key<T> key = getKey(errors, returnType, method, method.getAnnotations());
- key = scanner.prepareMethod(binder, annotation, key, point);
+ try {
+ key = scanner.prepareMethod(binder, annotation, key, point);
+ } catch(Throwable t) {
+ binder.addError(t);
+ }
Class<? extends Annotation> scopeAnnotation
= Annotations.findScopeAnnotation(errors, method.getAnnotations());
for (Message message : errors.getMessages()) {
diff --git a/core/src/com/google/inject/spi/Elements.java b/core/src/com/google/inject/spi/Elements.java
index 986582e2..fcd714d2 100644
--- a/core/src/com/google/inject/spi/Elements.java
+++ b/core/src/com/google/inject/spi/Elements.java
@@ -242,13 +242,27 @@ public final class Elements {
public void install(Module module) {
if (modules.add(module)) {
Binder binder = this;
+ boolean unwrapModuleSource = false;
// Update the module source for the new module
if (!(module instanceof ProviderMethodsModule)) {
moduleSource = getModuleSource(module);
+ unwrapModuleSource = true;
+ } else {
+ // There are two reason's we'd want to get the module source in a ProviderMethodsModule.
+ // ModuleAnnotatedMethodScanner lets users scan their own modules for @Provides-like
+ // bindings. If they install the module at a top-level, then moduleSource can be null.
+ // Also, if they pass something other than 'this' to it, we'd have the wrong source.
+ Module delegate = ((ProviderMethodsModule) module).getDelegateModule();
+ if (delegate != null
+ && (moduleSource == null
+ || !moduleSource.getModuleClassName().equals(delegate.getClass().getName()))) {
+ moduleSource = getModuleSource(delegate);
+ unwrapModuleSource = true;
+ }
}
if (module instanceof PrivateModule) {
binder = binder.newPrivateBinder();
- }
+ }
try {
module.configure(binder);
} catch (RuntimeException e) {
@@ -261,7 +275,7 @@ public final class Elements {
}
binder.install(ProviderMethodsModule.forModule(module));
// We are done with this module, so undo module source change
- if (!(module instanceof ProviderMethodsModule)) {
+ if (unwrapModuleSource) {
moduleSource = moduleSource.getParent();
}
}
diff --git a/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java b/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java
index 62f82203..8e4515ba 100644
--- a/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java
+++ b/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java
@@ -21,6 +21,8 @@ import static com.google.inject.name.Names.named;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import com.google.inject.Binder;
@@ -125,4 +127,64 @@ public class ModuleAnnotatedMethodScannerTest extends TestCase {
Names.named(((Named) key.getAnnotation()).value() + "-munged"));
}
}
+
+ public void testFailingScanner_scannerOutsideModule() {
+ try {
+ Guice.createInjector(new FailingScanner().forModule(new SomeModule()));
+ fail();
+ } catch (CreationException expected) {
+ Message m = Iterables.getOnlyElement(expected.getErrorMessages());
+ assertEquals(
+ "An exception was caught and reported. Message: Failing in the scanner.",
+ m.getMessage());
+ assertEquals(IllegalStateException.class, m.getCause().getClass());
+ ElementSource source = (ElementSource) Iterables.getOnlyElement(m.getSources());
+ assertEquals(SomeModule.class.getName(),
+ Iterables.getOnlyElement(source.getModuleClassNames()));
+ assertEquals(String.class.getName() + " " + SomeModule.class.getName() + ".aString()",
+ source.toString());
+ }
+ }
+
+ public void testFailingScanner_scannerInModule() {
+ Module module = new AbstractModule() {
+ @Override public void configure() {
+ install(new FailingScanner().forModule(new SomeModule()));
+ }
+ };
+ try {
+ Guice.createInjector(module);
+ fail();
+ } catch (CreationException expected) {
+ Message m = Iterables.getOnlyElement(expected.getErrorMessages());
+ assertEquals(
+ "An exception was caught and reported. Message: Failing in the scanner.",
+ m.getMessage());
+ assertEquals(IllegalStateException.class, m.getCause().getClass());
+ ElementSource source = (ElementSource) Iterables.getOnlyElement(m.getSources());
+ assertEquals(ImmutableList.of(SomeModule.class.getName(), module.getClass().getName()),
+ source.getModuleClassNames());
+ assertEquals(String.class.getName() + " " + SomeModule.class.getName() + ".aString()",
+ source.toString());
+ }
+ }
+
+ public static class FailingScanner extends ModuleAnnotatedMethodScanner {
+ @Override public Set<? extends Class<? extends Annotation>> annotationClasses() {
+ return ImmutableSet.of(TestProvides.class);
+ }
+
+ @Override public <T> Key<T> prepareMethod(
+ Binder binder, Annotation rawAnnotation, Key<T> key, InjectionPoint injectionPoint) {
+ throw new IllegalStateException("Failing in the scanner.");
+ }
+ }
+
+ static class SomeModule extends AbstractModule {
+ @TestProvides String aString() {
+ return "Foo";
+ }
+
+ @Override protected void configure() {}
+ }
}