Revert "Dramatically improves generics support in UiBinder."

This reverts commit ba30ecd58ec03a7009ed17e6863a41d01a946828.

This breaks existing use case with local type variables (e.g. <T> T createX()) due to a bug in Class#isAssignableFrom. I will try again later.

Change-Id: I2965cc49953b90f03a70d43bfdbaf3326e902778
diff --git a/user/src/com/google/gwt/uibinder/elementparsers/BeanParser.java b/user/src/com/google/gwt/uibinder/elementparsers/BeanParser.java
index 7a8f593..5e1e6a0 100644
--- a/user/src/com/google/gwt/uibinder/elementparsers/BeanParser.java
+++ b/user/src/com/google/gwt/uibinder/elementparsers/BeanParser.java
@@ -140,7 +140,7 @@
         writer.die(elem, "Duplicate attribute name: %s", propertyName);
       }
 
-      if (unfilledRequiredParams.containsKey(propertyName)) {
+      if (unfilledRequiredParams.keySet().contains(propertyName)) {
         JType paramType = unfilledRequiredParams.get(propertyName);
         String value = elem.consumeAttributeWithDefault(attribute.getName(),
             null, paramType);
diff --git a/user/src/com/google/gwt/uibinder/rebind/FieldReference.java b/user/src/com/google/gwt/uibinder/rebind/FieldReference.java
index 1de4f3d..3092525 100644
--- a/user/src/com/google/gwt/uibinder/rebind/FieldReference.java
+++ b/user/src/com/google/gwt/uibinder/rebind/FieldReference.java
@@ -53,7 +53,7 @@
       } else if (i > 0) {
         b.append(", ");
       }
-      b.append(types[i]);
+      b.append(types[i].getQualifiedSourceName());
     }
 
     return b.toString();
@@ -139,7 +139,7 @@
 
     for (JType leftType : left.types) {
 
-      if (leftType.equals(rightHandType)) {
+      if (leftType == rightHandType) {
         return;
       }
 
@@ -178,7 +178,7 @@
      * fact, which will halt processing.
      */
     logger.error(left.source, "%s required, but %s returns %s", renderTypesList(left.types),
-        FieldReference.this, rightHandType);
+        FieldReference.this, rightHandType.getQualifiedSourceName());
   }
 
   private boolean handleMismatchedNonNumericPrimitives(JType leftType, JType rightHandType,
diff --git a/user/src/com/google/gwt/uibinder/rebind/HandlerEvaluator.java b/user/src/com/google/gwt/uibinder/rebind/HandlerEvaluator.java
index 0078d66..a2fd077 100644
--- a/user/src/com/google/gwt/uibinder/rebind/HandlerEvaluator.java
+++ b/user/src/com/google/gwt/uibinder/rebind/HandlerEvaluator.java
@@ -25,6 +25,7 @@
 import com.google.gwt.event.shared.EventHandler;
 import com.google.gwt.uibinder.client.UiHandler;
 import com.google.gwt.uibinder.rebind.model.OwnerClass;
+import com.google.gwt.uibinder.rebind.model.OwnerField;
 import com.google.web.bindery.event.shared.HandlerRegistration;
 
 /**
@@ -154,6 +155,9 @@
                   + "in the template."), boundMethod, objectName);
         }
         JClassType objectType = fieldWriter.getInstantiableType();
+        if (objectType.isGenericType() != null) {
+          objectType = tryEnhancingTypeInfo(objectName, objectType);
+        }
 
         // Retrieves the "add handler" method in the object.
         JMethod addHandlerMethodType = getAddHandlerMethodForObject(objectType, handlerType);
@@ -169,6 +173,23 @@
     }
   }
 
+  private JClassType tryEnhancingTypeInfo(String objectName, JClassType objectType) {
+    OwnerField uiField = ownerClass.getUiField(objectName);
+    if (uiField != null) {
+      JParameterizedType pType = uiField.getRawType().isParameterized();
+      if (pType != null) {
+        // Even field is parameterized, it might be a super class. In that case, if we use the field
+        // type then we might miss some add handlers methods from the objectType itself; something
+        // we don't want to happen!
+        if (pType.getBaseType().equals(objectType)) {
+          // Now we proved type from UiField is more specific, let's use that one
+          return pType;
+        }
+      }
+    }
+    return objectType;
+  }
+
   /**
    * Writes a handler entry using the given writer.
    *
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
index 3a9ccb0..f94ca7f 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
@@ -917,15 +917,8 @@
     // Get the class associated with this element.
     JClassType type = findFieldType(elem);
 
-
-    // If the element has a name then let's try enhancing the type info.
-    String fieldName = getFieldName(elem);
-    if (fieldName != null) {
-      type = tryEnhancingTypeInfo(fieldName, type);
-    }
-
     // Declare its field.
-    FieldWriter field = declareField(elem, type, fieldName);
+    FieldWriter field = declareField(elem, type.getQualifiedSourceName());
 
     /*
      * Push the field that will hold this widget on top of the parsedFieldStack
@@ -1093,10 +1086,17 @@
 
   /**
    * Declares a field of the given type name, returning the name of the declared
-   * field. If {@code fieldName} is {@code null}, it will be generated.
+   * field. If the element has a field or id attribute, use its value.
+   * Otherwise, create and return a new, private field name for it.
    */
-  private FieldWriter declareField(XMLElement source, JClassType type, String fieldName)
+  private FieldWriter declareField(XMLElement source, String typeName)
       throws UnableToCompleteException {
+    JClassType type = oracle.findType(typeName);
+    if (type == null) {
+      die(source, "Unknown type %s", typeName);
+    }
+
+    String fieldName = getFieldName(source);
     if (fieldName == null) {
       // TODO(rjrjr) could collide with user declared name, as is
       // also a worry in HandlerEvaluator. Need a general scheme for
@@ -1108,28 +1108,6 @@
     return fieldManager.registerField(type, fieldName);
   }
 
-  /**
-   * This method tries to improve the existing type information by looking at the ui field.
-   * declaration. (Although the ui.xml cannot define the type parameters for generic types, the
-   * field declaration itself inside the class might include this information.)
-   */
-  private JClassType tryEnhancingTypeInfo(String fieldName, JClassType fieldType) {
-    OwnerField uiField = ownerClass.getUiField(fieldName);
-    if (uiField != null) {
-      JParameterizedType pType = uiField.getRawType().isParameterized();
-      if (pType != null) {
-        // Even if the field is parameterized, the type of the field might be a super class of the
-        // type declared in the xml. In that case, the new type would be less specific, we don't
-        // want that to happen:
-        if (pType.getBaseType().equals(fieldType)) {
-          // Now we proved type from UiField is more specific, let's use that one.
-          return pType;
-        }
-      }
-    }
-    return fieldType;
-  }
-
   private void dieGettingEventTypeName(JMethod jMethod, Exception e)
       throws UnableToCompleteException {
     die("Could not obtain DomEvent.Type object for first parameter of %s (%s)",
diff --git a/user/src/com/google/gwt/uibinder/rebind/model/OwnerClass.java b/user/src/com/google/gwt/uibinder/rebind/model/OwnerClass.java
index ac7bc03..7a997ae 100644
--- a/user/src/com/google/gwt/uibinder/rebind/model/OwnerClass.java
+++ b/user/src/com/google/gwt/uibinder/rebind/model/OwnerClass.java
@@ -32,7 +32,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.TreeMap;
 
 /**
@@ -63,12 +62,6 @@
       new HashMap<JClassType, JMethod>();
 
   /**
-   * Map from raw type to the method that produces it.
-   */
-  private final Map<JClassType, JMethod> uiFactoriesForRawTypes =
-      new HashMap<JClassType, JMethod>();
-
-  /**
    * List of all @UiHandler methods in the owner class.
    */
   private final List<JMethod> uiHandlers = new ArrayList<JMethod>();
@@ -79,7 +72,6 @@
 
   private final UiBinderContext context;
 
-
   /**
    * Constructor.
    *
@@ -93,7 +85,6 @@
     this.context = context;
     findUiFields(ownerType);
     findUiFactories(ownerType);
-    findRawUiFactories();
     findUiHandlers(ownerType);
   }
 
@@ -113,26 +104,7 @@
       forType = genericType.getRawType();
     }
 
-    // Exact match
-    JMethod jMethod = uiFactories.get(forType);
-
-    // If A<T>, A<String> or A<?> are queried, match to A as backward compatibility:
-    if (jMethod == null && forType.isParameterized() != null) {
-      jMethod = uiFactories.get(forType.getErasedType());
-    }
-
-    // If A or A<?> is queried, match to A<T>, A<String> etc. as it is a valid assignment:
-    if (jMethod == null && (forType.isRawType() != null || isParametrizedWithWildcard(forType))) {
-      jMethod = uiFactoriesForRawTypes.get(forType.getErasedType());
-    }
-
-    return jMethod;
-  }
-
-  private static boolean isParametrizedWithWildcard(JClassType type) {
-    JParameterizedType parameterized = type.isParameterized();
-    return parameterized != null
-        && parameterized.isAssignableFrom(parameterized.getBaseType().asParameterizedByWildcards());
+    return uiFactories.get(forType);
   }
 
   /**
@@ -178,13 +150,14 @@
   }
 
   /**
-   * Scans the owner class to find all methods annotated with @UiFactory, and puts them in
-   * {@link #uiFactories}.
+   * Scans the owner class to find all methods annotated with @UiFactory, and
+   * puts them in {@link #uiFactories}.
    *
    * @param ownerType the type of the owner class
    * @throws UnableToCompleteException
    */
-  private void findUiFactories(JClassType ownerType) throws UnableToCompleteException {
+  private void findUiFactories(JClassType ownerType)
+      throws UnableToCompleteException {
     JMethod[] methods = ownerType.getMethods();
     for (JMethod method : methods) {
       if (method.isAnnotationPresent(UiFactory.class)) {
@@ -195,6 +168,11 @@
               + method.getName());
         }
         
+        JParameterizedType paramType = factoryType.isParameterized();
+        if (paramType != null) {
+          factoryType = paramType.getRawType();
+        }
+
         if (uiFactories.containsKey(factoryType)) {
           logger.die("Duplicate factory in class "
               + method.getEnclosingType().getName() + " for type "
@@ -212,15 +190,6 @@
     }
   }
 
-  private void findRawUiFactories() {
-    for (Entry<JClassType, JMethod> entry : uiFactories.entrySet()) {
-      JParameterizedType parameterizedType = entry.getKey().isParameterized();
-      if (parameterizedType != null) {
-        uiFactoriesForRawTypes.put(parameterizedType.getRawType(), entry.getValue());
-      }
-    }
-  }
-
   /**
    * Scans the owner class to find all fields annotated with @UiField, and puts
    * them in {@link #uiFields} and {@link #uiFieldTypes}.
diff --git a/user/test/com/google/gwt/uibinder/rebind/model/OwnerClassTest.java b/user/test/com/google/gwt/uibinder/rebind/model/OwnerClassTest.java
index d72aea9..8e1293f 100644
--- a/user/test/com/google/gwt/uibinder/rebind/model/OwnerClassTest.java
+++ b/user/test/com/google/gwt/uibinder/rebind/model/OwnerClassTest.java
@@ -20,9 +20,7 @@
 import com.google.gwt.core.ext.typeinfo.JClassType;
 import com.google.gwt.core.ext.typeinfo.JMethod;
 import com.google.gwt.core.ext.typeinfo.JParameter;
-import com.google.gwt.core.ext.typeinfo.JParameterizedType;
 import com.google.gwt.core.ext.typeinfo.JType;
-import com.google.gwt.core.ext.typeinfo.JWildcardType.BoundType;
 import com.google.gwt.core.ext.typeinfo.TypeOracle;
 import com.google.gwt.dev.CompilerContext;
 import com.google.gwt.dev.javac.CompilationState;
@@ -173,6 +171,20 @@
           }
         },
         new MockJavaResource(
+            "com.google.gwt.uibinder.rebind.model.WildcardWidgetFactory") {
+          @Override
+          public CharSequence getContent() {
+            StringBuffer code = new StringBuffer();
+            code.append("package com.google.gwt.uibinder.rebind.model;\n");
+            code.append("import com.google.gwt.uibinder.client.UiFactory;\n");
+            code.append("public class WildcardWidgetFactory {");
+            code.append("  @UiFactory");
+            code.append("  Abstract<?> createOne() { return null; }");
+            code.append("}\n");
+            return code;
+          }
+        },
+        new MockJavaResource(
             "com.google.gwt.uibinder.rebind.model.ParamterizedWidgetFactory") {
           @Override
           public CharSequence getContent() {
@@ -195,8 +207,6 @@
             code.append("import com.google.gwt.uibinder.client.UiFactory;\n");
             code.append("public class TooManyGenerics {");
             code.append("  @UiFactory");
-            code.append("  Abstract create() { return null; }");
-            code.append("  @UiFactory");
             code.append("  Abstract<?> createSomething() { return null; }");
             code.append("  @UiFactory");
             code.append("  Abstract<String> createStringThing() { return null; }");
@@ -297,54 +307,36 @@
   public void testParameterizedWidgets() throws UnableToCompleteException {
     JClassType ownerType = types.findType("com.google.gwt.uibinder.rebind.model.ParamterizedWidgetFactory");
     JClassType abstractType = types.findType("com.google.gwt.uibinder.rebind.model.Abstract");
-    JClassType abstractTypeWildcard = createParameterizedWithWildcard(abstractType);
-    JClassType abstractTypeString = createParameterizedWithString(abstractType);
-    JClassType abstractTypeObject = createParameterizedWithObject(abstractType);
-    OwnerClass ownerClass = new OwnerClass(ownerType, MortalLogger.NULL, uiBinderCtx);
+    OwnerClass ownerClass = new OwnerClass(ownerType, MortalLogger.NULL,
+        uiBinderCtx);
 
     JMethod expected = ownerType.findMethod("createOne", new JType[] {});
+    JMethod uiFactoryMethod = ownerClass.getUiFactoryMethod(abstractType);
 
-    assertEquals(expected, ownerClass.getUiFactoryMethod(abstractType));
-    assertEquals(expected, ownerClass.getUiFactoryMethod(abstractTypeWildcard));
-    assertEquals(expected, ownerClass.getUiFactoryMethod(abstractTypeString));
-    assertEquals(null, ownerClass.getUiFactoryMethod(abstractTypeObject));
+    assertEquals(expected, uiFactoryMethod);
   }
 
-  public void testOwnerClass_uiFactoryWithMoreGenerics()
-      throws UnableToCompleteException {
-    JClassType ownerType = types.findType("com.google.gwt.uibinder.rebind.model.TooManyGenerics");
+  public void testWildcardWidgets() throws UnableToCompleteException {
+    JClassType ownerType = types.findType("com.google.gwt.uibinder.rebind.model.WildcardWidgetFactory");
     JClassType abstractType = types.findType("com.google.gwt.uibinder.rebind.model.Abstract");
-    JClassType abstractTypeWildcard = createParameterizedWithWildcard(abstractType);
-    JClassType abstractTypeString = createParameterizedWithString(abstractType);
-    JClassType abstractTypeObject = createParameterizedWithObject(abstractType);
-    OwnerClass ownerClass = new OwnerClass(ownerType, MortalLogger.NULL, uiBinderCtx);
+    OwnerClass ownerClass = new OwnerClass(ownerType, MortalLogger.NULL,
+        uiBinderCtx);
 
-    JMethod expected;
+    JMethod expected = ownerType.findMethod("createOne", new JType[] {});
+    JMethod uiFactoryMethod = ownerClass.getUiFactoryMethod(abstractType);
 
-    expected = ownerType.findMethod("create", new JType[] {});
-    assertEquals(expected, ownerClass.getUiFactoryMethod(abstractType));
-    assertEquals(expected, ownerClass.getUiFactoryMethod(abstractTypeObject));
-
-    expected = ownerType.findMethod("createSomething", new JType[] {});
-    assertEquals(expected, ownerClass.getUiFactoryMethod(abstractTypeWildcard));
-
-    expected = ownerType.findMethod("createStringThing", new JType[] {});
-    assertEquals(expected, ownerClass.getUiFactoryMethod(abstractTypeString));
+    assertEquals(expected, uiFactoryMethod);
   }
 
-  private JParameterizedType createParameterizedWithString(JClassType abstractType) {
-    return types.getParameterizedType(
-        abstractType.isGenericType(), new JClassType[] {types.findType("java.lang.String")});
-  }
+  public void testHowSuckyWeReallyAreWithGenerics() {
+    JClassType ownerType = types.findType("com.google.gwt.uibinder.rebind.model.TooManyGenerics");
 
-  private JParameterizedType createParameterizedWithObject(JClassType abstractType) {
-    return types.getParameterizedType(
-        abstractType.isGenericType(), new JClassType[] {types.getJavaLangObject()});
-  }
-
-  private JParameterizedType createParameterizedWithWildcard(JClassType abstractType) {
-    return types.getParameterizedType(abstractType.isGenericType(),
-        new JClassType[] {types.getWildcardType(BoundType.UNBOUND, types.getJavaLangObject())});
+    try {
+      new OwnerClass(ownerType, MortalLogger.NULL, uiBinderCtx);
+      fail();
+    } catch (UnableToCompleteException e) {
+      /* pass */
+    }
   }
 
   public void testOwnerClass_uiFactoryBadType() {
diff --git a/user/test/com/google/gwt/uibinder/test/client/Constants.java b/user/test/com/google/gwt/uibinder/test/client/Constants.java
index 6cec350..4d3f017 100644
--- a/user/test/com/google/gwt/uibinder/test/client/Constants.java
+++ b/user/test/com/google/gwt/uibinder/test/client/Constants.java
@@ -18,9 +18,6 @@
 import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.safehtml.shared.SafeHtmlUtils;
 
-import java.util.Arrays;
-import java.util.List;
-
 /**
  * Used to test static imports in UiBinder templates.
  */
@@ -46,8 +43,6 @@
 
   public static String CONST_FOO = "Foo";
 
-  public static List<String> CONST_LIST = Arrays.asList("1", "2", "3");
-
   public SafeHtml getSafeHtml() {
     return SafeHtmlUtils.fromSafeConstant("<b>This text should be bold!</b>");
   }
diff --git a/user/test/com/google/gwt/uibinder/test/client/MyValueListBox.java b/user/test/com/google/gwt/uibinder/test/client/MyValueListBox.java
deleted file mode 100644
index bcf7133..0000000
--- a/user/test/com/google/gwt/uibinder/test/client/MyValueListBox.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2013 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.uibinder.test.client;
-
-import com.google.gwt.user.client.ui.ValueListBox;
-
-/**
- * A custom widget that add type parameter to its base class.
- */
-class MyValueListBox extends ValueListBox<String> {
-}
diff --git a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
index 2fd12ba..84f1d77 100644
--- a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
+++ b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
@@ -65,7 +65,6 @@
 import com.google.gwt.user.client.ui.Tree;
 import com.google.gwt.user.client.ui.TreeItem;
 import com.google.gwt.user.client.ui.ValueLabel;
-import com.google.gwt.user.client.ui.ValueListBox;
 import com.google.gwt.user.client.ui.Widget;
 
 import java.util.List;
@@ -199,8 +198,8 @@
   @UiField DateLabel myDateLabel3;
   @UiField NumberLabel<Float> myNumberLabel;
   @UiField NumberLabel<Float> myNumberLabel2;
-  @UiField(provided = true)
-  Renderer<Double> doubleRenderer = DoubleRenderer.instance();
+  @UiField(provided = true) @SuppressWarnings("rawtypes")
+  Renderer doubleRenderer = DoubleRenderer.instance();
   @UiField ValueLabel<Double> myValueLabel;
   @UiField DoubleBox myDoubleBox;
   @SuppressWarnings("rawtypes")
@@ -213,7 +212,6 @@
   @UiField HTML htmlWithComputedSafeHtml;
   @UiField HTML htmlWithComputedText;
   @UiField Label labelWithComputedText;
-  @UiField ValueListBox<String> myValueListBox;
 
   ValueChangeEvent<Double> doubleValueChangeEvent;
   @UiHandler("myDoubleBox")
diff --git a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml
index fd25232..5eea996 100644
--- a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml
+++ b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml
@@ -84,10 +84,6 @@
   Tests the static import of a single constant into the local namespace.
 </ui:import>
 
-<ui:import field='com.google.gwt.uibinder.test.client.Constants.CONST_LIST'>
-  Tests the static import of a single constant with generics.
-</ui:import>
-
 <ui:import field='com.google.gwt.uibinder.test.client.Constants.Inner.*'>
   Tests the static import of multiple constants into the local namespace.
 </ui:import>
@@ -702,9 +698,6 @@
 
   <img src="{values.aUrl}" ui:field='myImage'/>
   
-  <gwt:ValueListBox ui:field="myValueListBox" acceptableValues="{CONST_LIST}" />
-  <demo:MyValueListBox acceptableValues="{CONST_LIST}" />
-
   <gwt:HTML ui:field='htmlWithComputedSafeHtml'><ui:safehtml from="{constants.getSafeHtml}" /></gwt:HTML>
   <gwt:HTML ui:field='htmlWithComputedText'><ui:text from="{constants.getText}" /></gwt:HTML>
   <gwt:Label ui:field='labelWithComputedText'><ui:text from="{constants.getText}"/></gwt:Label>