Author: limpbizkit
Date: Fri Nov 14 00:43:40 2008
New Revision: 663
Added:
trunk/test/com/google/inject/TypeLiteralTypeResolutionTest.java
- copied, changed from r653,
/trunk/test/com/google/inject/internal/TypeResolverTest.java
Removed:
trunk/src/com/google/inject/internal/TypeResolver.java
Modified:
trunk/src/com/google/inject/TypeLiteral.java
trunk/src/com/google/inject/internal/MoreTypes.java
trunk/src/com/google/inject/internal/ProviderMethodsModule.java
trunk/src/com/google/inject/spi/InjectionPoint.java
trunk/test/com/google/inject/AllTests.java
trunk/test/com/google/inject/spi/InjectionPointTest.java
Log:
Made type resolution way fast. We no longer build any collections --
instead we just do everything on demand. A very naive benchmark showed this
to be much faster (50s vs 3s).
Also merged TypeResolver with TypeLiteral. This exposes a bunch of new APIs
for types - such as getting the generic parameter types of a method. I'm
not convinced that we should be exposing all of this, but it's nice for
extensions. For example, @Provides methods need type resolution.
Modified: trunk/src/com/google/inject/TypeLiteral.java
==============================================================================
--- trunk/src/com/google/inject/TypeLiteral.java (original)
+++ trunk/src/com/google/inject/TypeLiteral.java Fri Nov 14 00:43:40 2008
@@ -16,12 +16,21 @@
package com.google.inject;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.collect.ImmutableList;
import com.google.inject.internal.MoreTypes;
import static com.google.inject.internal.MoreTypes.canonicalize;
import com.google.inject.util.Types;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.List;
/**
* Represents a generic type [EMAIL PROTECTED] T}. Java doesn't yet provide a
way to
@@ -140,5 +149,152 @@
*/
public static <T> TypeLiteral<T> get(Class<T> type) {
return new TypeLiteral<T>(type);
+ }
+
+
+ /** Returns an immutable list of the resolved types. */
+ private List<Type> resolveAll(Type[] types) {
+ Type[] result = new Type[types.length];
+ for (int t = 0; t < types.length; t++) {
+ result[t] = resolve(types[t]);
+ }
+ return ImmutableList.of(result);
+ }
+
+ /**
+ * Resolves known type parameters in [EMAIL PROTECTED] toResolve} and
returns the
result.
+ */
+ Type resolve(Type toResolve) {
+ while (true) {
+ if (toResolve instanceof TypeVariable) {
+ TypeVariable original = (TypeVariable) toResolve;
+ toResolve = MoreTypes.resolveTypeVariable(type, rawType, original);
+ if (toResolve == original) {
+ return toResolve;
+ }
+
+ } else if (toResolve instanceof GenericArrayType) {
+ GenericArrayType original = (GenericArrayType) toResolve;
+ Type componentType = original.getGenericComponentType();
+ Type newComponentType = resolve(componentType);
+ return componentType == newComponentType
+ ? original
+ : Types.arrayOf(newComponentType);
+
+ } else if (toResolve instanceof ParameterizedType) {
+ ParameterizedType original = (ParameterizedType) toResolve;
+ Type ownerType = original.getOwnerType();
+ Type newOwnerType = resolve(ownerType);
+ boolean changed = newOwnerType != ownerType;
+
+ Type[] args = original.getActualTypeArguments();
+ for (int t = 0, length = args.length; t < length; t++) {
+ Type resolvedTypeArgument = resolve(args[t]);
+ if (resolvedTypeArgument != args[t]) {
+ if (!changed) {
+ args = args.clone();
+ changed = true;
+ }
+ args[t] = resolvedTypeArgument;
+ }
+ }
+
+ return changed
+ ? Types.newParameterizedTypeWithOwner(newOwnerType,
original.getRawType(), args)
+ : original;
+
+ } else {
+ return toResolve;
+ }
+ }
+ }
+
+ /**
+ * Returns the generic form of [EMAIL PROTECTED] supertype}. For example, if
this
is [EMAIL PROTECTED]
+ * ArrayList<String>}, this returns [EMAIL PROTECTED] Iterable<String>}
given the
input [EMAIL PROTECTED]
+ * Iterable.class}.
+ *
+ * @param supertype a superclass of, or interface implemented by, this.
+ */
+ public Type getSupertype(Class<?> supertype) {
+ checkArgument(supertype.isAssignableFrom(rawType),
+ "%s is not a supertype of %s", supertype, this.type);
+ return resolve(MoreTypes.getGenericSupertype(type, rawType,
supertype));
+ }
+
+ /**
+ * Returns the resolved generic type of [EMAIL PROTECTED] field}.
+ *
+ * @param field a field defined by this or any superclass.
+ */
+ public Type getFieldType(Field field) {
+ checkArgument(field.getDeclaringClass().isAssignableFrom(rawType),
+ "%s is not defined by a supertype of %s", field, type);
+ return resolve(field.getGenericType());
+ }
+
+ /**
+ * Returns the resolved generic parameter types of [EMAIL PROTECTED]
methodOrConstructor}.
+ *
+ * @param methodOrConstructor a method or constructor defined by this or
any supertype.
+ */
+ public List<Type> getParameterTypes(Member methodOrConstructor) {
+ Type[] genericParameterTypes;
+
+ if (methodOrConstructor instanceof Method) {
+ Method method = (Method) methodOrConstructor;
+ checkArgument(method.getDeclaringClass().isAssignableFrom(rawType),
+ "%s is not defined by a supertype of %s", method, type);
+ genericParameterTypes = method.getGenericParameterTypes();
+
+ } else if (methodOrConstructor instanceof Constructor) {
+ Constructor constructor = (Constructor) methodOrConstructor;
+
checkArgument(constructor.getDeclaringClass().isAssignableFrom(rawType),
+ "%s does not construct a supertype of %s", constructor, type);
+ genericParameterTypes = constructor.getGenericParameterTypes();
+
+ } else {
+ throw new IllegalArgumentException("Not a method or a constructor: "
+ methodOrConstructor);
+ }
+
+ return resolveAll(genericParameterTypes);
+ }
+
+ /**
+ * Returns the resolved generic exception types thrown by [EMAIL PROTECTED]
constructor}.
+ *
+ * @param methodOrConstructor a method or constructor defined by this or
any supertype.
+ */
+ public List<Type> getExceptionTypes(Member methodOrConstructor) {
+ Type[] genericExceptionTypes;
+
+ if (methodOrConstructor instanceof Method) {
+ Method method = (Method) methodOrConstructor;
+ checkArgument(method.getDeclaringClass().isAssignableFrom(rawType),
+ "%s is not defined by a supertype of %s", method, type);
+ genericExceptionTypes = method.getGenericExceptionTypes();
+
+ } else if (methodOrConstructor instanceof Constructor) {
+ Constructor<?> constructor = (Constructor<?>) methodOrConstructor;
+
checkArgument(constructor.getDeclaringClass().isAssignableFrom(rawType),
+ "%s does not construct a supertype of %s", constructor, type);
+ genericExceptionTypes = constructor.getGenericExceptionTypes();
+
+ } else {
+ throw new IllegalArgumentException("Not a method or a constructor: "
+ methodOrConstructor);
+ }
+
+ return resolveAll(genericExceptionTypes);
+ }
+
+ /**
+ * Returns the resolved generic return type of [EMAIL PROTECTED] method}.
+ *
+ * @param method a method defined by this or any supertype.
+ */
+ public Type getReturnType(Method method) {
+ checkArgument(method.getDeclaringClass().isAssignableFrom(rawType),
+ "%s is not defined by a supertype of %s", method, type);
+ return resolve(method.getGenericReturnType());
}
}
Modified: trunk/src/com/google/inject/internal/MoreTypes.java
==============================================================================
--- trunk/src/com/google/inject/internal/MoreTypes.java (original)
+++ trunk/src/com/google/inject/internal/MoreTypes.java Fri Nov 14 00:43:40
2008
@@ -26,13 +26,16 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Arrays;
import java.util.Map;
+import java.util.NoSuchElementException;
/**
* Static methods for working with types that we aren't publishing in the
@@ -337,6 +340,82 @@
throw new IllegalArgumentException(
"Unsupported implementation class for Member, " +
member.getClass());
}
+ }
+
+ /**
+ * Returns the generic supertype for [EMAIL PROTECTED] supertype}. For
example,
given a class [EMAIL PROTECTED]
+ * IntegerSet}, the result for when supertype is [EMAIL PROTECTED]
Set.class} is
[EMAIL PROTECTED] Set<Integer>} and the
+ * result when the supertype is [EMAIL PROTECTED] Collection.class} is
[EMAIL PROTECTED]
Collection<Integer>}.
+ */
+ public static Type getGenericSupertype(Type type, Class<?> rawType,
Class<?> toResolve) {
+ if (toResolve == rawType) {
+ return type;
+ }
+
+ // we skip searching through interfaces if unknown is an interface
+ if (toResolve.isInterface()) {
+ Class[] interfaces = rawType.getInterfaces();
+ for (int i = 0, length = interfaces.length; i < length; i++) {
+ if (interfaces[i] == toResolve) {
+ return rawType.getGenericInterfaces()[i];
+ } else if (toResolve.isAssignableFrom(interfaces[i])) {
+ return getGenericSupertype(rawType.getGenericInterfaces()[i],
interfaces[i], toResolve);
+ }
+ }
+ }
+
+ // check our supertypes
+ if (!rawType.isInterface()) {
+ while (rawType != Object.class) {
+ Class<?> rawSupertype = rawType.getSuperclass();
+ if (rawSupertype == toResolve) {
+ return rawType.getGenericSuperclass();
+ } else if (toResolve.isAssignableFrom(rawSupertype)) {
+ return getGenericSupertype(rawType.getGenericSuperclass(),
rawSupertype, toResolve);
+ }
+ rawType = rawSupertype;
+ }
+ }
+
+ // we can't resolve this further
+ return toResolve;
+ }
+
+ public static Type resolveTypeVariable(Type type, Class<?> rawType,
TypeVariable unknown) {
+ Class<?> declaredByRaw = declaringClassOf(unknown);
+
+ // we can't reduce this further
+ if (declaredByRaw == null) {
+ return unknown;
+ }
+
+ Type declaredBy = getGenericSupertype(type, rawType, declaredByRaw);
+ if (declaredBy instanceof ParameterizedType) {
+ int index = indexOf(declaredByRaw.getTypeParameters(), unknown);
+ return ((ParameterizedType)
declaredBy).getActualTypeArguments()[index];
+ }
+
+ return unknown;
+ }
+
+ private static int indexOf(Object[] array, Object toFind) {
+ for (int i = 0; i < array.length; i++) {
+ if (toFind.equals(array[i])) {
+ return i;
+ }
+ }
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * Returns the declaring class of [EMAIL PROTECTED] typeVariable}, or [EMAIL
PROTECTED] null}
if it was not declared by
+ * a class.
+ */
+ private static Class<?> declaringClassOf(TypeVariable typeVariable) {
+ GenericDeclaration genericDeclaration =
typeVariable.getGenericDeclaration();
+ return genericDeclaration instanceof Class
+ ? (Class<?>) genericDeclaration
+ : null;
}
public static class ParameterizedTypeImpl implements ParameterizedType,
Serializable {
Modified: trunk/src/com/google/inject/internal/ProviderMethodsModule.java
==============================================================================
--- trunk/src/com/google/inject/internal/ProviderMethodsModule.java
(original)
+++ trunk/src/com/google/inject/internal/ProviderMethodsModule.java Fri Nov
14 00:43:40 2008
@@ -16,9 +16,8 @@
package com.google.inject.internal;
-import com.google.common.base.Preconditions;
-import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Lists;
import com.google.inject.Binder;
import com.google.inject.Key;
@@ -43,11 +42,11 @@
*/
public final class ProviderMethodsModule implements Module {
private final Module delegate;
- private final TypeResolver typeResolver;
+ private final TypeLiteral<?> typeLiteral;
private ProviderMethodsModule(Module delegate) {
this.delegate = checkNotNull(delegate, "delegate");
- this.typeResolver = new TypeResolver(this.delegate.getClass());
+ this.typeLiteral = TypeLiteral.get(this.delegate.getClass());
}
/**
@@ -108,7 +107,7 @@
// prepare the parameter providers
List<Provider<?>> parameterProviders = Lists.newArrayList();
- List<Type> parameterTypes = typeResolver.getParameterTypes(method);
+ List<Type> parameterTypes = typeLiteral.getParameterTypes(method);
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
for (int i = 0; i < parameterTypes.size(); i++) {
Key<?> key = getKey(errors, TypeLiteral.get(parameterTypes.get(i)),
@@ -118,7 +117,7 @@
// Define T as the method's return type.
@SuppressWarnings("unchecked") TypeLiteral<T> returnType
- = (TypeLiteral<T>)
TypeLiteral.get(typeResolver.getReturnType(method));
+ = (TypeLiteral<T>)
TypeLiteral.get(typeLiteral.getReturnType(method));
Key<T> key = getKey(errors, returnType, method,
method.getAnnotations());
Class<? extends Annotation> scopeAnnotation
Modified: trunk/src/com/google/inject/spi/InjectionPoint.java
==============================================================================
--- trunk/src/com/google/inject/spi/InjectionPoint.java (original)
+++ trunk/src/com/google/inject/spi/InjectionPoint.java Fri Nov 14 00:43:40
2008
@@ -21,12 +21,12 @@
import com.google.inject.ConfigurationException;
import com.google.inject.Inject;
import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
import com.google.inject.internal.Annotations;
import com.google.inject.internal.Errors;
import com.google.inject.internal.ErrorsException;
import com.google.inject.internal.MoreTypes;
import com.google.inject.internal.Nullability;
-import com.google.inject.internal.TypeResolver;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.annotation.Annotation;
@@ -62,22 +62,22 @@
this.optional = optional;
}
- InjectionPoint(TypeResolver typeResolver, Method method) {
+ InjectionPoint(TypeLiteral<?> type, Method method) {
this.member = method;
Inject inject = method.getAnnotation(Inject.class);
this.optional = inject.optional();
- this.dependencies = forMember(method, typeResolver,
method.getParameterAnnotations());
+ this.dependencies = forMember(method, type,
method.getParameterAnnotations());
}
- InjectionPoint(TypeResolver typeResolver, Constructor<?> constructor) {
+ InjectionPoint(TypeLiteral<?> type, Constructor<?> constructor) {
this.member = constructor;
this.optional = false;
- this.dependencies = forMember(constructor, typeResolver,
constructor.getParameterAnnotations());
+ this.dependencies = forMember(constructor, type,
constructor.getParameterAnnotations());
}
- InjectionPoint(TypeResolver typeResolver, Field field) {
+ InjectionPoint(TypeLiteral<?> type, Field field) {
this.member = field;
Inject inject = field.getAnnotation(Inject.class);
@@ -88,7 +88,7 @@
Errors errors = new Errors(field);
Key<?> key = null;
try {
- key = Annotations.getKey(typeResolver.getFieldType(field), field,
annotations, errors);
+ key = Annotations.getKey(type.getFieldType(field), field,
annotations, errors);
} catch (ErrorsException e) {
errors.merge(e.getErrors());
}
@@ -98,7 +98,7 @@
newDependency(key, Nullability.allowsNull(annotations), -1));
}
- private ImmutableList<Dependency<?>> forMember(Member member,
TypeResolver typeResolver,
+ private ImmutableList<Dependency<?>> forMember(Member member,
TypeLiteral<?> type,
Annotation[][] paramterAnnotations) {
Errors errors = new Errors(member);
Iterator<Annotation[]> annotationsIterator =
Arrays.asList(paramterAnnotations).iterator();
@@ -106,7 +106,7 @@
List<Dependency<?>> dependencies = Lists.newArrayList();
int index = 0;
- for (Type parameterType : typeResolver.getParameterTypes(member)) {
+ for (Type parameterType : type.getParameterTypes(member)) {
try {
Annotation[] parameterAnnotations = annotationsIterator.next();
Key<?> key = Annotations.getKey(parameterType, member,
parameterAnnotations, errors);
@@ -183,8 +183,8 @@
*/
public static InjectionPoint forConstructorOf(Type type) {
Errors errors = new Errors(type);
- TypeResolver typeResolver = new TypeResolver(type);
- Class<?> rawType = typeResolver.getRawType();
+ TypeLiteral<?> typeLiteral = TypeLiteral.get(type);
+ Class<?> rawType = MoreTypes.getRawType(type);
Constructor<?> injectableConstructor = null;
for (Constructor<?> constructor : rawType.getDeclaredConstructors()) {
@@ -206,7 +206,7 @@
errors.throwConfigurationExceptionIfErrorsExist();
if (injectableConstructor != null) {
- return new InjectionPoint(typeResolver, injectableConstructor);
+ return new InjectionPoint(typeLiteral, injectableConstructor);
}
// If no annotated constructor is found, look for a no-arg constructor
instead.
@@ -221,7 +221,7 @@
}
checkForMisplacedBindingAnnotations(noArgConstructor, errors);
- return new InjectionPoint(typeResolver, noArgConstructor);
+ return new InjectionPoint(typeLiteral, noArgConstructor);
} catch (NoSuchMethodException e) {
errors.missingConstructor(rawType);
throw new ConfigurationException(errors.getMessages());
@@ -239,8 +239,9 @@
*/
public static void addForStaticMethodsAndFields(Type type,
Collection<InjectionPoint> sink) {
Errors errors = new Errors();
- addInjectionPoints(type, Factory.FIELDS, true, sink, errors);
- addInjectionPoints(type, Factory.METHODS, true, sink, errors);
+ TypeLiteral<?> typeLiteral = TypeLiteral.get(type);
+ addInjectionPoints(typeLiteral, Factory.FIELDS, true, sink, errors);
+ addInjectionPoints(typeLiteral, Factory.METHODS, true, sink, errors);
errors.throwConfigurationExceptionIfErrorsExist();
}
@@ -256,8 +257,9 @@
public static void addForInstanceMethodsAndFields(Type type,
Collection<InjectionPoint> sink) {
// TODO (crazybob): Filter out overridden members.
Errors errors = new Errors();
- addInjectionPoints(type, Factory.FIELDS, false, sink, errors);
- addInjectionPoints(type, Factory.METHODS, false, sink, errors);
+ TypeLiteral<?> typeLiteral = TypeLiteral.get(type);
+ addInjectionPoints(typeLiteral, Factory.FIELDS, false, sink, errors);
+ addInjectionPoints(typeLiteral, Factory.METHODS, false, sink, errors);
errors.throwConfigurationExceptionIfErrorsExist();
}
@@ -269,27 +271,25 @@
}
}
- private static <M extends Member & AnnotatedElement> void
addInjectionPoints(Type type,
+ private static <M extends Member & AnnotatedElement> void
addInjectionPoints(TypeLiteral<?> type,
Factory<M> factory, boolean statics, Collection<InjectionPoint>
injectionPoints,
Errors errors) {
- if (type == Object.class) {
+ if (type.getType() == Object.class) {
return;
}
- TypeResolver typeResolver = new TypeResolver(type);
-
// Add injectors for superclass first.
- Type superType =
typeResolver.getSupertype(MoreTypes.getRawType(type).getSuperclass());
- addInjectionPoints(superType, factory, statics, injectionPoints,
errors);
+ Type superType =
type.getSupertype(MoreTypes.getRawType(type.getType()).getSuperclass());
+ addInjectionPoints(TypeLiteral.get(superType), factory, statics,
injectionPoints, errors);
// Add injectors for all members next
- addInjectorsForMembers(typeResolver, factory, statics,
injectionPoints, errors);
+ addInjectorsForMembers(type, factory, statics, injectionPoints,
errors);
}
private static <M extends Member & AnnotatedElement> void
addInjectorsForMembers(
- TypeResolver typeResolver, Factory<M> factory, boolean statics,
+ TypeLiteral<?> typeResolver, Factory<M> factory, boolean statics,
Collection<InjectionPoint> injectionPoints, Errors errors) {
- for (M member : factory.getMembers(typeResolver.getRawType())) {
+ for (M member :
factory.getMembers(MoreTypes.getRawType(typeResolver.getType()))) {
if (isStatic(member) != statics) {
continue;
}
@@ -318,7 +318,7 @@
public Field[] getMembers(Class<?> type) {
return type.getDeclaredFields();
}
- public InjectionPoint create(TypeResolver typeResolver, Field
member, Errors errors) {
+ public InjectionPoint create(TypeLiteral<?> typeResolver, Field
member, Errors errors) {
return new InjectionPoint(typeResolver, member);
}
};
@@ -327,14 +327,14 @@
public Method[] getMembers(Class<?> type) {
return type.getDeclaredMethods();
}
- public InjectionPoint create(TypeResolver typeResolver, Method
member, Errors errors) {
+ public InjectionPoint create(TypeLiteral<?> typeResolver, Method
member, Errors errors) {
checkForMisplacedBindingAnnotations(member, errors);
return new InjectionPoint(typeResolver, member);
}
};
M[] getMembers(Class<?> type);
- InjectionPoint create(TypeResolver typeResolver, M member, Errors
errors);
+ InjectionPoint create(TypeLiteral<?> typeResolver, M member, Errors
errors);
}
private static final long serialVersionUID = 0;
Modified: trunk/test/com/google/inject/AllTests.java
==============================================================================
--- trunk/test/com/google/inject/AllTests.java (original)
+++ trunk/test/com/google/inject/AllTests.java Fri Nov 14 00:43:40 2008
@@ -77,6 +77,7 @@
suite.addTestSuite(RequestInjectionTest.class);
suite.addTestSuite(SuperclassTest.class);
suite.addTestSuite(TypeLiteralTest.class);
+ suite.addTestSuite(TypeLiteralTypeResolutionTest.class);
// commands
suite.addTestSuite(ElementsTest.class);
Copied: trunk/test/com/google/inject/TypeLiteralTypeResolutionTest.java
(from r653, /trunk/test/com/google/inject/internal/TypeResolverTest.java)
==============================================================================
--- /trunk/test/com/google/inject/internal/TypeResolverTest.java
(original)
+++ trunk/test/com/google/inject/TypeLiteralTypeResolutionTest.java Fri Nov
14 00:43:40 2008
@@ -14,11 +14,12 @@
* limitations under the License.
*/
-package com.google.inject.internal;
+package com.google.inject;
import com.google.common.collect.ImmutableList;
import static com.google.inject.Asserts.assertEqualsBothWays;
import static com.google.inject.Asserts.assertNotSerializable;
+import com.google.inject.util.Types;
import static com.google.inject.util.Types.arrayOf;
import static com.google.inject.util.Types.listOf;
import static com.google.inject.util.Types.newParameterizedType;
@@ -29,28 +30,41 @@
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
+import java.util.AbstractCollection;
import java.util.AbstractList;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import junit.framework.TestCase;
-public class TypeResolverTest extends TestCase {
+/**
+ * This test checks that TypeLiteral can perform type resolution on its
members.
+ *
+ * @author [EMAIL PROTECTED] (Jesse Wilson)
+ */
+public class TypeLiteralTypeResolutionTest extends TestCase {
Type arrayListOfString = newParameterizedType(ArrayList.class,
String.class);
Type hasGenericFieldsOfShort = newParameterizedTypeWithOwner(
getClass(), HasGenericFields.class, Short.class);
Type hasGenericConstructorOfShort = newParameterizedTypeWithOwner(
- getClass(), HasGenericConstructor.class, Short.class);
+ getClass(), GenericConstructor.class, Short.class);
Type throwerOfNpe = newParameterizedTypeWithOwner(
getClass(), Thrower.class, NullPointerException.class);
Type hasArrayOfShort = newParameterizedTypeWithOwner(getClass(),
HasArray.class, Short.class);
Type hasRelatedOfString = newParameterizedTypeWithOwner(
getClass(), HasRelated.class, String.class, String.class);
+ Type mapK = Map.class.getTypeParameters()[0];
+ Type hashMapK = HashMap.class.getTypeParameters()[0];
+ Type setEntryKV;
+ Type entryStringInteger = setOf(newParameterizedTypeWithOwner(
+ Map.class, Map.Entry.class, String.class, Integer.class));
Field list;
Field instance;
- Constructor<HasGenericConstructor> newHasGenericConstructor;
+ Constructor<GenericConstructor> newHasGenericConstructor;
Constructor<Thrower> newThrower;
Constructor newString;
Method stringIndexOf;
@@ -60,12 +74,12 @@
Method echo;
Method throwS;
- protected void setUp() throws Exception {
+ @Override protected void setUp() throws Exception {
super.setUp();
list = HasGenericFields.class.getField("list");
instance = HasGenericFields.class.getField("instance");
- newHasGenericConstructor =
HasGenericConstructor.class.getConstructor(Object.class, Object.class);
+ newHasGenericConstructor =
GenericConstructor.class.getConstructor(Object.class, Object.class);
newThrower = Thrower.class.getConstructor();
stringIndexOf = String.class.getMethod("indexOf", String.class);
newString = String.class.getConstructor(String.class);
@@ -74,10 +88,11 @@
getSetOfArray = HasArray.class.getMethod("getSetOfArray");
echo = HasRelated.class.getMethod("echo", Object.class);
throwS = Thrower.class.getMethod("throwS");
+ setEntryKV =
HashMap.class.getMethod("entrySet").getGenericReturnType();
}
public void testDirectInheritance() throws NoSuchMethodException {
- TypeResolver resolver = new TypeResolver(arrayListOfString);
+ TypeLiteral<?> resolver = TypeLiteral.get(arrayListOfString);
assertEquals(listOf(String.class),
resolver.getReturnType(List.class.getMethod("subList", int.class,
int.class)));
assertEquals(ImmutableList.<Type>of(String.class),
@@ -85,7 +100,7 @@
}
public void testGenericSupertype() {
- TypeResolver resolver = new TypeResolver(arrayListOfString);
+ TypeLiteral<?> resolver = TypeLiteral.get(arrayListOfString);
assertEquals(newParameterizedType(Collection.class, String.class),
resolver.getSupertype(Collection.class));
assertEquals(newParameterizedType(Iterable.class, String.class),
@@ -96,7 +111,7 @@
}
public void testRecursiveTypeVariable() {
- TypeResolver resolver = new TypeResolver(MyInteger.class);
+ TypeLiteral<?> resolver = TypeLiteral.get(MyInteger.class);
assertEquals(MyInteger.class,
resolver.getParameterTypes(comparableCompareTo).get(0));
}
@@ -110,7 +125,7 @@
}
public void testFields() {
- TypeResolver resolver = new TypeResolver(hasGenericFieldsOfShort);
+ TypeLiteral<?> resolver = TypeLiteral.get(hasGenericFieldsOfShort);
assertEquals(listOf(Short.class), resolver.getFieldType(list));
assertEquals(Short.class, resolver.getFieldType(instance));
}
@@ -121,17 +136,17 @@
}
public void testGenericConstructor() throws NoSuchMethodException {
- TypeResolver resolver = new TypeResolver(hasGenericConstructorOfShort);
+ TypeLiteral<?> resolver =
TypeLiteral.get(hasGenericConstructorOfShort);
assertEquals(Short.class,
resolver.getParameterTypes(newHasGenericConstructor).get(0));
}
- static class HasGenericConstructor<S> {
+ static class GenericConstructor<S> {
@SuppressWarnings("UnusedDeclaration")
- public <T> HasGenericConstructor(S s, T t) {}
+ public <T> GenericConstructor(S s, T t) {}
}
public void testThrowsExceptions() {
- TypeResolver resolver = new TypeResolver(throwerOfNpe);
+ TypeLiteral<?> resolver = TypeLiteral.get(throwerOfNpe);
assertEquals(NullPointerException.class,
resolver.getExceptionTypes(newThrower).get(0));
assertEquals(NullPointerException.class,
resolver.getExceptionTypes(throwS).get(0));
}
@@ -142,7 +157,7 @@
}
public void testArrays() {
- TypeResolver resolver = new TypeResolver(hasArrayOfShort);
+ TypeLiteral<?> resolver = TypeLiteral.get(hasArrayOfShort);
assertEquals(arrayOf(Short.class), resolver.getReturnType(getArray));
assertEquals(setOf(arrayOf(Short.class)),
resolver.getReturnType(getSetOfArray));
}
@@ -153,7 +168,7 @@
}
public void testRelatedTypeVariables() {
- TypeResolver resolver = new TypeResolver(hasRelatedOfString);
+ TypeLiteral<?> resolver = TypeLiteral.get(hasRelatedOfString);
assertEquals(String.class, resolver.getParameterTypes(echo).get(0));
assertEquals(String.class, resolver.getReturnType(echo));
}
@@ -164,7 +179,7 @@
/** Ensure the cache doesn't cache too much */
public void testCachingAndReindexing() throws NoSuchMethodException {
- TypeResolver resolver = new TypeResolver(
+ TypeLiteral<?> resolver = TypeLiteral.get(
newParameterizedTypeWithOwner(getClass(), HasLists.class,
String.class, Short.class));
assertEquals(listOf(String.class),
resolver.getReturnType(HasLists.class.getMethod("listS")));
@@ -179,53 +194,114 @@
}
public void testUnsupportedQueries() throws NoSuchMethodException {
- TypeResolver resolver = new TypeResolver(arrayListOfString);
+ TypeLiteral<?> resolver = TypeLiteral.get(arrayListOfString);
try {
resolver.getExceptionTypes(stringIndexOf);
+ fail();
} catch (IllegalArgumentException e) {
assertEquals("public int java.lang.String.indexOf(java.lang.String)
is not defined by a "
+ "supertype of java.util.ArrayList<java.lang.String>",
e.getMessage());
}
try {
resolver.getParameterTypes(stringIndexOf);
+ fail();
} catch (Exception e) {
assertEquals("public int java.lang.String.indexOf(java.lang.String)
is not defined by a "
+ "supertype of java.util.ArrayList<java.lang.String>",
e.getMessage());
}
try {
resolver.getReturnType(stringIndexOf);
+ fail();
} catch (Exception e) {
assertEquals("public int java.lang.String.indexOf(java.lang.String)
is not defined by a "
+ "supertype of java.util.ArrayList<java.lang.String>",
e.getMessage());
}
try {
resolver.getSupertype(String.class);
+ fail();
} catch (Exception e) {
assertEquals("class java.lang.String is not a supertype of "
+ "java.util.ArrayList<java.lang.String>", e.getMessage());
}
try {
resolver.getExceptionTypes(newString);
+ fail();
} catch (Exception e) {
assertEquals("public java.lang.String(java.lang.String) does not
construct "
+ "a supertype of java.util.ArrayList<java.lang.String>",
e.getMessage());
}
try {
resolver.getParameterTypes(newString);
+ fail();
} catch (Exception e) {
assertEquals("public java.lang.String(java.lang.String) does not
construct "
+ "a supertype of java.util.ArrayList<java.lang.String>",
e.getMessage());
}
}
+ public void testResolve() {
+ TypeLiteral<?> typeResolver = TypeLiteral.get(StringIntegerMap.class);
+ assertEquals(String.class, typeResolver.resolve(mapK));
+
+ typeResolver = new TypeLiteral<Map<String, Integer>>() {};
+ assertEquals(String.class, typeResolver.resolve(mapK));
+ assertEquals(Types.mapOf(String.class, Integer.class),
typeResolver.getSupertype(Map.class));
+
+ typeResolver = new TypeLiteral<BetterMap<String, Integer>>() {};
+ assertEquals(String.class, typeResolver.resolve(mapK));
+
+ typeResolver = new TypeLiteral<BestMap<String, Integer>>() {};
+ assertEquals(String.class, typeResolver.resolve(mapK));
+
+ typeResolver = TypeLiteral.get(StringIntegerHashMap.class);
+ assertEquals(String.class, typeResolver.resolve(mapK));
+ assertEquals(String.class, typeResolver.resolve(hashMapK));
+ assertEquals(entryStringInteger, typeResolver.resolve(setEntryKV));
+ assertEquals(Object.class, typeResolver.getSupertype(Object.class));
+ }
+
+ public void testOnObject() {
+ TypeLiteral<?> typeResolver = TypeLiteral.get(Object.class);
+ assertEquals(Object.class, typeResolver.getSupertype(Object.class));
+ assertEquals(Object.class, typeResolver.getRawType());
+
+ // interfaces also resolve Object
+ typeResolver = TypeLiteral.get(Types.setOf(Integer.class));
+ assertEquals(Object.class, typeResolver.getSupertype(Object.class));
+ }
+
+ interface StringIntegerMap extends Map<String, Integer> {}
+ interface BetterMap<K1, V1> extends Map<K1, V1> {}
+ interface BestMap<K2, V2> extends BetterMap<K2, V2> {}
+ static class StringIntegerHashMap extends HashMap<String, Integer> {}
+
+ public void testGetSupertype() {
+ TypeLiteral<AbstractList<String>> listOfString = new
TypeLiteral<AbstractList<String>>() {};
+ assertEquals(Types.newParameterizedType(AbstractCollection.class,
String.class),
+ listOfString.getSupertype(AbstractCollection.class));
+
+ TypeLiteral arrayListOfE = TypeLiteral.get(newParameterizedType(
+ ArrayList.class, ArrayList.class.getTypeParameters()));
+ assertEquals(newParameterizedType(AbstractCollection.class,
+ ArrayList.class.getTypeParameters()),
arrayListOfE.getSupertype(AbstractCollection.class));
+ }
+
+ public void testGetSupertypeForArraysAsList() {
+ Class<? extends List> arraysAsListClass = Arrays.asList().getClass();
+ Type anotherE = arraysAsListClass.getTypeParameters()[0];
+ TypeLiteral type =
TypeLiteral.get(newParameterizedType(AbstractList.class, anotherE));
+ assertEquals(newParameterizedType(AbstractCollection.class, anotherE),
+ type.getSupertype(AbstractCollection.class));
+ }
+
// TODO(jessewilson): tests for tricky bounded types like <T extends
Collection, Serializable>
// TODO(jessewilson): tests for wildcard types
public void testEqualsAndHashCode() throws IOException {
- TypeResolver a1 = new TypeResolver(arrayListOfString);
- TypeResolver a2 = new TypeResolver(arrayListOfString);
- TypeResolver b = new TypeResolver(listOf(String.class));
+ TypeLiteral<?> a1 = TypeLiteral.get(arrayListOfString);
+ TypeLiteral<?> a2 = TypeLiteral.get(arrayListOfString);
+ TypeLiteral<?> b = TypeLiteral.get(listOf(String.class));
assertEqualsBothWays(a1, a2);
assertNotSerializable(a1);
assertFalse(a1.equals(b));
Modified: trunk/test/com/google/inject/spi/InjectionPointTest.java
==============================================================================
--- trunk/test/com/google/inject/spi/InjectionPointTest.java (original)
+++ trunk/test/com/google/inject/spi/InjectionPointTest.java Fri Nov 14
00:43:40 2008
@@ -25,7 +25,6 @@
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.ErrorsException;
-import com.google.inject.internal.TypeResolver;
import com.google.inject.name.Named;
import static com.google.inject.name.Names.named;
import java.io.IOException;
@@ -51,14 +50,14 @@
}
public void testFieldInjectionPoint() throws NoSuchFieldException,
IOException, ErrorsException {
- TypeResolver typeResolver = new TypeResolver(getClass());
+ TypeLiteral<?> typeLiteral = TypeLiteral.get(getClass());
Field fooField = getClass().getField("foo");
- InjectionPoint injectionPoint = new InjectionPoint(typeResolver,
fooField);
+ InjectionPoint injectionPoint = new InjectionPoint(typeLiteral,
fooField);
assertSame(fooField, injectionPoint.getMember());
assertFalse(injectionPoint.isOptional());
assertEquals(getClass().getName() + ".foo", injectionPoint.toString());
- assertEqualsBothWays(injectionPoint, new InjectionPoint(typeResolver,
fooField));
+ assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral,
fooField));
assertSimilarWhenReserialized(injectionPoint);
Dependency<?> dependency =
getOnlyElement(injectionPoint.getDependencies());
@@ -70,18 +69,18 @@
assertEquals(false, dependency.isNullable());
assertSimilarWhenReserialized(dependency);
assertEqualsBothWays(dependency,
- getOnlyElement(new InjectionPoint(typeResolver,
fooField).getDependencies()));
+ getOnlyElement(new InjectionPoint(typeLiteral,
fooField).getDependencies()));
}
public void testMethodInjectionPoint() throws Exception {
- TypeResolver typeResolver = new TypeResolver(getClass());
+ TypeLiteral<?> typeLiteral = TypeLiteral.get(getClass());
Method barMethod = getClass().getMethod("bar", String.class);
- InjectionPoint injectionPoint = new InjectionPoint(typeResolver,
barMethod);
+ InjectionPoint injectionPoint = new InjectionPoint(typeLiteral,
barMethod);
assertSame(barMethod, injectionPoint.getMember());
assertFalse(injectionPoint.isOptional());
assertEquals(getClass().getName() + ".bar()",
injectionPoint.toString());
- assertEqualsBothWays(injectionPoint, new InjectionPoint(typeResolver,
barMethod));
+ assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral,
barMethod));
assertSimilarWhenReserialized(injectionPoint);
Dependency<?> dependency =
getOnlyElement(injectionPoint.getDependencies());
@@ -93,19 +92,19 @@
assertEquals(false, dependency.isNullable());
assertSimilarWhenReserialized(dependency);
assertEqualsBothWays(dependency,
- getOnlyElement(new InjectionPoint(typeResolver,
barMethod).getDependencies()));
+ getOnlyElement(new InjectionPoint(typeLiteral,
barMethod).getDependencies()));
}
public void testConstructorInjectionPoint() throws
NoSuchMethodException, IOException,
ErrorsException {
- TypeResolver typeResolver = new TypeResolver(Constructable.class);
+ TypeLiteral<?> typeLiteral = TypeLiteral.get(Constructable.class);
Constructor<?> constructor =
Constructable.class.getConstructor(String.class);
- InjectionPoint injectionPoint = new InjectionPoint(typeResolver,
constructor);
+ InjectionPoint injectionPoint = new InjectionPoint(typeLiteral,
constructor);
assertSame(constructor, injectionPoint.getMember());
assertFalse(injectionPoint.isOptional());
assertEquals(Constructable.class.getName() + ".<init>()",
injectionPoint.toString());
- assertEqualsBothWays(injectionPoint, new InjectionPoint(typeResolver,
constructor));
+ assertEqualsBothWays(injectionPoint, new InjectionPoint(typeLiteral,
constructor));
assertSimilarWhenReserialized(injectionPoint);
Dependency<?> dependency =
getOnlyElement(injectionPoint.getDependencies());
@@ -117,7 +116,7 @@
assertEquals(false, dependency.isNullable());
assertSimilarWhenReserialized(dependency);
assertEqualsBothWays(dependency,
- getOnlyElement(new InjectionPoint(typeResolver,
constructor).getDependencies()));
+ getOnlyElement(new InjectionPoint(typeLiteral,
constructor).getDependencies()));
}
public void testUnattachedDependency() throws IOException {
@@ -144,8 +143,8 @@
Set<InjectionPoint> sink = Sets.newHashSet();
InjectionPoint.addForInstanceMethodsAndFields(HasInjections.class,
sink);
assertEquals(ImmutableSet.of(
- new InjectionPoint(new TypeResolver(HasInjections.class),
instanceMethod),
- new InjectionPoint(new TypeResolver(HasInjections.class),
instanceField)),
+ new InjectionPoint(TypeLiteral.get(HasInjections.class),
instanceMethod),
+ new InjectionPoint(TypeLiteral.get(HasInjections.class),
instanceField)),
sink);
}
@@ -156,8 +155,8 @@
Set<InjectionPoint> sink = Sets.newHashSet();
InjectionPoint.addForStaticMethodsAndFields(HasInjections.class, sink);
assertEquals(ImmutableSet.of(
- new InjectionPoint(new TypeResolver(HasInjections.class),
staticMethod),
- new InjectionPoint(new TypeResolver(HasInjections.class),
staticField)),
+ new InjectionPoint(TypeLiteral.get(HasInjections.class),
staticMethod),
+ new InjectionPoint(TypeLiteral.get(HasInjections.class),
staticField)),
sink);
}
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"google-guice-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/google-guice-dev?hl=en
-~----------~----~----~----~------~----~------~--~---