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