fixes issue with requireExplicitBindings and linked bindings where the implicit binding is scoped.
git-svn-id: https://google-guice.googlecode.com/svn/trunk@1175 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java b/src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java
index fe8c9a6..672cf25 100644
--- a/src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java
+++ b/src/com/google/inject/internal/ProviderToInternalFactoryAdapter.java
@@ -40,7 +40,10 @@
T t = injector.callInContext(new ContextualCallable<T>() {
public T call(InternalContext context) throws ErrorsException {
Dependency dependency = context.getDependency();
- return internalFactory.get(errors, context, dependency, false);
+ // Always pretend that we are a linked binding, to support
+ // scoping implicit bindings. If we are not actually a linked
+ // binding, we'll fail properly elsewhere in the chain.
+ return internalFactory.get(errors, context, dependency, true);
}
});
errors.throwIfNewErrors(0);
diff --git a/test/com/google/inject/JitBindingsTest.java b/test/com/google/inject/JitBindingsTest.java
index a5676f1..95be8d3 100644
--- a/test/com/google/inject/JitBindingsTest.java
+++ b/test/com/google/inject/JitBindingsTest.java
@@ -50,6 +50,86 @@
ensureFails(injector, true, FooImpl.class);
}
+ public void testLinkedEagerSingleton() {
+ Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(Foo.class).to(FooImpl.class).asEagerSingleton();
+ }
+ }).build();
+ // Foo was explicitly bound
+ ensureWorks(injector, Foo.class);
+ // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
+ // It is OK to call getBinding for introspection, but an error to get the provider
+ // of the binding
+ ensureFails(injector, true, FooImpl.class);
+ }
+
+ public void testBasicsWithEagerSingleton() {
+ Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(Foo.class).to(FooImpl.class).asEagerSingleton();
+ bind(Bar.class);
+ bind(FooBar.class);
+ }
+ }).build();
+ // Foo, Bar & FooBar was explicitly bound
+ ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
+ // FooImpl was implicitly bound, it is an error to call getInstance or getProvider,
+ // It is OK to call getBinding for introspection, but an error to get the provider
+ // of the binding
+ ensureFails(injector, true, FooImpl.class);
+ }
+
+ public void testLinkedToScoped() {
+ Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(Foo.class).to(ScopedFooImpl.class);
+ }
+ }).build();
+ // Foo was explicitly bound
+ ensureWorks(injector, Foo.class);
+ // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider,
+ // It is OK to call getBinding for introspection, but an error to get the provider
+ // of the binding
+ ensureFails(injector, true, ScopedFooImpl.class);
+ }
+
+ public void testBasicsWithScoped() {
+ Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(Foo.class).to(ScopedFooImpl.class);
+ bind(Bar.class);
+ bind(FooBar.class);
+ }
+ }).build();
+ // Foo, Bar & FooBar was explicitly bound
+ ensureWorks(injector, FooBar.class, Bar.class, Foo.class);
+ // FooSingletonImpl was implicitly bound, it is an error to call getInstance or getProvider,
+ // It is OK to call getBinding for introspection, but an error to get the provider
+ // of the binding
+ ensureFails(injector, true, ScopedFooImpl.class);
+ }
+
+ public void testFailsIfInjectingScopedDirectlyWhenItIsntBound() {
+ try {
+ new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(Foo.class).to(ScopedFooImpl.class);
+ bind(WantsScopedFooImpl.class);
+ }
+ }).build();
+ fail();
+ } catch(CreationException expected) {
+ assertContains(expected.getMessage(), "1) " + jitFailed(ScopedFooImpl.class));
+ assertTrue(expected.getMessage(), !expected.getMessage().contains("2) "));
+ }
+ }
+
public void testLinkedProviderBindingWorks() {
Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
@Override
@@ -127,6 +207,17 @@
ensureFails(injector, true, ImplByImpl.class);
}
+ public void testImplementedBySomethingThatIsAnnotated() {
+ Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(ImplByScoped.class);
+ }
+ }).build();
+ ensureWorks(injector, ImplByScoped.class);
+ ensureFails(injector, true, ImplByScopedImpl.class);
+ }
+
public void testProvidedBy() {
Injector injector = new InjectorBuilder().requireExplicitBindings().addModules(new AbstractModule() {
@Override
@@ -257,10 +348,14 @@
}
}
}
- }
+ }
private static interface Foo {}
private static class FooImpl implements Foo {}
+ @Singleton private static class ScopedFooImpl implements Foo {}
+ private static class WantsScopedFooImpl {
+ @SuppressWarnings("unused") @Inject ScopedFooImpl scopedFoo;
+ }
private static class Bar {}
private static class FooBar {
@SuppressWarnings("unused") @Inject Foo foo;
@@ -279,6 +374,11 @@
@ImplementedBy(ImplByImpl.class)
private static interface ImplBy {}
private static class ImplByImpl implements ImplBy {}
+
+ @ImplementedBy(ImplByScopedImpl.class)
+ private static interface ImplByScoped {}
+ @Singleton
+ private static class ImplByScopedImpl implements ImplByScoped {}
@ProvidedBy(ProvByProvider.class)
private static interface ProvBy {}