Fixes issue 1985. Moved all subtype tests into JClassType. Added a new superclass for JParameterizedType and JRawType to make the new subtype tests simpler.
Also implemented JWildcardType.getErasedType() since it was using JDelegatingClassType's version which was wrong.
Patch by: mmendez, rdayal, spoon
Review by: spoon, rdayal, mmendez
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1791 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JArrayType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JArrayType.java
index d1e1b9f..fd67a67 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JArrayType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JArrayType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -301,45 +301,6 @@
}
@Override
- public boolean isAssignableFrom(JClassType possibleSubtype) {
- if (this == possibleSubtype) {
- // type is assignable to itself
- return true;
- }
-
- JArrayType possibleSubtypeArray = possibleSubtype.isArray();
- if (possibleSubtypeArray == null) {
- // possible subtype must be an array to be assignable
- return false;
- }
-
- JType thisComponentType = getComponentType();
- JType otherComponentType = possibleSubtypeArray.getComponentType();
-
- if (thisComponentType.isPrimitive() != null
- || otherComponentType.isPrimitive() != null) {
- /*
- * Since this was not equal to the possible subtype, we know that either
- * the dimensions are off or the component types are off
- */
- return false;
- }
-
- assert (thisComponentType instanceof JClassType);
- assert (otherComponentType instanceof JClassType);
-
- JClassType thisComponentClassType = (JClassType) thisComponentType;
- JClassType otherComponentClassType = (JClassType) otherComponentType;
-
- return thisComponentClassType.isAssignableFrom(otherComponentClassType);
- }
-
- @Override
- public boolean isAssignableTo(JClassType possibleSupertype) {
- return possibleSupertype.isAssignableFrom(this);
- }
-
- @Override
public JClassType isClass() {
// intentional null
return null;
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java
index 1f67de2..be49e4e 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JClassType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -23,7 +23,7 @@
import java.util.Set;
/**
- * Type representing a Java class or interface type.
+ * Type used to represent any non-primitive type.
*/
public abstract class JClassType extends JType implements HasAnnotations,
HasMetaData {
@@ -40,17 +40,268 @@
}
/**
- * Returns the {@link JGenericType} base type if the otherType is raw or
- * parameterized type.
+ * Returns <code>true</code> if the rhs array type can be assigned to the
+ * lhs array type.
*/
- protected static JClassType maybeGetGenericBaseType(JClassType otherType) {
- if (otherType.isParameterized() != null) {
- return otherType.isParameterized().getBaseType();
- } else if (otherType.isRawType() != null) {
- return otherType.isRawType().getGenericType();
+ private static boolean areArraysAssignable(JArrayType lhsType,
+ JArrayType rhsType) {
+ // areClassTypesAssignable should prevent us from getting here if the types
+ // are referentially equal.
+ assert (lhsType != rhsType);
+
+ JType lhsComponentType = lhsType.getComponentType();
+ JType rhsComponentType = rhsType.getComponentType();
+
+ if (lhsComponentType.isPrimitive() != null
+ || rhsComponentType.isPrimitive() != null) {
+ /*
+ * Arrays are referentially stable so there will only be one int[] no
+ * matter how many times it is referenced in the code. So, if either
+ * component type is a primitive then we know that we are not assignable.
+ */
+ return false;
}
-
- return otherType;
+
+ assert (lhsComponentType instanceof JClassType);
+ assert (rhsComponentType instanceof JClassType);
+
+ JClassType thisComponentClass = (JClassType) lhsComponentType;
+ JClassType subtypeComponentClass = (JClassType) rhsComponentType;
+
+ return areClassTypesAssignable(thisComponentClass, subtypeComponentClass);
+ }
+
+ /**
+ * Returns <code>true</code> if the rhsType can be assigned to the lhsType.
+ */
+ private static boolean areClassTypesAssignable(JClassType lhsType,
+ JClassType rhsType) {
+ // The supertypes of rhs will include rhs.
+ Set<JClassType> rhsSupertypes = getFlattenedSuperTypeHierarchy(rhsType);
+ for (JClassType rhsSupertype : rhsSupertypes) {
+ if (areClassTypesAssignableNoSupers(lhsType, rhsSupertype)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns <code>true</code> if the lhs and rhs are assignable without
+ * consideration of the supertypes of the rhs.
+ *
+ * @param lhsType
+ * @param rhsType
+ * @return
+ */
+ private static boolean areClassTypesAssignableNoSupers(JClassType lhsType,
+ JClassType rhsType) {
+ if (lhsType == rhsType) {
+ // Done, these are the same types.
+ return true;
+ }
+
+ if (lhsType == lhsType.getOracle().getJavaLangObject()) {
+ // Done, any type can be assigned to object.
+ return true;
+ }
+
+ /*
+ * Get the generic base type, if there is one, for the lhs type and convert
+ * it to a raw type if it is generic.
+ */
+ if (lhsType.isGenericType() != null) {
+ lhsType = lhsType.isGenericType().getRawType();
+ }
+
+ if (rhsType.isGenericType() != null) {
+ // Treat the generic rhs type as a raw type.
+ rhsType = rhsType.isGenericType().getRawType();
+ }
+
+ // Check for JTypeParameters.
+ JTypeParameter lhsTypeParam = lhsType.isTypeParameter();
+ JTypeParameter rhsTypeParam = rhsType.isTypeParameter();
+ if (lhsTypeParam != null) {
+ JBound bounds = lhsTypeParam.getBounds();
+ JClassType[] lhsTypeBounds = bounds.getBounds();
+ for (JClassType lhsTypeBound : lhsTypeBounds) {
+ if (!areClassTypesAssignable(lhsTypeBound, rhsType)) {
+ // Done, the rhsType was not assignable to one of the bounds.
+ return false;
+ }
+ }
+
+ // Done, the rhsType was assignable to all of the bounds.
+ return true;
+ } else if (rhsTypeParam != null) {
+ JClassType[] possibleSubtypeBounds = rhsTypeParam.getBounds().getBounds();
+ for (JClassType possibleSubtypeBound : possibleSubtypeBounds) {
+ if (areClassTypesAssignable(lhsType, possibleSubtypeBound)) {
+ // Done, at least one bound is assignable to this type.
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /*
+ * Check for JWildcards. We have not examined this part in great detail
+ * since there should not be top level wildcard types.
+ */
+ JWildcardType lhsWildcard = lhsType.isWildcard();
+ JWildcardType rhsWildcard = rhsType.isWildcard();
+ if (lhsWildcard != null && rhsWildcard != null) {
+ // Both types are wildcards.
+ return areWildcardsAssignable(lhsWildcard, rhsWildcard);
+ } else if (lhsWildcard != null) {
+ // The lhs type is a wildcard but the rhs is not.
+ // ? extends T, U OR ? super T, U
+ JBound lhsBound = lhsWildcard.getBounds();
+ if (lhsBound.isUpperBound() != null) {
+ return areClassTypesAssignable(lhsBound.getFirstBound(), rhsType);
+ } else {
+ // ? super T will reach object no matter what the rhs type is
+ return true;
+ }
+ }
+
+ // Check for JArrayTypes.
+ JArrayType lhsArray = lhsType.isArray();
+ JArrayType rhsArray = rhsType.isArray();
+ if (lhsArray != null) {
+ if (rhsArray == null) {
+ return false;
+ } else {
+ return areArraysAssignable(lhsArray, rhsArray);
+ }
+ } else if (rhsArray != null) {
+ // Safe although perhaps not necessary
+ return false;
+ }
+
+ // Check for JParameterizedTypes and JRawTypes.
+ JMaybeParameterizedType lhsMaybeParameterized = lhsType.isMaybeParameterizedType();
+ JMaybeParameterizedType rhsMaybeParameterized = rhsType.isMaybeParameterizedType();
+ if (lhsMaybeParameterized != null && rhsMaybeParameterized != null) {
+ if (lhsMaybeParameterized.getBaseType() == rhsMaybeParameterized.getBaseType()) {
+ if (lhsMaybeParameterized.isRawType() != null
+ || rhsMaybeParameterized.isRawType() != null) {
+ /*
+ * Any raw type can be assigned to or from any parameterization of its
+ * generic type.
+ */
+ return true;
+ }
+
+ assert (lhsMaybeParameterized.isRawType() == null &&
+ rhsMaybeParameterized.isRawType() == null);
+ JParameterizedType lhsParameterized = lhsMaybeParameterized.isParameterized();
+ JParameterizedType rhsParameterized = rhsMaybeParameterized.isParameterized();
+ assert (lhsParameterized != null && rhsParameterized != null);
+
+ return areTypeArgumentsAssignable(lhsParameterized,
+ rhsParameterized);
+ }
+ }
+
+ // Default to not being assignable.
+ return false;
+ }
+
+ /**
+ * Returns <code>true</code> if the type arguments of the rhs parameterized
+ * type are assignable to the type arguments of the lhs parameterized type.
+ */
+ private static boolean areTypeArgumentsAssignable(JParameterizedType lhsType,
+ JParameterizedType rhsType) {
+ // areClassTypesAssignable should prevent us from getting here if the types
+ // are referentially equal.
+ assert (lhsType != rhsType);
+ assert (lhsType.getBaseType() == rhsType.getBaseType());
+
+ JClassType[] lhsTypeArgs = lhsType.getTypeArgs();
+ JClassType[] rhsTypeArgs = rhsType.getTypeArgs();
+ JGenericType lhsBaseType = lhsType.getBaseType();
+
+ // Compare at least as many formal type parameters as are declared on the
+ // generic base type. gwt.typeArgs could cause more types to be included.
+
+ JTypeParameter[] lhsTypeParams = lhsBaseType.getTypeParameters();
+ for (int i = 0; i < lhsTypeParams.length; ++i) {
+ if (!doesTypeArgumentContain(lhsTypeArgs[i], rhsTypeArgs[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns <code>true</code> if the rhsWildcard can be assigned to the
+ * lhsWildcard. This method does not consider supertypes of either
+ * lhs or rhs.
+ */
+ private static boolean areWildcardsAssignable(JWildcardType lhsWildcard,
+ JWildcardType rhsWildcard) {
+ // areClassTypesAssignable should prevent us from getting here if the types
+ // are referentially equal.
+ assert (lhsWildcard != rhsWildcard);
+ assert (lhsWildcard != null && rhsWildcard != null);
+
+ JBound lhsBound = lhsWildcard.getBounds();
+ JBound rhsBound = rhsWildcard.getBounds();
+
+ if (lhsBound.isUpperBound() != null && rhsBound.isUpperBound() != null) {
+ // lhsType: ? extends T, rhsType: ? extends U
+ return areClassTypesAssignable(lhsBound.getFirstBound(),
+ rhsBound.getFirstBound());
+ } else if (lhsBound.isLowerBound() != null
+ && rhsBound.isLowerBound() != null) {
+ // lhsType: ? super T, rhsType ? super U
+ return areClassTypesAssignable(rhsBound.getFirstBound(),
+ lhsBound.getFirstBound());
+ }
+
+ return false;
+ }
+
+ /**
+ * A restricted version of areClassTypesAssignable that is used for comparing
+ * the type arguments of parameterized types, where the lhsTypeArg is the
+ * container.
+ */
+ private static boolean doesTypeArgumentContain(JClassType lhsTypeArg,
+ JClassType rhsTypeArg) {
+ if (lhsTypeArg == rhsTypeArg) {
+ return true;
+ }
+
+ // Check for wildcard types
+ JWildcardType lhsWildcard = lhsTypeArg.isWildcard();
+ JWildcardType rhsWildcard = rhsTypeArg.isWildcard();
+
+ if (lhsWildcard != null) {
+ if (rhsWildcard != null) {
+ return areWildcardsAssignable(lhsWildcard, rhsWildcard);
+ } else {
+ // LHS is a wildcard but the RHS is not.
+ JBound lhsBound = lhsWildcard.getBounds();
+ if (lhsBound.isLowerBound() == null) {
+ return areClassTypesAssignable(lhsBound.getFirstBound(), rhsTypeArg);
+ } else {
+ return areClassTypesAssignable(rhsTypeArg, lhsBound.getFirstBound());
+ }
+ }
+ }
+
+ /*
+ * At this point the arguments are not the same and they are not wildcards
+ * so, they cannot be assignable, Eh.
+ */
+ return false;
}
private static void getFlattenedSuperTypeHierarchyRecursive(JClassType type,
@@ -72,7 +323,7 @@
getFlattenedSuperTypeHierarchyRecursive(intf, typesSeen);
}
}
-
+
public abstract void addImplementedInterface(JClassType intf);
public abstract void addMetaData(String tagName, String[] values);
@@ -171,9 +422,13 @@
public abstract boolean isAnnotationPresent(
Class<? extends Annotation> annotationClass);
- public abstract boolean isAssignableFrom(JClassType possibleSubtype);
+ public boolean isAssignableFrom(JClassType possibleSubtype) {
+ return areClassTypesAssignable(this, possibleSubtype);
+ }
- public abstract boolean isAssignableTo(JClassType possibleSupertype);
+ public boolean isAssignableTo(JClassType possibleSupertype) {
+ return areClassTypesAssignable(possibleSupertype, this);
+ }
/**
* Determines if the class can be constructed using a simple <code>new</code>
@@ -243,6 +498,10 @@
protected abstract void getOverridableMethodsOnSuperinterfacesAndMaybeThisInterface(
Map<String, JMethod> methodsBySignature);
+ protected JMaybeParameterizedType isMaybeParameterizedType() {
+ return null;
+ }
+
protected final String makeCompoundName(JClassType type) {
if (type.getEnclosingType() == null) {
return type.getSimpleSourceName();
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JDelegatingClassType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JDelegatingClassType.java
index e421658..62ab6cd 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JDelegatingClassType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JDelegatingClassType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -253,16 +253,6 @@
}
@Override
- public boolean isAssignableFrom(JClassType possibleSubtype) {
- return baseType.isAssignableFrom(possibleSubtype);
- }
-
- @Override
- public boolean isAssignableTo(JClassType possibleSupertype) {
- return baseType.isAssignableTo(possibleSupertype);
- }
-
- @Override
public JClassType isClass() {
if (baseType.isClass() != null) {
return this;
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JGenericType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JGenericType.java
index 50441dc..1297351 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JGenericType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JGenericType.java
@@ -17,33 +17,11 @@
import java.util.ArrayList;
import java.util.List;
-import java.util.Set;
/**
- *
+ * Type declaration that has type parameters.
*/
public class JGenericType extends JRealClassType implements HasTypeParameters {
- /**
- * Returns <code>true</code> if lhsType is assignable to rhsType.
- */
- private static boolean isAssignable(JClassType lhsType, JClassType rhsType) {
- if (lhsType == rhsType) {
- return true;
- }
-
- Set<JClassType> supertypes = getFlattenedSuperTypeHierarchy(rhsType);
- for (JClassType supertype : supertypes) {
- if (supertype.isParameterized() == null) {
- continue;
- }
-
- if (supertype.isParameterized().getBaseType() == lhsType) {
- return true;
- }
- }
-
- return false;
- }
private JRawType lazyRawType = null;
@@ -107,20 +85,6 @@
}
@Override
- public boolean isAssignableFrom(JClassType otherType) {
- otherType = maybeGetGenericBaseType(otherType);
-
- return isAssignable(this, otherType);
- }
-
- @Override
- public boolean isAssignableTo(JClassType otherType) {
- otherType = maybeGetGenericBaseType(otherType);
-
- return isAssignable(otherType, this);
- }
-
- @Override
public JGenericType isGenericType() {
return this;
}
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JMaybeParameterizedType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JMaybeParameterizedType.java
new file mode 100644
index 0000000..ee130ef
--- /dev/null
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JMaybeParameterizedType.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.core.ext.typeinfo;
+
+/**
+ * Super class for parameterized types or raw types.
+ */
+abstract class JMaybeParameterizedType extends JDelegatingClassType {
+
+ public JMaybeParameterizedType() {
+ super();
+ }
+
+ @Override
+ public JGenericType getBaseType() {
+ JGenericType genericType = super.getBaseType().isGenericType();
+ assert (genericType != null);
+ return genericType;
+ }
+
+ @Override
+ protected JMaybeParameterizedType isMaybeParameterizedType() {
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameterizedType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameterizedType.java
index 3c27edf..ec7ae54 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameterizedType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameterizedType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -25,41 +25,7 @@
/**
* Represents a parameterized type in a declaration.
*/
-public class JParameterizedType extends JDelegatingClassType {
- private static boolean areTypeArgsAssignableFrom(JClassType[] myTypeArgs,
- JClassType[] otherTypeArgs) {
- assert (myTypeArgs.length <= otherTypeArgs.length);
-
- for (int i = 0; i < myTypeArgs.length; ++i) {
- JClassType myTypeArg = myTypeArgs[i];
- JClassType otherTypeArg = otherTypeArgs[i];
-
- if (myTypeArg.isTypeParameter() != null) {
- /*
- * If my type argument is a type parameter consider it's erased form. This
- * avoids recursion sickness in the case where my type argument is of the
- * form:
- *
- * T extends Serializable & Comparable<T>
- *
- * and otherTypeArg is something like Long, Short, etc.
- */
- return myTypeArg.getErasedType().isAssignableFrom(otherTypeArg);
- }
-
- if (myTypeArg.isWildcard() == null) {
- // myTypeArg needs to be a wildcard or we cannot be assignable.
- return false;
- }
-
- if (!myTypeArg.isAssignableFrom(otherTypeArg)) {
- return false;
- }
- }
-
- return true;
- }
-
+public class JParameterizedType extends JMaybeParameterizedType {
/**
* Create a parameterized type along with any necessary enclosing
* parameterized types. Enclosing parameterized types are necessary when the
@@ -99,77 +65,6 @@
return parameterizedType;
}
- /**
- * Returns <code>true</code> if the rhsType can be assigned to the lhsType.
- */
- private static boolean isAssignable(JClassType lhsType, JClassType rhsType) {
- if (lhsType == rhsType) {
- return true;
- }
-
- Set<JClassType> rhsSupertypes = getFlattenedSuperTypeHierarchy(rhsType);
- if (rhsSupertypes.contains(lhsType)) {
- // Done, appears explicitly in the supertype hierarchy.
- return true;
- }
-
- /*
- * Get the generic base type for the lhsType if there is one.
- */
- JGenericType lhsBaseType = null;
- if (lhsType.isParameterized() != null) {
- lhsBaseType = lhsType.isParameterized().getBaseType();
- } else if (lhsType.isRawType() != null) {
- lhsBaseType = lhsType.isRawType().getBaseType();
- }
-
- /*
- * Check the supertype hierarchy to see if we can find a parameterization
- * or a raw type that would satisfy the assignment.
- */
- for (JClassType rhsSupertype : rhsSupertypes) {
- if (rhsSupertype.isGenericType() != null) {
- /*
- * A generic type will be treated as its raw type for assignment
- * purposes.
- */
- rhsSupertype = rhsSupertype.isGenericType().getRawType();
- }
-
- JParameterizedType rhsParameterized = rhsSupertype.isParameterized();
- if (rhsParameterized != null) {
- if (rhsParameterized.getBaseType() == lhsBaseType) {
- /*
- * This supertype and the lhsType have the same base type, but they
- * have different parameterizations so we test them.
- */
- assert (rhsParameterized != lhsType);
-
- if (lhsType.isRawType() != null) {
- // The lhsType is raw so we do not need to check the parameterization.
- return true;
- } else {
- assert (lhsType.isParameterized() != null);
-
- return areTypeArgsAssignableFrom(
- lhsType.isParameterized().getTypeArgs(),
- rhsParameterized.getTypeArgs());
- }
- }
- } else if (rhsSupertype.isRawType() != null) {
- if (rhsSupertype.isRawType().getBaseType() == lhsBaseType) {
- /*
- * The raw supertype has the same base type as the lhsType so the
- * assignment is okay.
- */
- return true;
- }
- }
- }
-
- return false;
- }
-
private final JClassType enclosingType;
private List<JClassType> interfaces;
@@ -229,11 +124,6 @@
}
@Override
- public JGenericType getBaseType() {
- return (JGenericType) super.getBaseType();
- }
-
- @Override
public JConstructor getConstructor(JType[] paramTypes)
throws NotFoundException {
return members.getConstructor(paramTypes);
@@ -424,16 +314,6 @@
}
@Override
- public boolean isAssignableFrom(JClassType otherType) {
- return isAssignable(this, otherType);
- }
-
- @Override
- public boolean isAssignableTo(JClassType otherType) {
- return isAssignable(otherType, this);
- }
-
- @Override
public JGenericType isGenericType() {
return null;
}
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JRawType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JRawType.java
index 63ba139..b7a6017 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JRawType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JRawType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -21,7 +21,7 @@
/**
* Represents a raw type; that is a generic type with no type arguments.
*/
-public class JRawType extends JDelegatingClassType {
+public class JRawType extends JMaybeParameterizedType {
private static final Substitution ERASURE_SUBSTITUTION = new Substitution() {
public JType getSubstitution(JType type) {
return type.getErasedType();
@@ -64,13 +64,6 @@
}
@Override
- public JGenericType getBaseType() {
- JGenericType genericType = super.getBaseType().isGenericType();
- assert (genericType != null);
- return genericType;
- }
-
- @Override
public JConstructor getConstructor(JType[] paramTypes)
throws NotFoundException {
return members.getConstructor(paramTypes);
@@ -181,20 +174,6 @@
}
@Override
- public boolean isAssignableFrom(JClassType otherType) {
- otherType = maybeGetGenericBaseType(otherType);
-
- return getBaseType().isAssignableFrom(otherType);
- }
-
- @Override
- public boolean isAssignableTo(JClassType otherType) {
- otherType = maybeGetGenericBaseType(otherType);
-
- return getBaseType().isAssignableTo(otherType);
- }
-
- @Override
public JGenericType isGenericType() {
return null;
}
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
index 2411d2c..78a0779 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -27,7 +27,7 @@
import java.util.Set;
/**
- * Type representing a Java class or interface type.
+ * Type representing a Java class or interface type that a user would declare.
*/
public class JRealClassType extends JClassType {
@@ -325,51 +325,6 @@
}
@Override
- public boolean isAssignableFrom(JClassType otherType) {
- if (otherType == this) {
- return true;
- }
-
- if (allSubtypes.contains(otherType)) {
- // JGenericTypes should appear in the allSubtypes hierarchy - do nothing
- return true;
- } else if (this == getOracle().getJavaLangObject()) {
- // This case handles the odd "every interface is an Object"
- // but doesn't actually have Object as a superclass.
- //
- return true;
- } else {
- if (otherType.isTypeParameter() != null) {
- return otherType.isAssignableTo(this);
- }
-
- if (otherType.isWildcard() != null) {
- return otherType.isAssignableTo(this);
- }
-
- if (otherType.isGenericType() != null) {
- return otherType.isAssignableTo(this);
- }
-
- if (otherType.isRawType() != null) {
- return otherType.isAssignableTo(this);
- }
-
- if (otherType.isParameterized() != null) {
- return otherType.isAssignableTo(this);
- }
-
- // At this point we should only have JArrayTypes or JRealClassTypes from
- // which we are not assignable.
- return false;
- }
- }
-
- public boolean isAssignableTo(JClassType possibleSupertype) {
- return possibleSupertype.isAssignableFrom(this);
- }
-
- @Override
public JClassType isClass() {
return isInterface ? null : this;
}
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JTypeParameter.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JTypeParameter.java
index 4262c0e..874e4c4 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JTypeParameter.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JTypeParameter.java
@@ -118,24 +118,6 @@
}
@Override
- public boolean isAssignableFrom(JClassType otherType) {
- if (otherType == this) {
- return true;
- }
-
- return getBounds().isAssignableFrom(otherType);
- }
-
- @Override
- public boolean isAssignableTo(JClassType otherType) {
- if (otherType == this) {
- return true;
- }
-
- return getBounds().isAssignableTo(otherType);
- }
-
- @Override
public JGenericType isGenericType() {
return null;
}
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JWildcardType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JWildcardType.java
index 20b8e53..a6d18dc 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JWildcardType.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JWildcardType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -41,6 +41,17 @@
}
@Override
+ public JClassType getErasedType() {
+ if (bounds.isLowerBound() != null) {
+ // ? super T erases to Object
+ return getOracle().getJavaLangObject();
+ }
+
+ // ? extends T erases to T
+ return getFirstBound();
+ }
+
+ @Override
public JField getField(String name) {
return getBaseType().getField(name);
}
@@ -74,30 +85,27 @@
public String getSimpleSourceName() {
return "?" + bounds.getSimpleSourceName();
}
-
+
@Override
public JClassType[] getSubtypes() {
+ // We are not sure what the correct behavior should be for lower bound
+ // wildcards. ? super Number contains ? super T for all T extends Number,
+ // but it also includes T for Number extends T. For example, Object is a
+ // subtype.
return bounds.getSubtypes();
}
-
+
@Override
- public boolean isAssignableFrom(JClassType otherType) {
- if (otherType == this) {
- return true;
+ public JClassType getSuperclass() {
+ if (bounds.isLowerBound() != null) {
+ // The only safe superclass for a ? super T is Object.
+ return getOracle().getJavaLangObject();
}
- return getBounds().isAssignableFrom(otherType);
+ // The superclass of an upper bound is the upper bound.
+ return getFirstBound();
}
-
- @Override
- public boolean isAssignableTo(JClassType otherType) {
- if (otherType == this) {
- return true;
- }
-
- return getBounds().isAssignableTo(otherType);
- }
-
+
@Override
public JGenericType isGenericType() {
return null;
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/JGenericTypeTest.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/JGenericTypeTest.java
index 5a443f1..d3e9ef3 100644
--- a/dev/core/test/com/google/gwt/core/ext/typeinfo/JGenericTypeTest.java
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/JGenericTypeTest.java
@@ -184,9 +184,54 @@
JClassType[] bounds = bound.getBounds();
assertEquals(1, bounds.length);
- assertEquals(moduleContext.getOracle().getJavaLangObject(), bounds[0]);
+ assertEquals(moduleContext.getOracle().getType(Serializable.class.getName()),
+ bounds[0]);
+ }
+
+ /**
+ * Test method for {@link
+ * com.google.gwt.core.ext.typeinfo.JGenericType#isAssignableFrom(JClassType)}.
+ *
+ * @throws NotFoundException
+ */
+ public void testIsAssignableFrom() throws NotFoundException {
+ JGenericType genericType = getTestType();
+
+ // Check that the generic type's superclass is assignable from the generic type
+ assertTrue(genericType.getSuperclass().isAssignableFrom(genericType));
+
+ // Check that each implemented interface is assignable from the generic type
+ JClassType[] implementedInterfaces = genericType.getImplementedInterfaces();
+ for (JClassType implementedInterface : implementedInterfaces) {
+ assertTrue(implementedInterface.isAssignableFrom(genericType));
+ assertTrue(implementedInterface.isAssignableFrom(genericType.getRawType()));
+ }
+ }
+
+ /**
+ * Test method for {@link
+ * com.google.gwt.core.ext.typeinfo.JGenericType#isAssignableTo(JClassType)}.
+ *
+ * @throws NotFoundException
+ */
+ public void testIsAssignableTo() throws NotFoundException {
+ JGenericType genericType = getTestType();
+
+ // Check that generic type is assignable to its superclass
+ assertTrue(genericType.isAssignableTo(genericType.getSuperclass()));
+
+ // Check that the generic class is assignable to any implemented interface
+ JClassType[] implementedInterfaces = genericType.getImplementedInterfaces();
+ for (JClassType implementedInterface : implementedInterfaces) {
+ assertTrue(genericType.isAssignableTo(implementedInterface));
+
+ if (implementedInterface.isParameterized() != null) {
+ assertTrue(genericType.isAssignableTo(implementedInterface.isParameterized().getRawType()));
+ }
+ }
}
+
/**
* Returns the generic version of {@link GenericClass}.
*/
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/JParameterizedTypeTest.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/JParameterizedTypeTest.java
index ca91c61..0b23f6b 100644
--- a/dev/core/test/com/google/gwt/core/ext/typeinfo/JParameterizedTypeTest.java
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/JParameterizedTypeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -19,6 +19,7 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.test.Base;
import com.google.gwt.core.ext.typeinfo.test.Derived;
+import com.google.gwt.core.ext.typeinfo.test.ExtendsRawGenericClass;
import com.google.gwt.core.ext.typeinfo.test.GenericClass;
import com.google.gwt.core.ext.typeinfo.test.MyCustomList;
import com.google.gwt.core.ext.typeinfo.test.MyIntegerList;
@@ -32,6 +33,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.Vector;
/**
* Test for {@link JParameterizedType}.
@@ -228,33 +230,43 @@
TypeOracle oracle = moduleContext.getOracle();
JGenericType genericList = (JGenericType) oracle.getType(List.class.getName());
+ // ?
JWildcardType unboundWildcard = oracle.getWildcardType(new JUpperBound(
oracle.getJavaLangObject()));
+
+ // ? extends Number
JWildcardType numUpperBoundWildcard = oracle.getWildcardType(new JUpperBound(
oracle.getType(Number.class.getName())));
- // List<?> should be assignable from List<? extends Number>
+ // List<?>
JParameterizedType unboundList = oracle.getParameterizedType(genericList,
new JClassType[] {unboundWildcard});
- JParameterizedType numUpperBoundList = oracle.getParameterizedType(
+
+ // List<? extends Number>
+ JParameterizedType listOfExtendsNumber = oracle.getParameterizedType(
genericList, new JClassType[] {numUpperBoundWildcard});
- assertTrue(unboundList.isAssignableFrom(numUpperBoundList));
- assertFalse(unboundList.isAssignableTo(numUpperBoundList));
+
+ // List<?> should be assignable from List<? extends Number>
+ assertTrue(unboundList.isAssignableFrom(listOfExtendsNumber));
+ assertFalse(unboundList.isAssignableTo(listOfExtendsNumber));
- assertFalse(numUpperBoundList.isAssignableFrom(unboundList));
- assertTrue(numUpperBoundList.isAssignableTo(unboundList));
+ assertFalse(listOfExtendsNumber.isAssignableFrom(unboundList));
+ assertTrue(listOfExtendsNumber.isAssignableTo(unboundList));
- // List<? extends Number> should be assignable from List<? extends Integer>
+ // ? extends Integer
JWildcardType intUpperBoundWildcard = oracle.getWildcardType(new JUpperBound(
integerType));
- JParameterizedType intUpperBoundList = oracle.getParameterizedType(
+ // List<? extends Integer>
+ JParameterizedType listOfExtendsInteger = oracle.getParameterizedType(
genericList, new JClassType[] {intUpperBoundWildcard});
- assertTrue(numUpperBoundList.isAssignableFrom(intUpperBoundList));
- assertFalse(numUpperBoundList.isAssignableTo(intUpperBoundList));
- assertFalse(intUpperBoundList.isAssignableFrom(numUpperBoundList));
- assertTrue(intUpperBoundList.isAssignableTo(numUpperBoundList));
+ // List<? extends Number> should be assignable from List<? extends Integer>
+ assertTrue(listOfExtendsNumber.isAssignableFrom(listOfExtendsInteger));
+ assertFalse(listOfExtendsNumber.isAssignableTo(listOfExtendsInteger));
+
+ assertFalse(listOfExtendsInteger.isAssignableFrom(listOfExtendsNumber));
+ assertTrue(listOfExtendsInteger.isAssignableTo(listOfExtendsNumber));
// List<? super Integer> should be assignable from List<? super Number>
JWildcardType numLowerBoundWildcard = oracle.getWildcardType(new JLowerBound(
@@ -262,15 +274,83 @@
JWildcardType intLowerBoundWildcard = oracle.getWildcardType(new JLowerBound(
integerType));
- JParameterizedType numLowerBoundList = oracle.getParameterizedType(
+ // List<? super Number>
+ JParameterizedType listOfSuperNumber = oracle.getParameterizedType(
genericList, new JClassType[] {numLowerBoundWildcard});
- JParameterizedType intLowerBoundList = oracle.getParameterizedType(
+
+ // List<? super Interger>
+ JParameterizedType listOfSuperInteger = oracle.getParameterizedType(
genericList, new JClassType[] {intLowerBoundWildcard});
- assertTrue(intLowerBoundList.isAssignableFrom(numLowerBoundList));
- assertFalse(intLowerBoundList.isAssignableTo(numLowerBoundList));
- assertFalse(numLowerBoundList.isAssignableFrom(intLowerBoundList));
- assertTrue(numLowerBoundList.isAssignableTo(intLowerBoundList));
+ assertTrue(listOfSuperInteger.isAssignableFrom(listOfSuperNumber));
+ assertFalse(listOfSuperInteger.isAssignableTo(listOfSuperNumber));
+ assertFalse(listOfSuperNumber.isAssignableFrom(listOfSuperInteger));
+ assertTrue(listOfSuperNumber.isAssignableTo(listOfSuperInteger));
+
+ JParameterizedType listOfObject = oracle.getParameterizedType(genericList,
+ new JClassType[] {oracle.getJavaLangObject()});
+
+ JClassType stringType = oracle.getType(String.class.getName());
+ JParameterizedType listOfString = oracle.getParameterizedType(genericList,
+ new JClassType[] {stringType});
+
+ // List<Object> is not assignable from List<String>
+ assertFalse(listOfObject.isAssignableFrom(listOfString));
+
+ // List<String> is not assignable from List<Object>
+ assertFalse(listOfString.isAssignableFrom(listOfObject));
+
+ // List<List<String>> is not assignable from List<Vector<String>>
+ JParameterizedType listOfListOfString = oracle.getParameterizedType(
+ genericList, new JClassType[] {listOfString});
+
+ JGenericType genericVector = oracle.getType(Vector.class.getName()).isGenericType();
+ JParameterizedType vectorOfString = oracle.getParameterizedType(genericVector, new JClassType[] {stringType});
+ JParameterizedType listOfVectorOfString = oracle.getParameterizedType(genericList, new JClassType[] {vectorOfString});
+
+ assertFalse(listOfListOfString.isAssignableFrom(listOfVectorOfString));
+ assertFalse(listOfVectorOfString.isAssignableFrom(listOfListOfString));
+
+ // List<List> is not assignable from List<List<String>>
+ JClassType listOfRawList = oracle.getParameterizedType(genericList, new JClassType[] {genericList.getRawType()});
+ assertFalse(listOfRawList.isAssignableFrom(listOfListOfString));
+ assertFalse(listOfListOfString.isAssignableFrom(listOfRawList));
+
+ JGenericType genericClass = oracle.getType(GenericClass.class.getName()).isGenericType();
+ JParameterizedType parameterizedGenericClass = oracle.getParameterizedType(genericClass, new JClassType[] {stringType});
+ JClassType extendsRawGenericClass = oracle.getType(ExtendsRawGenericClass.class.getName());
+
+ // GenericClass<String> is assignable from ExtendsRawGenericClass
+ assertTrue(parameterizedGenericClass.isAssignableFrom(extendsRawGenericClass));
+
+ // ExtendsRawGenericClass is not assignable from GenericClass<String>
+ assertFalse(extendsRawGenericClass.isAssignableFrom(parameterizedGenericClass));
+
+ // List<List<? extends Number>>
+ JClassType listOfListOfExtendsNumber = oracle.getParameterizedType(genericList, new JClassType[] {listOfExtendsNumber});
+
+ // List<List<? extends Integer>>
+ JClassType listOfListOfExtendsInteger = oracle.getParameterizedType(genericList, new JClassType[] {listOfExtendsInteger});
+
+ assertFalse(listOfListOfExtendsNumber.isAssignableFrom(listOfListOfExtendsInteger));
+
+ // List<Integer>
+ JClassType listOfInteger = oracle.getParameterizedType(genericList, new JClassType[] {integerType});
+
+ // List<? extends Number> is assignable from List<Integer>
+ assertTrue(listOfExtendsNumber.isAssignableFrom(listOfInteger));
+ assertFalse(listOfExtendsNumber.isAssignableFrom(listOfObject));
+
+ // List<? super Number> is not assignable from List<Integer>
+ assertFalse(listOfSuperNumber.isAssignableFrom(listOfInteger));
+
+ // List<? super Number> is assignable from List<Object>
+ assertTrue(listOfSuperNumber.isAssignableFrom(listOfObject));
+ }
+
+ @Override
+ public void testIsAssignableTo() throws NotFoundException {
+ // This is covered as part of testIsAssignableFrom
}
public void testOverridableMethods_Base() throws NotFoundException {
@@ -396,9 +476,4 @@
assertTrue(expectedMethods.isEmpty());
}
-
- @Override
- public void testIsAssignableTo() throws NotFoundException {
- // This is covered as part of testIsAssignableFrom
- }
}
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/JTypeParameterTest.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/JTypeParameterTest.java
index 9066707..55d4724 100644
--- a/dev/core/test/com/google/gwt/core/ext/typeinfo/JTypeParameterTest.java
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/JTypeParameterTest.java
@@ -23,11 +23,25 @@
import java.io.Serializable;
import java.util.Arrays;
+import java.util.Set;
/**
* Tests for {@link JTypeParameter}.
*/
public class JTypeParameterTest extends JDelegatingClassTypeTestBase {
+ private static JClassType findParameterizationOf(JClassType classType,
+ JGenericType genericType) {
+ Set<JClassType> supertypes = JClassType.getFlattenedSuperTypeHierarchy(classType);
+ for (JClassType supertype : supertypes) {
+ JMaybeParameterizedType maybeParameterizedType = supertype.isMaybeParameterizedType();
+ if (maybeParameterizedType != null && maybeParameterizedType.getBaseType() == genericType) {
+ return supertype;
+ }
+ }
+
+ return null;
+ }
+
private final boolean logToConsole = false;
private final ModuleContext moduleContext = new ModuleContext(logToConsole
? new PrintWriterTreeLogger() : TreeLogger.NULL,
@@ -80,13 +94,13 @@
}
/*
- * Checks that all non-local subtypes of the type parameter,
- * T extends Serializable & Comparable<T> are actually assignable to
- * Serializable and the properly parameterized version of Comparable<T>.
+ * Checks that all non-local subtypes of the type parameter, T extends
+ * Serializable & Comparable<T> are actually assignable to Serializable and
+ * the properly parameterized version of Comparable<T>.
*/
@Override
public void testGetSubtypes() throws NotFoundException {
-
+
TypeOracle oracle = moduleContext.getOracle();
JClassType testType = oracle.getType(MyCustomList.class.getName());
JGenericType genericType = testType.isGenericType();
@@ -96,29 +110,48 @@
JClassType serializableType = oracle.getType(Serializable.class.getCanonicalName());
JGenericType comparableType = (JGenericType) oracle.getType(Comparable.class.getCanonicalName());
JClassType[] computedSubtypes = typeParameter.getSubtypes();
-
+
for (JClassType computedSubtype : computedSubtypes) {
- JParameterizedType parameterizedComparableType = oracle.getParameterizedType(
- comparableType, new JClassType[] {computedSubtype});
if (computedSubtype.isLocalType()) {
// Ignore local types.
continue;
}
+ // Find the parameterized version of the Comparable interface.
+ JClassType comparableIntf = findParameterizationOf(computedSubtype,
+ comparableType);
+
assertTrue(computedSubtype.isAssignableTo(serializableType));
- assertTrue(computedSubtype.isAssignableTo(parameterizedComparableType));
+ assertTrue(computedSubtype.isAssignableTo(comparableIntf));
}
}
@Override
public void testIsAssignableFrom() throws NotFoundException {
JTypeParameter testType = getTestType();
- assertTrue(testType.isAssignableFrom(moduleContext.getOracle().getJavaLangObject()));
+ assertTrue(testType.isAssignableFrom(moduleContext.getOracle().getType(
+ Serializable.class.getName())));
+
+ // Check that the type parameter is assignable from each subtype
+ JClassType[] subtypes = testType.getSubtypes();
+ for (JClassType subtype : subtypes) {
+ assertTrue(testType.isAssignableFrom(subtype));
+ }
}
@Override
public void testIsAssignableTo() throws NotFoundException {
JTypeParameter testType = getTestType();
assertTrue(testType.isAssignableTo(moduleContext.getOracle().getJavaLangObject()));
+
+ // Check that each bound is assignable to this type parameter.
+ JClassType[] typeBounds = testType.getBounds().getBounds();
+ for (JClassType typeBound : typeBounds) {
+ // Test that the type parameter is assignable to the type bound.
+ assertTrue(testType.isAssignableTo(typeBound));
+
+ // Test that the type parameter is assignable from the type bound.
+ assertTrue(typeBound.isAssignableFrom(testType));
+ }
}
@Override
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/JWildcardTypeTest.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/JWildcardTypeTest.java
index 367a39d..fa6c004 100644
--- a/dev/core/test/com/google/gwt/core/ext/typeinfo/JWildcardTypeTest.java
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/JWildcardTypeTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -24,6 +24,7 @@
import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
/**
@@ -57,6 +58,20 @@
// Wildcard do not have nested types...
}
+ @Override
+ public void testGetErasedType() throws NotFoundException {
+ TypeOracle oracle = moduleContext.getOracle();
+ JClassType numberType = oracle.getType(Number.class.getCanonicalName());
+
+ // Tests that ? extends Number erases to number.
+ JWildcardType upperBoundWildcard = oracle.getWildcardType(new JUpperBound(numberType));
+ assertEquals(numberType, upperBoundWildcard.getErasedType());
+
+ // Tests that ? super Number erases to Object
+ JWildcardType lowerBoundWildcard = oracle.getWildcardType(new JLowerBound(numberType));
+ assertEquals(oracle.getJavaLangObject(), lowerBoundWildcard.getErasedType());
+ }
+
public void testGetMethods() throws NotFoundException {
super.testGetMethods();
}
@@ -112,8 +127,46 @@
}
@Override
- public void testIsAssignableFrom() {
+ public void testIsAssignableFrom() throws NotFoundException {
// Covered by the different testIsAssignableFrom*() variants below.
+ TypeOracle oracle = moduleContext.getOracle();
+
+
+ JClassType integerType = oracle.getType(Integer.class.getName());
+ JClassType numberType = oracle.getType(Number.class.getName());
+
+ // ? extends Number
+ JClassType extendsNumber = oracle.getWildcardType(new JUpperBound(numberType));
+
+ // ? extends Integer
+ JClassType extendsInteger = oracle.getWildcardType(new JUpperBound(integerType));
+
+ // Integer is not assignable from ? extends Number
+ assertFalse(integerType.isAssignableFrom(extendsNumber));
+
+ // Integer is assignable from ? extends Integer
+ assertTrue(integerType.isAssignableFrom(extendsInteger));
+
+ // Number is assignable from ? extends Integer
+ assertTrue(numberType.isAssignableFrom(extendsInteger));
+
+ // ? super Integer
+ JClassType superInteger = oracle.getWildcardType(new JLowerBound(integerType));
+
+ // Integer is assignable from ? super Integer
+ assertFalse(integerType.isAssignableFrom(superInteger));
+
+ // ? super Integer is assignable from Number
+ assertTrue(superInteger.isAssignableFrom(numberType));
+
+ JClassType superNumber = oracle.getWildcardType(new JLowerBound(numberType));
+
+ // ? super Number is assignable from Integer
+ assertTrue(superNumber.isAssignableFrom(integerType));
+
+ // ? super Number is assignable from Character
+ JClassType characterType = oracle.getType(Character.class.getName());
+ assertTrue(superNumber.isAssignableFrom(characterType));
}
/**
@@ -137,8 +190,7 @@
}
/**
- * Tests that <? extends Number> is assignable from <? extends Integer> and
- * that the reverse is not <code>true</code>.
+ * Tests that <? extends Object> is assignable to and from <? super Object>.
*/
public void testIsAssignableFrom_Extends_Object_From_Super_Object() {
TypeOracle oracle = moduleContext.getOracle();
@@ -147,16 +199,21 @@
JLowerBound lowerBound = new JLowerBound(javaLangObject);
JUpperBound upperBound = new JUpperBound(javaLangObject);
+ // ? super Object
JWildcardType lowerWildcard = oracle.getWildcardType(lowerBound);
+
+ // ? extends Object
JWildcardType upperWildcard = oracle.getWildcardType(upperBound);
+ // ? extends Object assignable from ? super Object
assertTrue(upperWildcard.isAssignableFrom(lowerWildcard));
- assertFalse(lowerWildcard.isAssignableFrom(upperWildcard));
+
+ // ? super Object assignable from ? extends Object
+ assertTrue(lowerWildcard.isAssignableFrom(upperWildcard));
}
/**
- * Tests that <? super Integer> is assignable from <? super Number> and that
- * the reverse is not <code>true</code>.
+ * Tests that <? super Integer> is assignable to and from <? super Number>.
*/
public void testIsAssignableFrom_Super_Integer_From_Super_Number()
throws NotFoundException {
@@ -170,15 +227,14 @@
JWildcardType numberWildcard = oracle.getWildcardType(numberBound);
JWildcardType integerWildcard = oracle.getWildcardType(integerBound);
- assertFalse(numberWildcard.isAssignableFrom(integerWildcard));
+ assertTrue(numberWildcard.isAssignableFrom(integerWildcard));
assertTrue(numberWildcard.isAssignableTo(integerWildcard));
assertTrue(integerWildcard.isAssignableFrom(numberWildcard));
- assertFalse(integerWildcard.isAssignableTo(numberWildcard));
+ assertTrue(integerWildcard.isAssignableTo(numberWildcard));
}
/**
- * Tests that <? super Number> is assignable to <? super Integer> and that the
- * reverse is not <code>true</code>.
+ * Tests that <? super Number> is assignable to and from <? super Integer>.
*/
public void testIsAssignableFrom_Super_Number_To_Super_Integer()
throws NotFoundException {
@@ -193,7 +249,7 @@
JWildcardType integerWildcard = oracle.getWildcardType(integerBound);
assertTrue(numberWildcard.isAssignableTo(integerWildcard));
- assertFalse(integerWildcard.isAssignableTo(numberWildcard));
+ assertTrue(integerWildcard.isAssignableTo(numberWildcard));
}
@Override
@@ -222,8 +278,7 @@
}
/**
- * Tests that <? super Number> is assignable to <? super Integer> and that
- * the reverse is not <code>true</code>.
+ * Tests that <? super Number> is assignable to and from <? super Integer>.
*/
public void testIsAssignableTo_Super_Number_To_Super_Integer()
throws NotFoundException {
@@ -237,7 +292,7 @@
JWildcardType numberWildcard = oracle.getWildcardType(numberBound);
JWildcardType integerWildcard = oracle.getWildcardType(integerBound);
- assertFalse(integerWildcard.isAssignableTo(numberWildcard));
+ assertTrue(integerWildcard.isAssignableTo(numberWildcard));
assertTrue(numberWildcard.isAssignableTo(integerWildcard));
}
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/ExtendsRawGenericClass.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/ExtendsRawGenericClass.java
new file mode 100644
index 0000000..f6a6bd9
--- /dev/null
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/ExtendsRawGenericClass.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.core.ext.typeinfo.test;
+
+/**
+ * Class used to test assignment between a parameterized type and a subclass
+ * of the raw version.
+ */
+public class ExtendsRawGenericClass extends GenericClass {
+}
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/GenericClass.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/GenericClass.java
index 047b3af..f328c00 100644
--- a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/GenericClass.java
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/GenericClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -29,7 +29,7 @@
* definition of GenericClass is as follows: class GenericClass<T extends
* Serializable & Comparable<T>> implements Comparable<T> { ... }
*/
-public class GenericClass<T> implements Comparable<T> {
+public class GenericClass<T extends Serializable> implements Comparable<T>, Serializable {
/**
* Non-static, generic inner class.
*
@@ -65,8 +65,6 @@
*/
// GenericClass.NonGenericInnerClass rawNonGenericInnerClassField;
- GenericClass<Integer>.Foo.Bar wtf;
-
Class rawClazzField;
/**
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/GenericSubclass.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/GenericSubclass.java
index 23187a6..5935087 100644
--- a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/GenericSubclass.java
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/GenericSubclass.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
@@ -15,10 +15,12 @@
*/
package com.google.gwt.core.ext.typeinfo.test;
+import java.io.Serializable;
+
/**
* Test a generic class that extends a generic class.
*/
-public class GenericSubclass<U> extends GenericClass<U> {
+public class GenericSubclass<U extends Serializable> extends GenericClass<U> {
GenericClass<Integer> child;
public GenericSubclass(U t) {