diff options
Diffstat (limited to 'core/src/com/google/inject/internal/MoreTypes.java')
-rw-r--r-- | core/src/com/google/inject/internal/MoreTypes.java | 37 |
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; } /** |