Revision: 7940
Author: [email protected]
Date: Mon Apr 19 07:56:12 2010
Log: Allows owner class to provide a parameterized type.

Fixes incorrect direction of isAssignable check when using @UiField(provided = true)

Also deletes some unused code: declareDomField no longer uses its element param, because ensureCurrentFieldAttached no longer uses its arg, etc.

Review at http://gwt-code-reviews.appspot.com/359801

Review by: [email protected]
http://code.google.com/p/google-web-toolkit/source/detail?r=7940

Added:
 /trunk/user/test/com/google/gwt/uibinder/test/client/Specific.java
Modified:
/trunk/user/src/com/google/gwt/uibinder/elementparsers/FieldInterpreter.java /trunk/user/src/com/google/gwt/uibinder/elementparsers/WidgetInterpreter.java
 /trunk/user/src/com/google/gwt/uibinder/rebind/AbstractFieldWriter.java
 /trunk/user/src/com/google/gwt/uibinder/rebind/FieldWriter.java
/trunk/user/src/com/google/gwt/uibinder/rebind/FieldWriterOfExistingType.java
 /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
/trunk/user/test/com/google/gwt/uibinder/test/client/ParameterizedWidget.java /trunk/user/test/com/google/gwt/uibinder/test/client/ParameterizedWidget.ui.xml /trunk/user/test/com/google/gwt/uibinder/test/client/TestParameterizedWidgets.java

=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/uibinder/test/client/Specific.java Mon Apr 19 07:56:12 2010
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010 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;
+
+/**
+ * A specific implementation of {...@link Abstract}, used to test generics in
+ * UiBinder. See {...@link ParameterizedWidget}.
+ *
+ * @param <T> a param type
+ */
+public class Specific<T> extends Abstract<T> {
+
+}
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/elementparsers/FieldInterpreter.java Fri Apr 2 06:00:38 2010 +++ /trunk/user/src/com/google/gwt/uibinder/elementparsers/FieldInterpreter.java Mon Apr 19 07:56:12 2010
@@ -37,7 +37,7 @@
       throws UnableToCompleteException {
     String fieldName = writer.declareFieldIfNeeded(elem);
     if (fieldName != null) {
-      String token = writer.declareDomField(fieldName, element);
+      String token = writer.declareDomField(fieldName);

       if (elem.hasAttribute("id")) {
         writer.die(String.format(
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/elementparsers/WidgetInterpreter.java Fri Apr 2 06:00:38 2010 +++ /trunk/user/src/com/google/gwt/uibinder/elementparsers/WidgetInterpreter.java Mon Apr 19 07:56:12 2010
@@ -75,7 +75,7 @@
       // we'll reuse ids for any template rendered more than once.
       String idHolder = uiWriter.declareDomIdHolder();
       String childField = uiWriter.parseElementToField(elem);
-      uiWriter.ensureFieldAttached(fieldName);
+      uiWriter.ensureCurrentFieldAttached();

       String elementPointer = idHolder + "Element";
       uiWriter.addInitStatement(
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/AbstractFieldWriter.java Wed Nov 11 22:08:47 2009 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/AbstractFieldWriter.java Mon Apr 19 07:56:12 2010
@@ -71,21 +71,6 @@
   }

   public void setInitializer(String initializer) {
-    if (this.initializer != null) {
-      throw new IllegalStateException(String.format(
-          "Second attempt to set initializer for field \"%s\", "
- + "from \"%s\" to \"%s\"", name, this.initializer, initializer));
-    }
-    setInitializerMaybe(initializer);
-  }
-
-  @Deprecated
-  public void setInitializerMaybe(String initializer) {
- if (this.initializer != null && !this.initializer.equals(initializer)) {
-      throw new IllegalStateException(String.format(
-          "Attempt to change initializer for field \"%s\", "
- + "from \"%s\" to \"%s\"", name, this.initializer, initializer));
-    }
     this.initializer = initializer;
   }

=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/FieldWriter.java Wed Dec 2 10:02:31 2009 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/FieldWriter.java Mon Apr 19 07:56:12 2010
@@ -74,25 +74,12 @@
    * Used to provide an initializer string to use instead of a
* {...@link com.google.gwt.core.client.GWT#create()} call. Note that this is an * RHS expression. Don't include the leading '=', and don't end it with ';'.
-   * <p>
-   * TODO(rjrjr) Should be able to make this a constructor argument when
-   * BundleAttributeParser dies.
    *
    * @throws UnableToCompleteException
    * @throws IllegalStateException on second attempt to set the initializer
    */
   void setInitializer(String initializer);

-  /**
-   * @deprecated needed only by
- * {...@link com.google.gwt.uibinder.attributeparsers.BundleAttributeParser}
-   *             , which will die soon
- * @throws IllegalStateException if initializer in a later call doesn't match
-   *           earlier call
-   */
-  @Deprecated
-  void setInitializerMaybe(String initializer);
-
   /**
    * Write the field delcaration.
    */
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/FieldWriterOfExistingType.java Wed Nov 11 22:08:47 2009 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/FieldWriterOfExistingType.java Mon Apr 19 07:56:12 2010
@@ -16,6 +16,7 @@
 package com.google.gwt.uibinder.rebind;

 import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.JGenericType;

 /**
* Implementation of FieldWriter for fields whose type already exists (that is,
@@ -31,6 +32,12 @@
     if (type == null) {
       throw new IllegalArgumentException("type cannot be null");
     }
+
+    JGenericType genericType = type.isGenericType();
+    if (genericType != null) {
+      type = genericType.getRawType();
+    }
+
     this.type = type;
   }

=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java Fri Apr 2 06:00:38 2010 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java Mon Apr 19 07:56:12 2010
@@ -129,8 +129,7 @@
    * @param type the base type
    * @return a breadth-first collection of its type hierarchy
    */
-  static Iterable<JClassType> getClassHierarchyBreadthFirst(
-      JClassType type) {
+ static Iterable<JClassType> getClassHierarchyBreadthFirst(JClassType type) {
     LinkedList<JClassType> list = new LinkedList<JClassType>();
     LinkedList<JClassType> q = new LinkedList<JClassType>();

@@ -324,13 +323,10 @@
    * call and assign the Element instance to its field.
    *
    * @param fieldName The name of the field being declared
- * @param parentElementExpression an expression to be evaluated at runtime,
-   *          which will return an Element that is an ancestor of this one
-   *          (needed by the getElementById call mentioned above).
    */
- public String declareDomField(String fieldName, String parentElementExpression)
+  public String declareDomField(String fieldName)
       throws UnableToCompleteException {
-    ensureAttached(parentElementExpression);
+    ensureAttached();
     String name = declareDomIdHolder();
     setFieldInitializer(fieldName, "null");
     addInitStatement(
@@ -444,10 +440,9 @@
   /**
    * Ensure that the specified element is attached to the DOM.
    *
-   * @param element variable name of element to be attached
    * @see #beginAttachedSection(String)
    */
-  public void ensureAttached(String element) {
+  public void ensureAttached() {
     String attachSectionElement = attachSectionElements.getFirst();
     if (!attachedVars.containsKey(attachSectionElement)) {
       String attachedVar = "attachRecord" + nextAttachVar;
@@ -464,11 +459,10 @@
* an object that responds to Element getElement(). Convenience wrapper for
    * {...@link ensureAttached}<code>(field + ".getElement()")</code>.
    *
-   * @param field variable name of the field to be attached
    * @see #beginAttachedSection(String)
    */
-  public void ensureFieldAttached(String field) {
-    ensureAttached(field + ".getElement()");
+  public void ensureCurrentFieldAttached() {
+    ensureAttached();
   }

   /**
@@ -723,7 +717,7 @@
    *
    * @throws UnableToCompleteException
    */
- private void ensureAttachmentCleanedUp() throws UnableToCompleteException {
+  private void ensureAttachmentCleanedUp() {
     if (!attachSectionElements.isEmpty()) {
       throw new IllegalStateException("Attachments not cleaned up: "
           + attachSectionElements);
@@ -856,15 +850,34 @@
       throws UnableToCompleteException {
     JClassType fieldType = ownerField.getType().getRawType();

-    if (!templateClass.isAssignableTo(fieldType)) {
-      die("Template field and owner field types don't match: %s != %s",
-          templateClass.getQualifiedSourceName(),
-          fieldType.getQualifiedSourceName());
-    }
-
     if (!ownerField.isProvided()) {
+      /*
+ * Normally check that the type the template created can be slammed into
+       * the @UiField annotated field in the owning class
+       */
+      if (!templateClass.isAssignableTo(fieldType)) {
+        die(
+ "In @UiField %s, template field and owner field types don't match: %s is not assignable to %s",
+            ownerField.getName(), templateClass.getQualifiedSourceName(),
+            fieldType.getQualifiedSourceName());
+      }
+      /*
+       * And initialize the field
+       */
       niceWriter.write("owner.%1$s = %2$s;", ownerField.getName(),
           templateField);
+    } else {
+      /*
+ * But with @UiField(provided=true) the user builds it, so reverse the
+       * direction of the assignability check and do no init.
+       */
+      if (!fieldType.isAssignableTo(templateClass)) {
+        die(
+ "In UiField(provided = true) %s, template field and field types don't match: "
+                + "@UiField(provided=true)%s is not assignable to %s",
+            ownerField.getName(), fieldType.getQualifiedSourceName(),
+            templateClass.getQualifiedSourceName());
+      }
     }
   }

@@ -979,7 +992,8 @@

     // createAndBindUi method
     w.write("public %s createAndBindUi(final %s owner) {",
- uiRootType.getParameterizedQualifiedSourceName(), uiOwnerType.getParameterizedQualifiedSourceName());
+        uiRootType.getParameterizedQualifiedSourceName(),
+        uiOwnerType.getParameterizedQualifiedSourceName());
     w.indent();
     w.newline();

@@ -1010,7 +1024,9 @@

   private void writeClassOpen(IndentedWriter w) {
w.write("public class %s implements UiBinder<%s, %s>, %s {", implClassName, - uiRootType.getParameterizedQualifiedSourceName(), uiOwnerType.getParameterizedQualifiedSourceName(), baseClass.getParameterizedQualifiedSourceName());
+        uiRootType.getParameterizedQualifiedSourceName(),
+        uiOwnerType.getParameterizedQualifiedSourceName(),
+        baseClass.getParameterizedQualifiedSourceName());
     w.indent();
   }

@@ -1039,11 +1055,9 @@
         String fieldName = ownerField.getName();
         FieldWriter fieldWriter = fieldManager.lookup(fieldName);

-        // TODO(hermes) This can be null due to http://b/1836504. If that
-        // is fixed properly, a null fieldWriter will be an error
-        // (would that be a user error or a runtime error? Not sure)
+        // TODO why can this be null?
         if (fieldWriter != null) {
-          fieldManager.lookup(fieldName).setInitializerMaybe(
+          fieldManager.lookup(fieldName).setInitializer(
               formatCode("owner.%1$s", fieldName));
         }
       }
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/client/ParameterizedWidget.java Fri Jan 15 17:40:59 2010 +++ /trunk/user/test/com/google/gwt/uibinder/test/client/ParameterizedWidget.java Mon Apr 19 07:56:12 2010
@@ -31,16 +31,16 @@

   static final Binder binder = GWT.create(Binder.class);

-  @UiField
-  Abstract<?> a;
-
+  @UiField Abstract<?> fromFactory;
+  @UiField(provided = true) Specific<T> provided = new Specific<T>();
+
   ParameterizedWidget() {
     initWidget(binder.createAndBindUi(this));
   }

   @UiFactory
-  Abstract<?> createA() {
-    return new Abstract<String>() {
+  Abstract<T> createA() {
+    return new Abstract<T>() {
     };
   }
 }
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/client/ParameterizedWidget.ui.xml Fri Jan 15 17:40:59 2010 +++ /trunk/user/test/com/google/gwt/uibinder/test/client/ParameterizedWidget.ui.xml Mon Apr 19 07:56:12 2010
@@ -1,4 +1,8 @@
 <ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
-    xmlns:t="urn:import:com.google.gwt.uibinder.test.client">
- <t:Abstract ui:field='a'></t:Abstract>
+  xmlns:g="urn:import:com.google.gwt.user.client.ui"
+  xmlns:t="urn:import:com.google.gwt.uibinder.test.client">
+  <g:FlowPanel>
+    <t:Abstract ui:field='fromFactory' />
+    <t:Abstract ui:field='provided' />
+  </g:FlowPanel>
 </ui:UiBinder>
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/client/TestParameterizedWidgets.java Fri Jan 15 17:40:59 2010 +++ /trunk/user/test/com/google/gwt/uibinder/test/client/TestParameterizedWidgets.java Mon Apr 19 07:56:12 2010
@@ -28,6 +28,6 @@

   public void testHappy() {
     ParameterizedWidget<String> ui = new ParameterizedWidget<String>();
-    assertNotNull(ui.a);
+    assertNotNull(ui.fromFactory);
   }
 }

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to