aboutsummaryrefslogtreecommitdiff
path: root/core/src/com/google/inject/internal/MoreTypes.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/com/google/inject/internal/MoreTypes.java')
-rw-r--r--core/src/com/google/inject/internal/MoreTypes.java37
1 files changed, 34 insertions, 3 deletions
diff --git a/core/src/com/google/inject/internal/MoreTypes.java b/core/src/com/google/inject/internal/MoreTypes.java
index 12a76250..bdf6029a 100644
--- a/core/src/com/google/inject/internal/MoreTypes.java
+++ b/core/src/com/google/inject/internal/MoreTypes.java
@@ -23,6 +23,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;
import com.google.inject.ConfigurationException;
+import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Types;
@@ -64,6 +65,25 @@ public class MoreTypes {
.build();
/**
+ * Returns a key that doesn't hold any references to parent classes.
+ * This is necessary for anonymous keys, so ensure we don't hold a ref
+ * to the containing module (or class) forever.
+ */
+ public static <T> Key<T> canonicalizeKey(Key<T> key) {
+ // If we know this isn't a subclass, return as-is.
+ // Otherwise, recreate the key to avoid the subclass
+ if (key.getClass() == Key.class) {
+ return key;
+ } else if (key.getAnnotation() != null) {
+ return Key.get(key.getTypeLiteral(), key.getAnnotation());
+ } else if (key.getAnnotationType() != null) {
+ return Key.get(key.getTypeLiteral(), key.getAnnotationType());
+ } else {
+ return Key.get(key.getTypeLiteral());
+ }
+ }
+
+ /**
* Returns an type that's appropriate for use in a key.
*
* <p>If the raw type of {@code typeLiteral} is a {@code javax.inject.Provider}, this returns a
@@ -93,9 +113,20 @@ public class MoreTypes {
@SuppressWarnings("unchecked")
TypeLiteral<T> wrappedPrimitives = (TypeLiteral<T>) PRIMITIVE_TO_WRAPPER.get(typeLiteral);
- return wrappedPrimitives != null
- ? wrappedPrimitives
- : typeLiteral;
+ if (wrappedPrimitives != null) {
+ return wrappedPrimitives;
+ }
+
+ // If we know this isn't a subclass, return as-is.
+ if (typeLiteral.getClass() == TypeLiteral.class) {
+ return typeLiteral;
+ }
+
+ // recreate the TypeLiteral to avoid anonymous TypeLiterals from holding refs to their
+ // surrounding classes.
+ @SuppressWarnings("unchecked")
+ TypeLiteral<T> recreated = (TypeLiteral<T>) TypeLiteral.get(typeLiteral.getType());
+ return recreated;
}
/**