issue 506 - fail fast & with a useful error message when an AssistedInject factory has Provider<T> as a factory type. patch ( slightly modified) by ffaber.
git-svn-id: https://google-guice.googlecode.com/svn/trunk@1192 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java b/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java
index 5e3cf37..713068b 100644
--- a/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryModuleBuilder.java
@@ -173,6 +173,10 @@
* .implement(Car.class, Names.named("clean"), Prius.class)
* .build(CarFactory.class));
* }</pre>
+ *
+ * <h3>Implementation limitations</h3>
+ * As a limitation of the implementation, it is prohibited to declare a factory method that
+ * accepts a {@code Provider} as one of its arguments.
*
* @author schmitt@google.com (Peter Schmitt)
*/
diff --git a/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java b/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java
index d599166..d7ad255 100644
--- a/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java
+++ b/extensions/assistedinject/src/com/google/inject/assistedinject/FactoryProvider2.java
@@ -179,6 +179,13 @@
List<Key<?>> keys = Lists.newArrayList();
for (TypeLiteral<?> param : params) {
Key<?> paramKey = getKey(param, method, paramAnnotations[p++], errors);
+ Class<?> underlylingType = paramKey.getTypeLiteral().getRawType();
+ if (underlylingType.equals(Provider.class)
+ || underlylingType.equals(javax.inject.Provider.class)) {
+ errors.addMessage("A Provider may not be a type in a factory method of an AssistedInject."
+ + "\n Offending instance is parameter [%s] with key [%s] on method [%s]",
+ p, paramKey, method);
+ }
keys.add(assistKey(method, paramKey, errors));
}
ImmutableList<Key<?>> immutableParamList = ImmutableList.copyOf(keys);
@@ -407,7 +414,7 @@
}
return false;
}
-
+
/**
* Returns a key similar to {@code key}, but with an {@literal @}Assisted binding annotation.
* This fails if another binding annotation is clobbered in the process. If the key already has
@@ -466,7 +473,7 @@
final Key<?> assistedReturnType = Key.get(returnType.getTypeLiteral(), Assisted.class);
Module assistedModule = new AbstractModule() {
- @SuppressWarnings("unchecked") // raw keys are necessary for the args array and return value
+ @Override @SuppressWarnings("unchecked") // raw keys are necessary for the args array and return value
protected void configure() {
Binder binder = binder().withSource(method);
diff --git a/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProvider2Test.java b/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProvider2Test.java
index bd40290..58869ce 100644
--- a/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProvider2Test.java
+++ b/extensions/assistedinject/test/com/google/inject/assistedinject/FactoryProvider2Test.java
@@ -560,6 +560,73 @@
assertNull(subaru.colorProvider.get());
}
+ interface ProviderBasedColoredCarFactory {
+ Car createCar(Provider<Color> colorProvider, Provider<String> stringProvider);
+ Mustang createMustang(@Assisted("color") Provider<Color> colorProvider);
+ }
+
+ public void testAssistedProviderIsDisallowed() {
+ try {
+ Guice.createInjector(new AbstractModule() {
+ @Override protected void configure() {
+ bind(ProviderBasedColoredCarFactory.class).toProvider(
+ FactoryProvider.newFactory(ProviderBasedColoredCarFactory.class, Subaru.class));
+ }
+ });
+ fail();
+ } catch (CreationException expected) {
+ assertContains(expected.getMessage(),
+ "1) A Provider may not be a type in a factory method of an AssistedInject."
+ + "\n Offending instance is parameter [1] with key"
+ + " [com.google.inject.Provider<java.awt.Color>] on method ["
+ + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]",
+ "2) A Provider may not be a type in a factory method of an AssistedInject."
+ + "\n Offending instance is parameter [2] with key"
+ + " [com.google.inject.Provider<java.lang.String>] on method ["
+ + ProviderBasedColoredCarFactory.class.getName() + ".createCar()]",
+ "3) A Provider may not be a type in a factory method of an AssistedInject."
+ + "\n Offending instance is parameter [1] with key"
+ + " [com.google.inject.Provider<java.awt.Color>"
+ + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]"
+ + " on method [" + ProviderBasedColoredCarFactory.class.getName() + ".createMustang()]"
+ );
+
+ }
+ }
+
+ interface JavaxProviderBasedColoredCarFactory {
+ Car createCar(javax.inject.Provider<Color> colorProvider, javax.inject.Provider<String> stringProvider);
+ Mustang createMustang(@Assisted("color") javax.inject.Provider<Color> colorProvider);
+ }
+
+ public void testAssistedJavaxProviderIsDisallowed() {
+ try {
+ Guice.createInjector(new AbstractModule() {
+ @Override protected void configure() {
+ bind(JavaxProviderBasedColoredCarFactory.class).toProvider(
+ FactoryProvider.newFactory(JavaxProviderBasedColoredCarFactory.class, Subaru.class));
+ }
+ });
+ fail();
+ } catch (CreationException expected) {
+ assertContains(expected.getMessage(),
+ "1) A Provider may not be a type in a factory method of an AssistedInject."
+ + "\n Offending instance is parameter [1] with key"
+ + " [com.google.inject.Provider<java.awt.Color>] on method ["
+ + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]",
+ "2) A Provider may not be a type in a factory method of an AssistedInject."
+ + "\n Offending instance is parameter [2] with key"
+ + " [com.google.inject.Provider<java.lang.String>] on method ["
+ + JavaxProviderBasedColoredCarFactory.class.getName() + ".createCar()]",
+ "3) A Provider may not be a type in a factory method of an AssistedInject."
+ + "\n Offending instance is parameter [1] with key"
+ + " [com.google.inject.Provider<java.awt.Color>"
+ + " annotated with @com.google.inject.assistedinject.Assisted(value=color)]"
+ + " on method [" + JavaxProviderBasedColoredCarFactory.class.getName() + ".createMustang()]"
+ );
+ }
+ }
+
public void testFactoryUseBeforeInitialization() {
ColoredCarFactory carFactory = FactoryProvider.newFactory(ColoredCarFactory.class, Subaru.class)
.get();