Fixes another problem with JSNI method signatures introduced in r2090.  Decided to maintain information about whether a type bound was implicit (i.e. ?) or explicit ? (extends | super) T.

Added a test case to JWildcardTypeTest to make sure that we don't break JSNI again.

Review by: spoon (desk check)

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2110 8db76d5a-ed1c-0410-87a9-c151d255dfc7
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 5fb3d07..994a427 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
@@ -15,6 +15,8 @@
  */
 package com.google.gwt.core.ext.typeinfo;
 
+import com.google.gwt.core.ext.typeinfo.JWildcardType.BoundType;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.IdentityHashMap;
@@ -51,7 +53,7 @@
     for (int i = 0; i < newTypeArgs.length; ++i) {
       JClassType newTypeArg = substitutionMap.get(typeParameters[i]);
       if (newTypeArg == null) {
-        newTypeArg = oracle.getWildcardType(true,
+        newTypeArg = oracle.getWildcardType(BoundType.EXTENDS,
             typeParameters[i].getFirstBound());
       }
 
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 b25cf49..bb5a33e 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
@@ -19,13 +19,32 @@
  * Represents a wildcard type argument to a parameterized type.
  */
 public class JWildcardType extends JDelegatingClassType {
-  private boolean isUpperBound;
+  /**
+   * Type of wildcard bound.
+   */
+  public enum BoundType {
+    /**
+     * Used when the declaration explicitly used ? extends Type.
+     */
+    EXTENDS,
+
+    /**
+     * Used when the declaration explicitly used ? super Type.
+     */
+    SUPER,
+
+    /**
+     * Used when the declaration did not specify a bound.
+     */
+    UNBOUND
+  }
 
   private JClassType[] lazyLowerBounds;
   private JClassType[] lazyUpperBounds;
+  private final BoundType boundType;
 
-  public JWildcardType(boolean isUpperBound, JClassType typeBound) {
-    this.isUpperBound = isUpperBound;
+  public JWildcardType(BoundType boundType, JClassType typeBound) {
+    this.boundType = boundType;
     super.setBaseType(typeBound);
   }
 
@@ -41,7 +60,7 @@
 
   @Override
   public JClassType getErasedType() {
-    if (isUpperBound) {
+    if (isUpperBound()) {
       // ? extends T erases to T
       return getFirstBound().getErasedType();
     }
@@ -72,7 +91,7 @@
    */
   public JClassType[] getLowerBounds() {
     if (lazyLowerBounds == null) {
-      if (isUpperBound) {
+      if (isUpperBound()) {
         lazyLowerBounds = TypeOracle.NO_JCLASSES;
       } else {
         lazyLowerBounds = new JClassType[] {getFirstBound()};
@@ -104,7 +123,7 @@
 
   @Override
   public JClassType[] getSubtypes() {
-    if (isUpperBound) {
+    if (isUpperBound()) {
       return getFirstBound().getSubtypes();
     }
 
@@ -117,7 +136,7 @@
 
   @Override
   public JClassType getSuperclass() {
-    if (isUpperBound) {
+    if (isUpperBound()) {
       // The superclass of an upper bound is the upper bound.
       return getFirstBound();
     }
@@ -134,7 +153,7 @@
    */
   public JClassType[] getUpperBounds() {
     if (lazyUpperBounds == null) {
-      if (isUpperBound) {
+      if (isUpperBound()) {
         lazyUpperBounds = new JClassType[] {getFirstBound()};
       } else {
         // Object is the default upper bound.
@@ -174,22 +193,35 @@
    *         requested
    */
   boolean boundsMatch(JWildcardType otherWildcard) {
-    return isUpperBound == otherWildcard.isUpperBound
+    return isUpperBound() == otherWildcard.isUpperBound()
         && getFirstBound() == otherWildcard.getFirstBound();
   }
 
   @Override
   JClassType getSubstitutedType(JParameterizedType parameterizedType) {
-    return getOracle().getWildcardType(isUpperBound,
+    return getOracle().getWildcardType(boundType,
         getFirstBound().getSubstitutedType(parameterizedType));
   }
 
+  private boolean isUnbound() {
+    return boundType == BoundType.UNBOUND;
+  }
+
+  private boolean isUpperBound() {
+    return boundType != BoundType.SUPER;
+  }
+
   private String toString(boolean simpleName) {
-    String str = "?" + (isUpperBound ? " super " : " extends ");
-    if (simpleName) {
-      return str + getFirstBound().getSimpleSourceName();
+    String str = "?";
+    if (isUnbound()) {
+      return str;
     } else {
-      return str + getFirstBound().getParameterizedQualifiedSourceName();
+      str += (isUpperBound() ? " extends " : " super ");
+      if (simpleName) {
+        return str + getFirstBound().getSimpleSourceName();
+      } else {
+        return str + getFirstBound().getParameterizedQualifiedSourceName();
+      }
     }
   }
 }
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/TypeOracle.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/TypeOracle.java
index 6a0e534..a4a53c3 100644
--- a/dev/core/src/com/google/gwt/core/ext/typeinfo/TypeOracle.java
+++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/TypeOracle.java
@@ -467,9 +467,9 @@
     }
   }
 
-  public JWildcardType getWildcardType(boolean isUpperBound,
+  public JWildcardType getWildcardType(JWildcardType.BoundType boundType,
       JClassType typeBound) {
-    JWildcardType wildcardType = new JWildcardType(isUpperBound, typeBound);
+    JWildcardType wildcardType = new JWildcardType(boundType, typeBound);
     String sig = wildcardType.getQualifiedSourceName();
     List<JWildcardType> candidates = wildcardTypes.get(sig);
     if (candidates == null) {
diff --git a/dev/core/src/com/google/gwt/dev/jdt/TypeOracleBuilder.java b/dev/core/src/com/google/gwt/dev/jdt/TypeOracleBuilder.java
index 6726d88..cfc615c 100644
--- a/dev/core/src/com/google/gwt/dev/jdt/TypeOracleBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/jdt/TypeOracleBuilder.java
@@ -39,6 +39,7 @@
 import com.google.gwt.core.ext.typeinfo.JType;
 import com.google.gwt.core.ext.typeinfo.JTypeParameter;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
+import com.google.gwt.core.ext.typeinfo.JWildcardType.BoundType;
 import com.google.gwt.dev.jdt.CacheManager.Mapper;
 import com.google.gwt.dev.util.Empty;
 import com.google.gwt.dev.util.PerfLogger;
@@ -1527,24 +1528,24 @@
 
       assert (wcBinding.otherBounds == null);
 
-      boolean isUpperBound;
+      BoundType boundType;
       JClassType typeBound;
 
       switch (wcBinding.boundKind) {
         case Wildcard.EXTENDS: {
           assert (wcBinding.bound != null);
-          isUpperBound = true;
+          boundType = BoundType.EXTENDS;
           typeBound = (JClassType) resolveType(logger, wcBinding.bound);
         }
           break;
         case Wildcard.SUPER: {
           assert (wcBinding.bound != null);
-          isUpperBound = false;
+          boundType = BoundType.SUPER;
           typeBound = (JClassType) resolveType(logger, wcBinding.bound);
         }
           break;
         case Wildcard.UNBOUND: {
-          isUpperBound = true;
+          boundType = BoundType.UNBOUND;
           typeBound = (JClassType) resolveType(logger, wcBinding.erasure());
         }
           break;
@@ -1553,7 +1554,7 @@
           return null;
       }
 
-      return oracle.getWildcardType(isUpperBound, typeBound);
+      return oracle.getWildcardType(boundType, typeBound);
     }
 
     // Log other cases we know about that don't make sense.
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 6c10840..43eb420 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
@@ -17,6 +17,7 @@
 
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JWildcardType.BoundType;
 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;
@@ -89,7 +90,7 @@
   public void testGenericClass_LowerBoundWildcard() throws NotFoundException {
     TypeOracle oracle = moduleContext.getOracle();
     JGenericType genericType = getGenericTestType();
-    JWildcardType lowerBoundWildcard = oracle.getWildcardType(false,
+    JWildcardType lowerBoundWildcard = oracle.getWildcardType(BoundType.SUPER,
         integerType);
 
     JClassType type = oracle.getParameterizedType(genericType,
@@ -103,8 +104,8 @@
   public void testGenericClass_UnboundWildcard() throws NotFoundException {
     TypeOracle oracle = moduleContext.getOracle();
     JGenericType genericType = getGenericTestType();
-    JWildcardType upperBoundWildcard = oracle.getWildcardType(true,
-        oracle.getJavaLangObject());
+    JWildcardType upperBoundWildcard = oracle.getWildcardType(
+        BoundType.EXTENDS, oracle.getJavaLangObject());
 
     JClassType type = oracle.getParameterizedType(genericType,
         new JClassType[] {upperBoundWildcard});
@@ -117,7 +118,8 @@
   public void testGenericClass_UpperBoundWildcard() throws NotFoundException {
     TypeOracle oracle = moduleContext.getOracle();
     JGenericType genericType = getGenericTestType();
-    JWildcardType upperBoundWildcard = oracle.getWildcardType(true, integerType);
+    JWildcardType upperBoundWildcard = oracle.getWildcardType(
+        BoundType.EXTENDS, integerType);
 
     JClassType type = oracle.getParameterizedType(genericType,
         new JClassType[] {upperBoundWildcard});
@@ -205,7 +207,7 @@
     JGenericType myCustomListType = oracle.getType(MyCustomList.class.getName()).isGenericType();
     JParameterizedType parameterizedMyCustomList = oracle.getParameterizedType(
         myCustomListType, new JClassType[] {
-            oracle.getWildcardType(true,
+            oracle.getWildcardType(BoundType.EXTENDS,
                 oracle.getType(Serializable.class.getName())), integerType});
     JClassType[] expected = {
         oracle.getType(MyIntegerList.class.getName()),
@@ -230,12 +232,12 @@
     JGenericType genericList = (JGenericType) oracle.getType(List.class.getName());
 
     // ?
-    JWildcardType unboundWildcard = oracle.getWildcardType(true,
+    JWildcardType unboundWildcard = oracle.getWildcardType(BoundType.EXTENDS,
         oracle.getJavaLangObject());
 
     // ? extends Number
-    JWildcardType numUpperBoundWildcard = oracle.getWildcardType(true,
-        oracle.getType(Number.class.getName()));
+    JWildcardType numUpperBoundWildcard = oracle.getWildcardType(
+        BoundType.EXTENDS, oracle.getType(Number.class.getName()));
 
     // List<?>
     JParameterizedType unboundList = oracle.getParameterizedType(genericList,
@@ -253,8 +255,8 @@
     assertTrue(listOfExtendsNumber.isAssignableTo(unboundList));
 
     // ? extends Integer
-    JWildcardType intUpperBoundWildcard = oracle.getWildcardType(true,
-        integerType);
+    JWildcardType intUpperBoundWildcard = oracle.getWildcardType(
+        BoundType.EXTENDS, integerType);
 
     // List<? extends Integer>
     JParameterizedType listOfExtendsInteger = oracle.getParameterizedType(
@@ -268,10 +270,10 @@
     assertTrue(listOfExtendsInteger.isAssignableTo(listOfExtendsNumber));
 
     // List<? super Integer> should be assignable from List<? super Number>
-    JWildcardType numLowerBoundWildcard = oracle.getWildcardType(false,
-        oracle.getType(Number.class.getName()));
-    JWildcardType intLowerBoundWildcard = oracle.getWildcardType(false,
-        integerType);
+    JWildcardType numLowerBoundWildcard = oracle.getWildcardType(
+        BoundType.SUPER, oracle.getType(Number.class.getName()));
+    JWildcardType intLowerBoundWildcard = oracle.getWildcardType(
+        BoundType.SUPER, integerType);
 
     // List<? super Number>
     JParameterizedType listOfSuperNumber = oracle.getParameterizedType(
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 5fdce28..d91a1d3 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
@@ -17,6 +17,7 @@
 
 import com.google.gwt.core.ext.TreeLogger;
 import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JWildcardType.BoundType;
 import com.google.gwt.core.ext.typeinfo.test.CA;
 import com.google.gwt.core.ext.typeinfo.test.CB;
 import com.google.gwt.core.ext.typeinfo.test.CC;
@@ -63,11 +64,13 @@
     JClassType numberType = oracle.getType(Number.class.getCanonicalName());
 
     // Tests that ? extends Number erases to number.
-    JWildcardType upperBoundWildcard = oracle.getWildcardType(true, numberType);
+    JWildcardType upperBoundWildcard = oracle.getWildcardType(
+        BoundType.EXTENDS, numberType);
     assertEquals(numberType, upperBoundWildcard.getErasedType());
 
     // Tests that ? super Number erases to Object
-    JWildcardType lowerBoundWildcard = oracle.getWildcardType(false, numberType);
+    JWildcardType lowerBoundWildcard = oracle.getWildcardType(BoundType.SUPER,
+        numberType);
     assertEquals(oracle.getJavaLangObject(), lowerBoundWildcard.getErasedType());
   }
 
@@ -90,6 +93,32 @@
     // No overridable methods
   }
 
+  /**
+   * Tests that {@link JWildcardType#getParameterizedQualifiedSourceName()}
+   * returns the expected value. We test this because JSNI code depends on it.
+   * 
+   * @throws NotFoundException
+   */
+  public void testGetParameterizedQualifiedSourceName()
+      throws NotFoundException {
+    TypeOracle oracle = moduleContext.getOracle();
+    JClassType numberType = oracle.getType(Number.class.getName());
+
+    JWildcardType numberUpperBound = oracle.getWildcardType(BoundType.EXTENDS,
+        numberType);
+    assertEquals("? extends " + Number.class.getCanonicalName(),
+        numberUpperBound.getParameterizedQualifiedSourceName());
+
+    JWildcardType numberLowerBound = oracle.getWildcardType(BoundType.SUPER,
+        numberType);
+    assertEquals("? super " + Number.class.getCanonicalName(),
+        numberLowerBound.getParameterizedQualifiedSourceName());
+
+    JWildcardType unboundWildcard = oracle.getWildcardType(BoundType.UNBOUND,
+        oracle.getJavaLangObject());
+    assertEquals("?", unboundWildcard.getParameterizedQualifiedSourceName());
+  }
+
   @Override
   public void testGetSubtypes() {
     // Tested by testGetSubtypes_LowerBound() and testGetSubtypes_UpperBound()
@@ -98,7 +127,7 @@
   public void testGetSubtypes_LowerBound() throws NotFoundException {
     TypeOracle oracle = moduleContext.getOracle();
     // <? super Number>
-    JWildcardType lowerBoundWildcard = oracle.getWildcardType(false,
+    JWildcardType lowerBoundWildcard = oracle.getWildcardType(BoundType.SUPER,
         oracle.getType(Number.class.getName()));
     JClassType[] subtypes = lowerBoundWildcard.getSubtypes();
     assertEquals(0, subtypes.length);
@@ -108,8 +137,8 @@
   public void testGetSubtypes_UpperBound() throws NotFoundException {
     TypeOracle oracle = moduleContext.getOracle();
     // <? extends CA>
-    JWildcardType upperBoundWildcard = oracle.getWildcardType(true,
-        oracle.getType(CA.class.getName()));
+    JWildcardType upperBoundWildcard = oracle.getWildcardType(
+        BoundType.EXTENDS, oracle.getType(CA.class.getName()));
 
     JClassType[] expected = new JClassType[] {
         oracle.getType(CB.class.getName()), oracle.getType(CC.class.getName())};
@@ -134,10 +163,12 @@
     JClassType numberType = oracle.getType(Number.class.getName());
 
     // ? extends Number
-    JClassType extendsNumber = oracle.getWildcardType(true, numberType);
+    JClassType extendsNumber = oracle.getWildcardType(BoundType.EXTENDS,
+        numberType);
 
     // ? extends Integer
-    JClassType extendsInteger = oracle.getWildcardType(true, integerType);
+    JClassType extendsInteger = oracle.getWildcardType(BoundType.EXTENDS,
+        integerType);
 
     // Integer is not assignable from ? extends Number
     assertFalse(integerType.isAssignableFrom(extendsNumber));
@@ -149,7 +180,8 @@
     assertTrue(numberType.isAssignableFrom(extendsInteger));
 
     // ? super Integer
-    JClassType superInteger = oracle.getWildcardType(false, integerType);
+    JClassType superInteger = oracle.getWildcardType(BoundType.SUPER,
+        integerType);
 
     // Integer is assignable from ? super Integer
     assertFalse(integerType.isAssignableFrom(superInteger));
@@ -157,7 +189,7 @@
     // ? super Integer is assignable from Number
     assertTrue(superInteger.isAssignableFrom(numberType));
 
-    JClassType superNumber = oracle.getWildcardType(false, numberType);
+    JClassType superNumber = oracle.getWildcardType(BoundType.SUPER, numberType);
 
     // ? super Number is assignable from Integer
     assertTrue(superNumber.isAssignableFrom(integerType));
@@ -177,8 +209,10 @@
     JClassType numberType = oracle.getType(Number.class.getName());
     JClassType integerType = oracle.getType(Integer.class.getName());
 
-    JWildcardType numberWildcard = oracle.getWildcardType(true, numberType);
-    JWildcardType integerWildcard = oracle.getWildcardType(true, integerType);
+    JWildcardType numberWildcard = oracle.getWildcardType(BoundType.EXTENDS,
+        numberType);
+    JWildcardType integerWildcard = oracle.getWildcardType(BoundType.EXTENDS,
+        integerType);
 
     assertTrue(numberWildcard.isAssignableFrom(integerWildcard));
     assertFalse(integerWildcard.isAssignableFrom(numberWildcard));
@@ -193,10 +227,12 @@
     JClassType javaLangObject = oracle.getJavaLangObject();
 
     // ? super Object
-    JWildcardType lowerWildcard = oracle.getWildcardType(false, javaLangObject);
+    JWildcardType lowerWildcard = oracle.getWildcardType(BoundType.SUPER,
+        javaLangObject);
 
     // ? extends Object
-    JWildcardType upperWildcard = oracle.getWildcardType(true, javaLangObject);
+    JWildcardType upperWildcard = oracle.getWildcardType(BoundType.EXTENDS,
+        javaLangObject);
 
     // ? extends Object assignable from ? super Object
     assertTrue(upperWildcard.isAssignableFrom(lowerWildcard));
@@ -214,8 +250,10 @@
     JClassType numberType = oracle.getType(Number.class.getName());
     JClassType integerType = oracle.getType(Integer.class.getName());
 
-    JWildcardType numberWildcard = oracle.getWildcardType(false, numberType);
-    JWildcardType integerWildcard = oracle.getWildcardType(false, integerType);
+    JWildcardType numberWildcard = oracle.getWildcardType(BoundType.SUPER,
+        numberType);
+    JWildcardType integerWildcard = oracle.getWildcardType(BoundType.SUPER,
+        integerType);
 
     assertTrue(numberWildcard.isAssignableFrom(integerWildcard));
     assertTrue(numberWildcard.isAssignableTo(integerWildcard));
@@ -232,8 +270,10 @@
     JClassType numberType = oracle.getType(Number.class.getName());
     JClassType integerType = oracle.getType(Integer.class.getName());
 
-    JWildcardType numberWildcard = oracle.getWildcardType(false, numberType);
-    JWildcardType integerWildcard = oracle.getWildcardType(false, integerType);
+    JWildcardType numberWildcard = oracle.getWildcardType(BoundType.SUPER,
+        numberType);
+    JWildcardType integerWildcard = oracle.getWildcardType(BoundType.SUPER,
+        integerType);
 
     assertTrue(numberWildcard.isAssignableTo(integerWildcard));
     assertTrue(integerWildcard.isAssignableTo(numberWildcard));
@@ -254,8 +294,10 @@
     JClassType numberType = oracle.getType(Number.class.getName());
     JClassType integerType = oracle.getType(Integer.class.getName());
 
-    JWildcardType numberWildcard = oracle.getWildcardType(true, numberType);
-    JWildcardType integerWildcard = oracle.getWildcardType(true, integerType);
+    JWildcardType numberWildcard = oracle.getWildcardType(BoundType.EXTENDS,
+        numberType);
+    JWildcardType integerWildcard = oracle.getWildcardType(BoundType.EXTENDS,
+        integerType);
 
     assertTrue(integerWildcard.isAssignableTo(numberWildcard));
     assertFalse(numberWildcard.isAssignableTo(integerWildcard));
@@ -270,8 +312,10 @@
     JClassType numberType = oracle.getType(Number.class.getName());
     JClassType integerType = oracle.getType(Integer.class.getName());
 
-    JWildcardType numberWildcard = oracle.getWildcardType(false, numberType);
-    JWildcardType integerWildcard = oracle.getWildcardType(false, integerType);
+    JWildcardType numberWildcard = oracle.getWildcardType(BoundType.SUPER,
+        numberType);
+    JWildcardType integerWildcard = oracle.getWildcardType(BoundType.SUPER,
+        integerType);
 
     assertTrue(integerWildcard.isAssignableTo(numberWildcard));
     assertTrue(numberWildcard.isAssignableTo(integerWildcard));
@@ -289,6 +333,7 @@
   @Override
   protected JWildcardType getTestType() throws NotFoundException {
     TypeOracle oracle = moduleContext.getOracle();
-    return oracle.getWildcardType(true, oracle.getType(Number.class.getName()));
+    return oracle.getWildcardType(BoundType.EXTENDS,
+        oracle.getType(Number.class.getName()));
   }
 }