Revision: 6715 Author: [email protected] Date: Thu Nov 5 13:01:52 2009 Log: Merges tr...@6714 into releases/2.0 Fix DockLayoutPanelParser bad code gen svn merge --ignore-ancestry -c r6714 https://google-web-toolkit.googlecode.com/svn/trunk .
http://code.google.com/p/google-web-toolkit/source/detail?r=6715 Added: /releases/2.0/user/src/com/google/gwt/uibinder/rebind/W3cDomHelper.java /releases/2.0/user/test/com/google/gwt/uibinder/parsers/DockLayoutPanelParserTest.java /releases/2.0/user/test/com/google/gwt/uibinder/test/UiJavaResources.java Deleted: /releases/2.0/user/test/com/google/gwt/uibinder/rebind/DocumentTestHelp.java Modified: /releases/2.0/branch-info.txt /releases/2.0/user/src/com/google/gwt/uibinder/parsers/DockLayoutPanelParser.java /releases/2.0/user/src/com/google/gwt/uibinder/rebind/AbstractFieldWriter.java /releases/2.0/user/src/com/google/gwt/uibinder/rebind/AttributeParsers.java /releases/2.0/user/src/com/google/gwt/uibinder/rebind/FieldManager.java /releases/2.0/user/src/com/google/gwt/uibinder/rebind/FieldWriter.java /releases/2.0/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java /releases/2.0/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java /releases/2.0/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java /releases/2.0/user/src/com/google/gwt/uibinder/rebind/XMLElementProvider.java /releases/2.0/user/src/com/google/gwt/uibinder/rebind/XMLElementProviderImpl.java /releases/2.0/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java /releases/2.0/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java ======================================= --- /dev/null +++ /releases/2.0/user/src/com/google/gwt/uibinder/rebind/W3cDomHelper.java Thu Nov 5 13:01:52 2009 @@ -0,0 +1,78 @@ +/* + * Copyright 2009 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.rebind; + +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +/** + * Simplifies instantiation of the w3c XML parser, in just the style + * that UiBinder likes it. Used by both prod and test. + */ +public class W3cDomHelper { + private final DocumentBuilderFactory factory; + private final DocumentBuilder builder; + + public W3cDomHelper() { + factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + factory.setExpandEntityReferences(true); + try { + builder = factory.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new RuntimeException(e); + } + builder.setEntityResolver(new GwtResourceEntityResolver()); + } + + /** + * Creates an XML document model with the given contents. Nice for testing. + * + * @param string the document contents + */ + public Document documentFor(String string) throws SAXException, + IOException { + return builder.parse(new ByteArrayInputStream(string.getBytes())); + } + + public Document documentFor(URL url) throws SAXParseException { + try { + InputStream stream = url.openStream(); + InputSource input = new InputSource(stream); + input.setSystemId(url.toExternalForm()); + + return builder.parse(input); + } catch (SAXParseException e) { + // Let SAXParseExceptions through. + throw e; + } catch (SAXException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} ======================================= --- /dev/null +++ /releases/2.0/user/test/com/google/gwt/uibinder/parsers/DockLayoutPanelParserTest.java Thu Nov 5 13:01:52 2009 @@ -0,0 +1,285 @@ +/* + * Copyright 2009 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.parsers; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.TypeOracle; +import com.google.gwt.dev.javac.CompilationState; +import com.google.gwt.dev.javac.impl.MockJavaResource; +import com.google.gwt.dev.javac.impl.MockResourceOracle; +import com.google.gwt.dev.util.collect.Lists; +import com.google.gwt.uibinder.rebind.AttributeParsers; +import com.google.gwt.uibinder.rebind.FieldManager; +import com.google.gwt.uibinder.rebind.FieldWriter; +import com.google.gwt.uibinder.rebind.MortalLogger; +import com.google.gwt.uibinder.rebind.UiBinderWriter; +import com.google.gwt.uibinder.rebind.W3cDomHelper; +import com.google.gwt.uibinder.rebind.XMLElement; +import com.google.gwt.uibinder.rebind.XMLElementProvider; +import com.google.gwt.uibinder.rebind.XMLElementProviderImpl; +import com.google.gwt.uibinder.rebind.messages.MessagesWriter; +import com.google.gwt.uibinder.test.UiJavaResources; +import com.google.gwt.user.client.ui.DockLayoutPanel; + +import junit.framework.TestCase; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * A unit test. Guess what of. + */ +public class DockLayoutPanelParserTest extends TestCase { + private static class MyUiBinderWriter extends UiBinderWriter { + final List<String> statements = new ArrayList<String>(); + String died; + + public MyUiBinderWriter(JClassType baseClass, String implClassName, + String templatePath, TypeOracle oracle, MortalLogger logger, + FieldManager fieldManager, MessagesWriter messagesWriter) + throws UnableToCompleteException { + super(baseClass, implClassName, templatePath, oracle, logger, + fieldManager, messagesWriter); + } + + @Override + public void addStatement(String format, Object... args) { + statements.add(String.format(format, args)); + } + + @Override + public String parseElementToField(XMLElement elem) + throws UnableToCompleteException { + return elem.consumeOpeningTag(); + } + + @Override + public void die(String message, Object... params) + throws UnableToCompleteException { + noteDeath(String.format(message, params)); + super.die(message, params); + } + + @Override + public void die(String message) throws UnableToCompleteException { + noteDeath(message); + super.die(message); + } + + /** Handy place to set a break point and inspect suicide notes. */ + void noteDeath(String s) { + died = s; + } + } + + private static final W3cDomHelper docHelper = new W3cDomHelper(); + private static final String BINDER_URI = "binderUri"; + + private static final String fieldName = "fieldName"; + + // TODO(rjrjr) Move this to JavaResourceBase. Have to do it atomically for + // all other tests that define their own Enum. + private static final MockJavaResource ENUM = new MockJavaResource( + "java.lang.Enum") { + @Override + protected CharSequence getContent() { + StringBuffer code = new StringBuffer(); + code.append("package java.lang;\n"); + code.append("public abstract class Enum<E extends Enum<E>> {\n"); + code.append(" protected Enum(String name, int ordinal) {}\n"); + code.append("}\n"); + return code; + } + }; + private static final MockJavaResource MY_UI_JAVA = new MockJavaResource( + "my.Ui") { + @Override + protected CharSequence getContent() { + StringBuffer code = new StringBuffer(); + code.append("package my;\n"); + code.append("import com.google.gwt.user.client.ui.Widget;\n"); + code.append("public class Ui {\n"); + code.append(" public interface BaseClass extends " + + "com.google.gwt.uibinder.client.UiBinder<Widget, BaseClass> {}\n"); + code.append("}\n"); + return code; + } + }; + + private TypeOracle types; + private XMLElementProvider elemProvider; + private Document doc; + private MyUiBinderWriter writer; + private DockLayoutPanelParser parser; + private JClassType dockLayoutPanelType; + private FieldManager fieldManager; + + @Override + public void setUp() throws Exception { + super.setUp(); + + MockResourceOracle resources = new MockResourceOracle(getUiResources()); + CompilationState state = new CompilationState(TreeLogger.NULL, resources); + types = state.getTypeOracle(); + dockLayoutPanelType = types.findType("com.google.gwt.user.client.ui.DockLayoutPanel"); + + elemProvider = new XMLElementProviderImpl(new AttributeParsers(), null, + types, MortalLogger.NULL); + + fieldManager = new FieldManager(MortalLogger.NULL); + fieldManager.registerField( + types.findType(DockLayoutPanel.class.getCanonicalName()), fieldName); + + String templatePath = "TemplatePath.ui.xml"; + String implName = "ImplClass"; + JClassType baseType = types.findType("my.Ui.BaseClass"); + MessagesWriter messages = new MessagesWriter(BINDER_URI, MortalLogger.NULL, + templatePath, baseType.getPackage().getName(), implName); + + writer = new MyUiBinderWriter(baseType, implName, templatePath, types, + MortalLogger.NULL, fieldManager, messages); + parser = new DockLayoutPanelParser(); + } + + public void testHappy() throws UnableToCompleteException, SAXException, + IOException { + StringBuffer b = new StringBuffer(); + b.append("<ui:UiBinder xmlns:ui='" + BINDER_URI + "'"); + b.append(" xmlns:g='urn:import:com.google.gwt.user.client.ui'>"); + b.append(" <g:DockLayoutPanel unit='EM'>"); + b.append(" <g:north size='5'>"); + b.append(" <g:Label id='north'>north</g:Label>"); + b.append(" </g:north>"); + b.append(" <g:center>"); + b.append(" <g:Label id='center'>center</g:Label>"); + b.append(" </g:center>"); + b.append(" </g:DockLayoutPanel>"); + b.append("</ui:UiBinder>"); + + String[] expected = { + "fieldName.addNorth(<g:Label id='north'>, 5);", + "fieldName.add(<g:Label id='center'>);",}; + + parser.parse(getElem(b.toString()), fieldName, dockLayoutPanelType, writer); + FieldWriter w = fieldManager.lookup(fieldName); + assertEquals( + "new com.google.gwt.user.client.ui.DockLayoutPanel(com.google.gwt.dom.client.Style.Unit.EM)", + w.getInitializer()); + + Iterator<String> i = writer.statements.iterator(); + for (String e : expected) { + assertEquals(e, i.next()); + } + assertFalse(i.hasNext()); + assertNull(writer.died); + } + + public void testNiceCenter() throws UnableToCompleteException, SAXException, + IOException { + StringBuffer b = new StringBuffer(); + b.append("<ui:UiBinder xmlns:ui='" + BINDER_URI + "'"); + b.append(" xmlns:g='urn:import:com.google.gwt.user.client.ui'>"); + b.append(" <g:DockLayoutPanel unit='EM'>"); + b.append(" <g:center>"); + b.append(" <g:Label id='center'>center</g:Label>"); + b.append(" </g:center>"); + b.append(" <g:north size='5'>"); + b.append(" <g:Label id='north'>north</g:Label>"); + b.append(" </g:north>"); + b.append(" </g:DockLayoutPanel>"); + b.append("</ui:UiBinder>"); + + String[] expected = { + "fieldName.addNorth(<g:Label id='north'>, 5);", + "fieldName.add(<g:Label id='center'>);",}; + + parser.parse(getElem(b.toString()), fieldName, dockLayoutPanelType, writer); + FieldWriter w = fieldManager.lookup(fieldName); + assertEquals( + "new com.google.gwt.user.client.ui.DockLayoutPanel(com.google.gwt.dom.client.Style.Unit.EM)", + w.getInitializer()); + + Iterator<String> i = writer.statements.iterator(); + for (String e : expected) { + assertEquals(e, i.next()); + } + assertFalse(i.hasNext()); + } + + public void testTooManyCenters() throws SAXException, IOException { + StringBuffer b = new StringBuffer(); + b.append("<ui:UiBinder xmlns:ui='" + BINDER_URI + "'"); + b.append(" xmlns:g='urn:import:com.google.gwt.user.client.ui'>"); + b.append(" <g:DockLayoutPanel unit='EM'>"); + b.append(" <g:center>"); + b.append(" <g:Label id='center'>center</g:Label>"); + b.append(" </g:center>"); + b.append(" <g:center>"); + b.append(" <g:Label id='centerAlso'>centaur</g:Label>"); + b.append(" </g:center>"); + b.append(" </g:DockLayoutPanel>"); + b.append("</ui:UiBinder>"); + + try { + parser.parse(getElem(b.toString()), fieldName, dockLayoutPanelType, + writer); + fail(); + } catch (UnableToCompleteException e) { + assertNotNull(writer.died); + } + } + + public void testBadChild() throws SAXException, IOException { + StringBuffer b = new StringBuffer(); + b.append("<ui:UiBinder xmlns:ui='" + BINDER_URI + "'"); + b.append(" xmlns:g='urn:import:com.google.gwt.user.client.ui'>"); + b.append(" <g:DockLayoutPanel unit='EM'>"); + b.append(" <g:west><foo/></g:west>"); + b.append(" </g:DockLayoutPanel>"); + b.append("</ui:UiBinder>"); + + try { + parser.parse(getElem(b.toString()), fieldName, dockLayoutPanelType, + writer); + fail(); + } catch (UnableToCompleteException e) { + assertNotNull(writer.died); + } + } + + MockJavaResource[] getUiResources() { + List<MockJavaResource> rtn = Lists.create(UiJavaResources.getUiResources()); + rtn.add(MY_UI_JAVA); + rtn.add(ENUM); + return rtn.toArray(new MockJavaResource[rtn.size()]); + } + + private XMLElement getElem(String string) throws SAXException, IOException { + doc = docHelper.documentFor(string); + Element w3cElem = (Element) doc.getDocumentElement().getElementsByTagName( + "g:DockLayoutPanel").item(0); + XMLElement elem = elemProvider.get(w3cElem); + return elem; + } +} ======================================= --- /dev/null +++ /releases/2.0/user/test/com/google/gwt/uibinder/test/UiJavaResources.java Thu Nov 5 13:01:52 2009 @@ -0,0 +1,112 @@ +/* + * Copyright 2009 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; + +import com.google.gwt.dev.javac.impl.JavaResourceBase; +import com.google.gwt.dev.javac.impl.MockJavaResource; +import com.google.gwt.dev.util.collect.Lists; + +import java.util.List; + +/** + * A paired down set of GWT widget Java source files for code generator testing. + */ +public class UiJavaResources { + + public static final MockJavaResource WIDGET = new MockJavaResource( + "com.google.gwt.user.client.ui.Widget") { + @Override + protected CharSequence getContent() { + StringBuffer code = new StringBuffer(); + code.append("package com.google.gwt.user.client.ui;\n"); + code.append("public class Widget {\n"); + code.append("}\n"); + return code; + } + }; + public static final MockJavaResource DOCK_LAYOUT_PANEL = new MockJavaResource( + "com.google.gwt.user.client.ui.DockLayoutPanel") { + @Override + protected CharSequence getContent() { + StringBuffer code = new StringBuffer(); + code.append("package com.google.gwt.user.client.ui;\n"); + code.append("public class DockLayoutPanel extends Widget {\n"); + code.append("}\n"); + return code; + } + }; + public static final MockJavaResource SPLIT_LAYOUT_PANEL = new MockJavaResource( + "com.google.gwt.user.client.ui.SplitLayoutPanel") { + @Override + protected CharSequence getContent() { + StringBuffer code = new StringBuffer(); + code.append("package com.google.gwt.user.client.ui;\n"); + code.append("public class SplitLayoutPanel extends DockLayoutPanel {\n"); + code.append("}\n"); + return code; + } + }; + public static final MockJavaResource LABEL = new MockJavaResource( + "com.google.gwt.user.client.ui.Label") { + @Override + protected CharSequence getContent() { + StringBuffer code = new StringBuffer(); + code.append("package com.google.gwt.user.client.ui;\n"); + code.append("public class Label extends Widget {\n"); + code.append("}\n"); + return code; + } + }; + public static final MockJavaResource UI_BINDER = new MockJavaResource( + "com.google.gwt.uibinder.client.UiBinder") { + @Override + protected CharSequence getContent() { + StringBuffer code = new StringBuffer(); + code.append("package com.google.gwt.uibinder.client;\n"); + code.append("public interface UiBinder<U, O> {\n"); + code.append("}\n"); + return code; + } + }; + public static final MockJavaResource STYLE = new MockJavaResource( + "com.google.gwt.dom.client.Style") { + @Override + protected CharSequence getContent() { + StringBuffer code = new StringBuffer(); + code.append("package com.google.gwt.dom.client;\n"); + code.append("public class Style {\n"); + code.append(" public enum Unit { PX, PT, EM };\n"); + code.append("}\n"); + return code; + } + }; + + /** + * @return a pale reflection of com.google.gwt.user.ui, plus + * {...@link JavaResourceBase#getStandardResources} + */ + public static MockJavaResource[] getUiResources() { + MockJavaResource[] base = JavaResourceBase.getStandardResources(); + List<MockJavaResource> rtn = Lists.create(base); + rtn.add(WIDGET); + rtn.add(DOCK_LAYOUT_PANEL); + rtn.add(SPLIT_LAYOUT_PANEL); + rtn.add(LABEL); + rtn.add(UI_BINDER); + rtn.add(STYLE); + return rtn.toArray(new MockJavaResource[rtn.size()]); + } +} ======================================= --- /releases/2.0/user/test/com/google/gwt/uibinder/rebind/DocumentTestHelp.java Thu Oct 29 22:34:03 2009 +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2007 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.rebind; - -import org.w3c.dom.Document; -import org.xml.sax.SAXException; - -import java.io.ByteArrayInputStream; -import java.io.IOException; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - -/** - * Support methods for testing uibinder. - */ -class DocumentTestHelp { - /** - * Creates an XML document model with the given contents. - * - * @param string the document contents - */ - public static Document documentForString(String string) - throws ParserConfigurationException, SAXException, IOException { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - factory.setExpandEntityReferences(true); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(new ByteArrayInputStream(string.getBytes())); - return doc; - } - - /** - * Not instantiable. - */ - private DocumentTestHelp() { - } -} ======================================= --- /releases/2.0/branch-info.txt Thu Nov 5 11:56:01 2009 +++ /releases/2.0/branch-info.txt Thu Nov 5 13:01:52 2009 @@ -380,3 +380,7 @@ tr...@6513 was merged into this branch Remove two unused imports svn merge --ignore-ancestry -c 6513 https://google-web-toolkit.googlecode.com/svn/trunk . + +tr...@6714 was merged into this branch + Fix DockLayoutPanelParser bad code gen + svn merge --ignore-ancestry -c r6714 https://google-web-toolkit.googlecode.com/svn/trunk . ======================================= --- /releases/2.0/user/src/com/google/gwt/uibinder/parsers/DockLayoutPanelParser.java Wed Nov 4 14:13:39 2009 +++ /releases/2.0/user/src/com/google/gwt/uibinder/parsers/DockLayoutPanelParser.java Thu Nov 5 13:01:52 2009 @@ -39,6 +39,16 @@ */ public class DockLayoutPanelParser implements ElementParser { + private static class CenterChild { + final String widgetName; + final XMLElement child; + + public CenterChild(XMLElement child, String widgetName) { + this.widgetName = widgetName; + this.child = child; + } + } + private static final Map<String, String> DOCK_NAMES = new HashMap<String, String>(); static { @@ -60,31 +70,44 @@ writer.setFieldInitializerAsConstructor(fieldName, writer.getOracle().findType(DockLayoutPanel.class.getName()), unit); } + + CenterChild center = null; // Parse children. for (XMLElement child : elem.consumeChildElements()) { // Make sure the element is one of the fixed set of valid directions. if (!isValidChildElement(elem, child)) { writer.die( - "In %1$s, child must be one of " + - "<%2$s:north>, <%2$s:south>, <%2$s:east>, <%2$s:west> or <%2$s:center>, " + - "but found %3$s", - elem, elem.getPrefix(), child); + "In %1$s, child must be one of " + + "<%2$s:north>, <%2$s:south>, <%2$s:east>, <%2$s:west> or <%2$s:center>, " + + "but found %3$s", elem, elem.getPrefix(), child); } // Consume the single widget element. XMLElement widget = child.consumeSingleChildElement(); - String childFieldName = writer.parseElementToField(widget); - - if (requiresSize(child)) { + if (!writer.isWidgetElement(widget)) { + writer.die("In %s, %s must contain a widget, but found %s", elem, child, + widget); + } + String widgetName = writer.parseElementToField(widget); + + if (child.getLocalName().equals("center")) { + if (center != null) { + writer.die("In %s, only one <%s:center> is allowed", elem, + elem.getPrefix()); + } + center = new CenterChild(child, widgetName); + } else { String size = child.consumeDoubleAttribute("size"); writer.addStatement("%s.%s(%s, %s);", fieldName, addMethodName(child), - childFieldName, size); - } else { - writer.addStatement("%s.%s(%s);", fieldName, addMethodName(child), - childFieldName); + widgetName, size); } } + + if (center != null) { + writer.addStatement("%s.%s(%s);", fieldName, addMethodName(center.child), + center.widgetName); + } } private String addMethodName(XMLElement elem) { @@ -102,8 +125,8 @@ private boolean isValidChildElement(XMLElement parent, XMLElement child) { String childNsUri = child.getNamespaceUri(); if (childNsUri == null) { - return false; - } + return false; + } if (!childNsUri.equals(parent.getNamespaceUri())) { return false; } @@ -113,8 +136,4 @@ // Made it through the gauntlet. return true; } - - private boolean requiresSize(XMLElement elem) { - return !elem.getLocalName().equals("center"); - } -} +} ======================================= --- /releases/2.0/user/src/com/google/gwt/uibinder/rebind/AbstractFieldWriter.java Mon Nov 2 12:44:54 2009 +++ /releases/2.0/user/src/com/google/gwt/uibinder/rebind/AbstractFieldWriter.java Thu Nov 5 13:01:52 2009 @@ -45,6 +45,10 @@ this.name = name; this.logger = logger; } + + public String getInitializer() { + return initializer; + } public void needs(FieldWriter f) { needs.add(f); ======================================= --- /releases/2.0/user/src/com/google/gwt/uibinder/rebind/AttributeParsers.java Wed Nov 4 11:35:50 2009 +++ /releases/2.0/user/src/com/google/gwt/uibinder/rebind/AttributeParsers.java Thu Nov 5 13:01:52 2009 @@ -24,7 +24,10 @@ import java.util.HashMap; import java.util.Map; -class AttributeParsers { +/** + * Managers access to all implementations of {...@link AttributeParser} + */ +public class AttributeParsers { private static final String DOUBLE = "double"; private static final String BOOLEAN = "boolean"; ======================================= --- /releases/2.0/user/src/com/google/gwt/uibinder/rebind/FieldManager.java Mon Nov 2 12:44:54 2009 +++ /releases/2.0/user/src/com/google/gwt/uibinder/rebind/FieldManager.java Thu Nov 5 13:01:52 2009 @@ -26,7 +26,7 @@ * This class handles all {...@link FieldWriter} instances created for the current * template. */ -class FieldManager { +public class FieldManager { private static final String DUPLICATE_FIELD_ERROR = "Duplicate declaration of field %1$s."; @@ -46,8 +46,8 @@ /** * Basic constructor just injects an oracle instance. */ - public FieldManager(MortalLogger logger2) { - this.logger = logger2; + public FieldManager(MortalLogger logger) { + this.logger = logger; } /** ======================================= --- /releases/2.0/user/src/com/google/gwt/uibinder/rebind/FieldWriter.java Mon Nov 2 12:44:54 2009 +++ /releases/2.0/user/src/com/google/gwt/uibinder/rebind/FieldWriter.java Thu Nov 5 13:01:52 2009 @@ -36,6 +36,8 @@ String getQualifiedSourceName(); + String getInitializer(); + /** * @return the type of this field, or null if this field is of a type that has * not yet been generated ======================================= --- /releases/2.0/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java Mon Nov 2 21:21:03 2009 +++ /releases/2.0/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java Thu Nov 5 13:01:52 2009 @@ -26,7 +26,11 @@ import com.google.gwt.uibinder.rebind.messages.MessagesWriter; import com.google.gwt.uibinder.rebind.model.ImplicitClientBundle; +import org.w3c.dom.Document; +import org.xml.sax.SAXParseException; + import java.io.PrintWriter; +import java.net.URL; /** * Generator for implementations of @@ -36,6 +40,8 @@ private static final String TEMPLATE_SUFFIX = ".ui.xml"; + static final String BINDER_URI = "urn:ui:com.google.gwt.uibinder"; + /** * Given a UiBinder interface, return the path to its ui.xml file, suitable * for any classloader to find it as a resource. @@ -103,18 +109,22 @@ } private void generateOnce(JClassType interfaceType, String implName, - PrintWriter binderPrintWrier, TreeLogger treeLogger, TypeOracle oracle, + PrintWriter binderPrintWriter, TreeLogger treeLogger, TypeOracle oracle, PrintWriterManager writerManager) - throws UnableToCompleteException { + throws UnableToCompleteException { MortalLogger logger = new MortalLogger(treeLogger); String templatePath = deduceTemplateFile(logger, interfaceType); + MessagesWriter messages = new MessagesWriter(BINDER_URI, logger, + templatePath, interfaceType.getPackage().getName(), implName); UiBinderWriter uiBinderWriter = new UiBinderWriter(interfaceType, implName, - templatePath, oracle, logger); - uiBinderWriter.parseDocument(binderPrintWrier); - - MessagesWriter messages = uiBinderWriter.getMessages(); + templatePath, oracle, logger, new FieldManager(logger), messages); + + Document doc = getW3cDoc(logger, templatePath); + + uiBinderWriter.parseDocument(doc, binderPrintWriter); + if (messages.hasMessages()) { messages.write(writerManager.makePrintWriterFor(messages.getMessagesClassName())); } @@ -124,4 +134,21 @@ writerManager.commit(); } -} + + private Document getW3cDoc(MortalLogger logger, String templatePath) + throws UnableToCompleteException { + URL url = UiBinderGenerator.class.getClassLoader().getResource(templatePath); + if (null == url) { + logger.die("Unable to find resource: " + templatePath); + } + + Document doc = null; + try { + doc = new W3cDomHelper().documentFor(url); + } catch (SAXParseException e) { + logger.die("Error parsing XML (line " + e.getLineNumber() + "): " + + e.getMessage(), e); + } + return doc; + } +} ======================================= --- /releases/2.0/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java Wed Nov 4 11:35:50 2009 +++ /releases/2.0/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java Thu Nov 5 13:01:52 2009 @@ -110,7 +110,7 @@ writer.die("Bad prefix on <%s:%s>? The root element must be in " + "xml namespace \"%s\" (usually with prefix \"ui:\"), " + "but this has prefix \"%s\"", elem.getPrefix(), - elem.getLocalName(), UiBinderWriter.BINDER_URI, elem.getPrefix()); + elem.getLocalName(), UiBinderGenerator.BINDER_URI, elem.getPrefix()); } if (!TAG.equals(elem.getLocalName())) { ======================================= --- /releases/2.0/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java Wed Nov 4 11:35:50 2009 +++ /releases/2.0/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java Thu Nov 5 13:01:52 2009 @@ -33,15 +33,9 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -import java.io.IOException; -import java.io.InputStream; + import java.io.PrintWriter; import java.io.StringWriter; -import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -50,10 +44,6 @@ import java.util.Locale; import java.util.Map; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; - /** * Writer for UiBinder generated classes. * @@ -64,7 +54,6 @@ */ @SuppressWarnings("deprecation") public class UiBinderWriter { - static final String BINDER_URI = "urn:ui:com.google.gwt.uibinder"; private static final String PACKAGE_URI_SCHEME = "urn:import:"; // TODO(rjrjr) Another place that we need a general anonymous field @@ -226,17 +215,17 @@ private final AttributeParsers attributeParsers; private final BundleAttributeParsers bundleParsers; - UiBinderWriter(JClassType baseClass, String implClassName, - String templatePath, TypeOracle oracle, MortalLogger logger) + public UiBinderWriter(JClassType baseClass, String implClassName, + String templatePath, TypeOracle oracle, MortalLogger logger, + FieldManager fieldManager, MessagesWriter messagesWriter) throws UnableToCompleteException { this.baseClass = baseClass; this.implClassName = implClassName; this.oracle = oracle; this.logger = logger; this.templatePath = templatePath; - - this.messages = new MessagesWriter(BINDER_URI, logger, templatePath, - baseClass.getPackage().getName(), this.implClassName); + this.fieldManager = fieldManager; + this.messages = messagesWriter; // Check for possible misuse 'GWT.create(UiBinder.class)' JClassType uibinderItself = @@ -267,7 +256,6 @@ bundleClass = new ImplicitClientBundle(baseClass.getPackage().getName(), this.implClassName, CLIENT_BUNDLE_FIELD, logger); handlerEvaluator = new HandlerEvaluator(ownerClass, logger, oracle); - fieldManager = new FieldManager(logger); attributeParsers = new AttributeParsers(); bundleParsers = new BundleAttributeParsers(oracle, gwtPrefix, logger, @@ -563,7 +551,7 @@ public boolean isBinderElement(XMLElement elem) { String uri = elem.getNamespaceUri(); - return uri != null && BINDER_URI.equals(uri); + return uri != null && UiBinderGenerator.BINDER_URI.equals(uri); } public boolean isWidgetElement(XMLElement elem) { @@ -659,23 +647,16 @@ * Entry point for the code generation logic. It generates the * implementation's superstructure, and parses the root widget (leading to all * of its children being parsed as well). + * @param doc TODO */ - void parseDocument(PrintWriter printWriter) throws UnableToCompleteException { - Document doc = null; - try { - doc = parseXmlResource(templatePath); - } catch (SAXParseException e) { - die("Error parsing XML (line " + e.getLineNumber() + "): " - + e.getMessage(), e); - } - + void parseDocument(Document doc, PrintWriter printWriter) throws UnableToCompleteException { JClassType uiBinderClass = getOracle().findType(UiBinder.class.getName()); if (!baseClass.isAssignableTo(uiBinderClass)) { die(baseClass.getName() + " must implement UiBinder"); } Element documentElement = doc.getDocumentElement(); - gwtPrefix = documentElement.lookupPrefix(BINDER_URI); + gwtPrefix = documentElement.lookupPrefix(UiBinderGenerator.BINDER_URI); XMLElement elem = new XMLElementProviderImpl(attributeParsers, bundleParsers, oracle, logger).get(documentElement); @@ -910,45 +891,6 @@ return null; } - - private Document parseXmlResource(final String resourcePath) - throws SAXParseException, UnableToCompleteException { - // Get the document builder. We need namespaces, and automatic expanding - // of entity references (the latter of which makes life somewhat easier - // for XMLElement). - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - factory.setExpandEntityReferences(true); - DocumentBuilder builder; - try { - builder = factory.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - throw new RuntimeException(e); - } - - try { - ClassLoader classLoader = UiBinderGenerator.class.getClassLoader(); - URL url = classLoader.getResource(resourcePath); - if (null == url) { - die("Unable to find resource: " + resourcePath); - } - - InputStream stream = url.openStream(); - InputSource input = new InputSource(stream); - input.setSystemId(url.toExternalForm()); - - builder.setEntityResolver(new GwtResourceEntityResolver()); - - return builder.parse(input); - } catch (SAXParseException e) { - // Let SAXParseExceptions through. - throw e; - } catch (SAXException e) { - throw new RuntimeException(e); - } catch (IOException e) { - throw new RuntimeException(e); - } - } private void registerParsers() { // TODO(rjrjr): Allow third-party parsers to register themselves ======================================= --- /releases/2.0/user/src/com/google/gwt/uibinder/rebind/XMLElementProvider.java Mon Nov 2 13:18:15 2009 +++ /releases/2.0/user/src/com/google/gwt/uibinder/rebind/XMLElementProvider.java Thu Nov 5 13:01:52 2009 @@ -17,6 +17,9 @@ import org.w3c.dom.Element; -interface XMLElementProvider { +/** + * Implemented by objects that instantiate XMLElement. + */ +public interface XMLElementProvider { XMLElement get(Element e); } ======================================= --- /releases/2.0/user/src/com/google/gwt/uibinder/rebind/XMLElementProviderImpl.java Wed Nov 4 11:35:50 2009 +++ /releases/2.0/user/src/com/google/gwt/uibinder/rebind/XMLElementProviderImpl.java Thu Nov 5 13:01:52 2009 @@ -19,7 +19,10 @@ import org.w3c.dom.Element; -class XMLElementProviderImpl implements XMLElementProvider { +/** + * The default implemenatation of {...@link XMLElementProvider}. + */ +public class XMLElementProviderImpl implements XMLElementProvider { private final AttributeParsers attributeParsers; @SuppressWarnings("deprecation") // bundleParsers for legacy templates ======================================= --- /releases/2.0/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java Mon Nov 2 13:18:15 2009 +++ /releases/2.0/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java Thu Nov 5 13:01:52 2009 @@ -15,6 +15,7 @@ */ package com.google.gwt.uibinder; +import com.google.gwt.uibinder.parsers.DockLayoutPanelParserTest; import com.google.gwt.uibinder.parsers.FieldReferenceConverterTest; import com.google.gwt.uibinder.parsers.IntAttributeParserTest; import com.google.gwt.uibinder.parsers.StrictAttributeParserTest; @@ -49,6 +50,7 @@ suite.addTestSuite(OwnerFieldTest.class); // parsers + suite.addTestSuite(DockLayoutPanelParserTest.class); suite.addTestSuite(FieldReferenceConverterTest.class); suite.addTestSuite(IntAttributeParserTest.class); suite.addTestSuite(StrictAttributeParserTest.class); ======================================= --- /releases/2.0/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java Wed Nov 4 14:13:39 2009 +++ /releases/2.0/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java Thu Nov 5 13:01:52 2009 @@ -34,35 +34,35 @@ import java.util.HashSet; import java.util.Set; -import javax.xml.parsers.ParserConfigurationException; - /** * Tests XMLElement. */ public class XMLElementTest extends TestCase { private static final String STRING_WITH_DOUBLEQUOTE = "I have a \" quote in me"; + private static final W3cDomHelper docHelper = new W3cDomHelper(); private Document doc; private Element item; private XMLElement elm; private XMLElementProvider elemProvider; - - TypeOracle oracle; - + private TypeOracle oracle; + @Override public void setUp() throws Exception { super.setUp(); - init("<doc><elm attr1=\"attr1Value\" attr2=\"attr2Value\"/></doc>"); - MockResourceOracle resourceOracle = new MockResourceOracle( JavaResourceBase.getStandardResources()); - CompilationState state = new CompilationState(TreeLogger.NULL, resourceOracle); oracle = state.getTypeOracle(); + + elemProvider = new XMLElementProviderImpl(new AttributeParsers(), null, + oracle, MortalLogger.NULL); + + init("<doc><elm attr1=\"attr1Value\" attr2=\"attr2Value\"/></doc>"); } - public void testConsumeBoolean() throws ParserConfigurationException, - SAXException, IOException, UnableToCompleteException { + public void testConsumeBoolean() throws SAXException, IOException, + UnableToCompleteException { init("<doc><elm yes='true' no='false' " + "fnord='fnord' ref='{foo.bar.baz}'/></doc>"); @@ -84,8 +84,8 @@ } } - public void testConsumeBooleanConstant() throws ParserConfigurationException, - SAXException, IOException, UnableToCompleteException { + public void testConsumeBooleanConstant() throws SAXException, IOException, + UnableToCompleteException { init("<doc><elm yes='true' no='false' " + "fnord='fnord' ref='{foo.bar.baz}'/></doc>"); @@ -113,7 +113,7 @@ } public void testConsumeDouble() throws UnableToCompleteException, - ParserConfigurationException, SAXException, IOException { + SAXException, IOException { init("<doc><elm minus='-123.45' plus='123.45' minus-one='-1' " + "plus-one='1' fnord='fnord' ref='{foo.bar.baz}'/></doc>"); assertEquals("1", elm.consumeDoubleAttribute("plus-one")); @@ -167,9 +167,8 @@ } } - public void testConsumeSingleChildElementEmpty() - throws ParserConfigurationException, SAXException, IOException, - UnableToCompleteException { + public void testConsumeSingleChildElementEmpty() throws SAXException, + IOException, UnableToCompleteException { try { elm.consumeSingleChildElement(); fail("Should throw on single child element"); @@ -220,10 +219,9 @@ } public void testNoEndTags() throws Exception { - Document doc = DocumentTestHelp.documentForString("<doc><br/></doc>"); - - Element item = (Element) doc.getDocumentElement().getElementsByTagName("br").item( - 0); + doc = docHelper.documentFor("<doc><br/></doc>"); + Element documentElement = doc.getDocumentElement(); + Element item = (Element) documentElement.getElementsByTagName("br").item(0); XMLElement elm = elemProvider.get(item); assertEquals("br", item.getTagName()); assertEquals("", elm.getClosingTag()); @@ -234,14 +232,10 @@ item.appendChild(t); } - private void init(final String domString) - throws ParserConfigurationException, SAXException, IOException { - doc = DocumentTestHelp.documentForString(domString); + private void init(final String domString) throws SAXException, IOException { + doc = docHelper.documentFor(domString); item = (Element) doc.getDocumentElement().getElementsByTagName("elm").item( 0); - - elemProvider = new XMLElementProviderImpl(new AttributeParsers(), null, - oracle, MortalLogger.NULL); elm = elemProvider.get(item); } } --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---
