diff options
author | sameb <sameb@google.com> | 2015-02-10 15:37:44 -0800 |
---|---|---|
committer | Sam Berlin <sameb@google.com> | 2015-02-24 18:28:17 -0500 |
commit | 7445e44ba8acbbfc09116fec71d59066cdae8721 (patch) | |
tree | 9f050682d94fe6569c98da54054c9076eeb19696 /core | |
parent | 9be698db4a8fa560cfae23795d629b018ad009cf (diff) | |
download | guice-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')
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() {} + } } |