Remove loophole for making non-canonical Keys. This makes the behaviour of Key.get(new TypeLiteral<T>() {}) and new Key<T>() {} the same.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=51109122
diff --git a/core/src/com/google/inject/Key.java b/core/src/com/google/inject/Key.java
index 7842c66..7ed5e20 100644
--- a/core/src/com/google/inject/Key.java
+++ b/core/src/com/google/inject/Key.java
@@ -72,7 +72,8 @@
@SuppressWarnings("unchecked")
protected Key(Class<? extends Annotation> annotationType) {
this.annotationStrategy = strategyFor(annotationType);
- this.typeLiteral = (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass());
+ this.typeLiteral = MoreTypes.canonicalizeForKey(
+ (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass()));
this.hashCode = computeHashCode();
}
@@ -92,7 +93,8 @@
protected Key(Annotation annotation) {
// no usages, not test-covered
this.annotationStrategy = strategyFor(annotation);
- this.typeLiteral = (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass());
+ this.typeLiteral = MoreTypes.canonicalizeForKey(
+ (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass()));
this.hashCode = computeHashCode();
}
@@ -110,7 +112,8 @@
@SuppressWarnings("unchecked")
protected Key() {
this.annotationStrategy = NullAnnotationStrategy.INSTANCE;
- this.typeLiteral = (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass());
+ this.typeLiteral = MoreTypes.canonicalizeForKey(
+ (TypeLiteral<T>) TypeLiteral.fromSuperclassTypeParameter(getClass()));
this.hashCode = computeHashCode();
}
diff --git a/core/test/com/google/inject/KeyTest.java b/core/test/com/google/inject/KeyTest.java
index 41603e2..c0401e0 100644
--- a/core/test/com/google/inject/KeyTest.java
+++ b/core/test/com/google/inject/KeyTest.java
@@ -106,7 +106,7 @@
assertEquals(wrappers[t], primitiveKey.getTypeLiteral().getType());
assertEquals(wrappers[t], wrapperKey.getTypeLiteral().getType());
}
-
+
Key<Integer> integerKey = Key.get(Integer.class);
Key<Integer> integerKey2 = Key.get(Integer.class, Named.class);
Key<Integer> integerKey3 = Key.get(Integer.class, Names.named("int"));
@@ -191,6 +191,35 @@
}
}
+ public void testCannotGetKeyWithUnspecifiedTypeVariables() {
+ TypeLiteral<Integer> typeLiteral = KeyTest.createTypeLiteral();
+ try {
+ Key.get(typeLiteral);
+ fail("Guice should not allow keys for T");
+ } catch (ConfigurationException e) {
+ assertContains(e.getMessage(),
+ "T cannot be used as a key; It is not fully specified.");
+ }
+ }
+
+ private static <T> TypeLiteral<T> createTypeLiteral() {
+ return new TypeLiteral<T>() {};
+ }
+
+ public void testCannotCreateKeySubclassesWithUnspecifiedTypeVariables() {
+ try {
+ KeyTest.<Integer>createKey();
+ fail("Guice should not allow keys for T");
+ } catch (ConfigurationException e) {
+ assertContains(e.getMessage(),
+ "T cannot be used as a key; It is not fully specified.");
+ }
+ }
+
+ private static <T> Key<T> createKey() {
+ return new Key<T>() {};
+ }
+
interface B {}
@Retention(RUNTIME)
@@ -203,27 +232,27 @@
class HasTypeParameters<A, B extends List<A> & Runnable, C extends Runnable> {
A a; B b; C c;
}
-
+
public void testKeysWithDefaultAnnotations() {
AllDefaults allDefaults = HasAnnotations.class.getAnnotation(AllDefaults.class);
assertEquals(Key.get(Foo.class, allDefaults), Key.get(Foo.class, AllDefaults.class));
-
- Marker marker = HasAnnotations.class.getAnnotation(Marker.class);
+
+ Marker marker = HasAnnotations.class.getAnnotation(Marker.class);
assertEquals(Key.get(Foo.class, marker), Key.get(Foo.class, Marker.class));
-
+
Key<?> noDefaults = Key.get(Foo.class, NoDefaults.class);
assertNull(noDefaults.getAnnotation());
assertEquals(NoDefaults.class, noDefaults.getAnnotationType());
-
+
Key<?> someDefaults = Key.get(Foo.class, SomeDefaults.class);
assertNull(someDefaults.getAnnotation());
- assertEquals(SomeDefaults.class, someDefaults.getAnnotationType());
+ assertEquals(SomeDefaults.class, someDefaults.getAnnotationType());
}
-
+
@Retention(RUNTIME)
@BindingAnnotation @interface AllDefaults {
int v1() default 1;
- String v2() default "foo";
+ String v2() default "foo";
}
@Retention(RUNTIME)
@@ -232,18 +261,18 @@
String v2() default "foo";
Class<?> clazz();
}
-
+
@Retention(RUNTIME)
@BindingAnnotation @interface NoDefaults {
int value();
}
-
+
@Retention(RUNTIME)
@BindingAnnotation @interface Marker {
}
-
+
@AllDefaults
@Marker
class HasAnnotations {}
-
+
}