diff options
Diffstat (limited to 'client-compiler')
7 files changed, 221 insertions, 18 deletions
diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java b/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java index a6ca690a8a..13bd7051f6 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/ConnectorBundleLoaderFactory.java @@ -61,12 +61,14 @@ import com.vaadin.server.widgetsetutils.metadata.ConnectorInitVisitor; import com.vaadin.server.widgetsetutils.metadata.GeneratedSerializer; import com.vaadin.server.widgetsetutils.metadata.OnStateChangeVisitor; import com.vaadin.server.widgetsetutils.metadata.Property; +import com.vaadin.server.widgetsetutils.metadata.RendererVisitor; import com.vaadin.server.widgetsetutils.metadata.ServerRpcVisitor; import com.vaadin.server.widgetsetutils.metadata.StateInitVisitor; import com.vaadin.server.widgetsetutils.metadata.TypeVisitor; import com.vaadin.server.widgetsetutils.metadata.WidgetInitVisitor; import com.vaadin.shared.annotations.Delayed; import com.vaadin.shared.annotations.DelegateToWidget; +import com.vaadin.shared.annotations.NoLayout; import com.vaadin.shared.communication.ClientRpc; import com.vaadin.shared.communication.ServerRpc; import com.vaadin.shared.ui.Connect; @@ -453,6 +455,10 @@ public class ConnectorBundleLoaderFactory extends Generator { writer.println("var data = {"); writer.indent(); + if (property.getAnnotation(NoLayout.class) != null) { + writer.println("noLayout: 1, "); + } + writer.println("setter: function(bean, value) {"); writer.indent(); property.writeSetterBody(logger, writer, "bean", "value"); @@ -496,6 +502,7 @@ public class ConnectorBundleLoaderFactory extends Generator { writeParamTypes(w, bundle); writeProxys(w, bundle); writeDelayedInfo(w, bundle); + writeNoLayoutRpcMethods(w, bundle); w.println("%s(store);", loadNativeJsMethodName); @@ -503,10 +510,27 @@ public class ConnectorBundleLoaderFactory extends Generator { // this after the JS property data has been initialized writePropertyTypes(logger, w, bundle); writeSerializers(logger, w, bundle); + writePresentationTypes(w, bundle); writeDelegateToWidget(logger, w, bundle); writeOnStateChangeHandlers(logger, w, bundle); } + private void writeNoLayoutRpcMethods(SplittingSourceWriter w, + ConnectorBundle bundle) { + Map<JClassType, Set<JMethod>> needsNoLayout = bundle + .getNeedsNoLayoutRpcMethods(); + for (Entry<JClassType, Set<JMethod>> entry : needsNoLayout.entrySet()) { + JClassType type = entry.getKey(); + + for (JMethod method : entry.getValue()) { + w.println("store.setNoLayoutRpcMethod(%s, \"%s\");", + getClassLiteralString(type), method.getName()); + } + + w.splitIfNeeded(); + } + } + private void writeOnStateChangeHandlers(TreeLogger logger, SplittingSourceWriter w, ConnectorBundle bundle) throws UnableToCompleteException { @@ -684,6 +708,21 @@ public class ConnectorBundleLoaderFactory extends Generator { } } + private void writePresentationTypes(SplittingSourceWriter w, + ConnectorBundle bundle) { + Map<JClassType, JType> presentationTypes = bundle + .getPresentationTypes(); + for (Entry<JClassType, JType> entry : presentationTypes.entrySet()) { + + w.print("store.setPresentationType("); + writeClassLiteral(w, entry.getKey()); + w.print(", "); + writeClassLiteral(w, entry.getValue()); + w.println(");"); + w.splitIfNeeded(); + } + } + private void writePropertyTypes(TreeLogger logger, SplittingSourceWriter w, ConnectorBundle bundle) { Set<Property> properties = bundle.getNeedsProperty(); @@ -1240,8 +1279,9 @@ public class ConnectorBundleLoaderFactory extends Generator { throws NotFoundException { List<TypeVisitor> visitors = Arrays.<TypeVisitor> asList( new ConnectorInitVisitor(), new StateInitVisitor(), - new WidgetInitVisitor(), new ClientRpcVisitor(), - new ServerRpcVisitor(), new OnStateChangeVisitor()); + new WidgetInitVisitor(), new RendererVisitor(), + new ClientRpcVisitor(), new ServerRpcVisitor(), + new OnStateChangeVisitor()); for (TypeVisitor typeVisitor : visitors) { typeVisitor.init(oracle); } diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ArraySerializer.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ArraySerializer.java index 6ffd6c5462..0049ae9b50 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ArraySerializer.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ArraySerializer.java @@ -19,12 +19,14 @@ package com.vaadin.server.widgetsetutils.metadata; import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.typeinfo.JArrayType; import com.google.gwt.core.ext.typeinfo.JType; -import com.google.gwt.json.client.JSONArray; import com.google.gwt.user.rebind.SourceWriter; import com.vaadin.client.communication.JsonDecoder; import com.vaadin.client.communication.JsonEncoder; import com.vaadin.server.widgetsetutils.ConnectorBundleLoaderFactory; +import elemental.json.Json; +import elemental.json.JsonArray; + public class ArraySerializer extends JsonSerializer { private final JArrayType arrayType; @@ -40,12 +42,12 @@ public class ArraySerializer extends JsonSerializer { JType leafType = arrayType.getLeafType(); int rank = arrayType.getRank(); - w.println(JSONArray.class.getName() + " jsonArray = " + jsonValue - + ".isArray();"); + w.println(JsonArray.class.getName() + " jsonArray = (" + + JsonArray.class.getName() + ")" + jsonValue + ";"); // Type value = new Type[jsonArray.size()][][]; w.print(arrayType.getQualifiedSourceName() + " value = new " - + leafType.getQualifiedSourceName() + "[jsonArray.size()]"); + + leafType.getQualifiedSourceName() + "[jsonArray.length()]"); for (int i = 1; i < rank; i++) { w.print("[]"); } @@ -75,8 +77,8 @@ public class ArraySerializer extends JsonSerializer { String value, String applicationConnection) { JType componentType = arrayType.getComponentType(); - w.println(JSONArray.class.getName() + " values = new " - + JSONArray.class.getName() + "();"); + w.println(JsonArray.class.getName() + " values = " + + Json.class.getName() + ".createArray();"); // JPrimitiveType primitive = componentType.isPrimitive(); w.println("for (int i = 0; i < " + value + ".length; i++) {"); w.indent(); diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ClientRpcVisitor.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ClientRpcVisitor.java index 856f67657f..1df3d78588 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ClientRpcVisitor.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ClientRpcVisitor.java @@ -24,6 +24,7 @@ import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JMethod; import com.google.gwt.core.ext.typeinfo.JType; +import com.vaadin.shared.annotations.NoLayout; public class ClientRpcVisitor extends TypeVisitor { @Override @@ -39,6 +40,9 @@ public class ClientRpcVisitor extends TypeVisitor { bundle.setNeedsInvoker(type, method); bundle.setNeedsParamTypes(type, method); + if (method.getAnnotation(NoLayout.class) != null) { + bundle.setNeedsNoLayoutRpcMethod(type, method); + } JType[] parameterTypes = method.getParameterTypes(); for (JType paramType : parameterTypes) { diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java index e8a384298f..31f59ddee4 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/ConnectorBundle.java @@ -37,16 +37,17 @@ import com.google.gwt.core.ext.typeinfo.JParameterizedType; import com.google.gwt.core.ext.typeinfo.JType; import com.google.gwt.core.ext.typeinfo.NotFoundException; import com.google.gwt.core.ext.typeinfo.TypeOracle; -import com.google.gwt.json.client.JSONValue; import com.google.gwt.thirdparty.guava.common.collect.Sets; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.ComponentConnector; import com.vaadin.client.ServerConnector; import com.vaadin.client.communication.JSONSerializer; +import com.vaadin.client.connectors.AbstractRendererConnector; import com.vaadin.client.ui.UnknownComponentConnector; import com.vaadin.shared.communication.ClientRpc; import com.vaadin.shared.communication.ServerRpc; import com.vaadin.shared.ui.Connect; +import elemental.json.JsonValue; public class ConnectorBundle { private static final String FAIL_IF_NOT_SERIALIZABLE = "vFailIfNotSerializable"; @@ -59,6 +60,7 @@ public class ConnectorBundle { private final Set<JType> hasSerializeSupport = new HashSet<JType>(); private final Set<JType> needsSerializeSupport = new HashSet<JType>(); private final Map<JType, GeneratedSerializer> serializers = new HashMap<JType, GeneratedSerializer>(); + private final Map<JClassType, JType> presentationTypes = new HashMap<JClassType, JType>(); private final Set<JClassType> needsSuperClass = new HashSet<JClassType>(); private final Set<JClassType> needsGwtConstructor = new HashSet<JClassType>(); @@ -71,6 +73,7 @@ public class ConnectorBundle { private final Map<JClassType, Set<JMethod>> needsParamTypes = new HashMap<JClassType, Set<JMethod>>(); private final Map<JClassType, Set<JMethod>> needsDelayedInfo = new HashMap<JClassType, Set<JMethod>>(); private final Map<JClassType, Set<JMethod>> needsOnStateChange = new HashMap<JClassType, Set<JMethod>>(); + private final Map<JClassType, Set<JMethod>> needsNoLayoutRpcMethods = new HashMap<JClassType, Set<JMethod>>(); private final Set<Property> needsProperty = new HashSet<Property>(); private final Map<JClassType, Set<Property>> needsDelegateToWidget = new HashMap<JClassType, Set<Property>>(); @@ -102,7 +105,7 @@ public class ConnectorBundle { .getName()); JType[] deserializeParamTypes = new JType[] { oracle.findType(com.vaadin.client.metadata.Type.class.getName()), - oracle.findType(JSONValue.class.getName()), + oracle.findType(JsonValue.class.getName()), oracle.findType(ApplicationConnection.class.getName()) }; String deserializeMethodName = "deserialize"; // Just test that the method exists @@ -306,6 +309,25 @@ public class ConnectorBundle { return Collections.unmodifiableMap(serializers); } + public void setPresentationType(JClassType type, JType presentationType) { + if (!hasPresentationType(type)) { + presentationTypes.put(type, presentationType); + } + } + + private boolean hasPresentationType(JClassType type) { + if (presentationTypes.containsKey(type)) { + return true; + } else { + return previousBundle != null + && previousBundle.hasPresentationType(type); + } + } + + public Map<JClassType, JType> getPresentationTypes() { + return Collections.unmodifiableMap(presentationTypes); + } + private void setNeedsSuperclass(JClassType typeAsClass) { if (!isNeedsSuperClass(typeAsClass)) { needsSuperClass.add(typeAsClass); @@ -415,6 +437,11 @@ public class ConnectorBundle { return isConnected(type) && isType(type, ComponentConnector.class); } + public static boolean isConnectedRendererConnector(JClassType type) { + return isConnected(type) + && isType(type, AbstractRendererConnector.class); + } + private static boolean isInterfaceType(JClassType type, Class<?> class1) { return type.isInterface() != null && isType(type, class1); } @@ -608,6 +635,25 @@ public class ConnectorBundle { return Collections.unmodifiableMap(needsOnStateChange); } + public void setNeedsNoLayoutRpcMethod(JClassType type, JMethod method) { + if (!isNeedsNoLayoutRpcMethod(type, method)) { + addMapping(needsNoLayoutRpcMethods, type, method); + } + } + + private boolean isNeedsNoLayoutRpcMethod(JClassType type, JMethod method) { + if (hasMapping(needsNoLayoutRpcMethods, type, method)) { + return true; + } else { + return previousBundle != null + && previousBundle.isNeedsNoLayoutRpcMethod(type, method); + } + } + + public Map<JClassType, Set<JMethod>> getNeedsNoLayoutRpcMethods() { + return Collections.unmodifiableMap(needsNoLayoutRpcMethods); + } + public static JMethod findInheritedMethod(JClassType type, String methodName, JType... params) { diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/EnumSerializer.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/EnumSerializer.java index 18e9652ed1..9876baf946 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/EnumSerializer.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/EnumSerializer.java @@ -19,9 +19,10 @@ package com.vaadin.server.widgetsetutils.metadata; import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.typeinfo.JEnumConstant; import com.google.gwt.core.ext.typeinfo.JEnumType; -import com.google.gwt.json.client.JSONString; import com.google.gwt.user.rebind.SourceWriter; +import elemental.json.Json; + public class EnumSerializer extends JsonSerializer { private final JEnumType enumType; @@ -34,8 +35,7 @@ public class EnumSerializer extends JsonSerializer { @Override protected void printDeserializerBody(TreeLogger logger, SourceWriter w, String type, String jsonValue, String connection) { - w.println("String enumIdentifier = ((" + JSONString.class.getName() - + ")" + jsonValue + ").stringValue();"); + w.println("String enumIdentifier = " + jsonValue + ".asString();"); for (JEnumConstant e : enumType.getEnumConstants()) { w.println("if (\"" + e.getName() + "\".equals(enumIdentifier)) {"); w.indent(); @@ -50,8 +50,8 @@ public class EnumSerializer extends JsonSerializer { @Override protected void printSerializerBody(TreeLogger logger, SourceWriter w, String value, String applicationConnection) { - // return new JSONString(castedValue.name()); - w.println("return new " + JSONString.class.getName() + "(" + value + // return Json.create(castedValue.name()); + w.println("return " + Json.class.getName() + ".create(" + value + ".name());"); } diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/JsonSerializer.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/JsonSerializer.java index 0509689850..a7a6c568da 100644 --- a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/JsonSerializer.java +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/JsonSerializer.java @@ -19,10 +19,10 @@ package com.vaadin.server.widgetsetutils.metadata; import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.core.ext.typeinfo.JType; -import com.google.gwt.json.client.JSONValue; import com.google.gwt.user.rebind.SourceWriter; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.communication.JSONSerializer; +import elemental.json.JsonValue; public abstract class JsonSerializer implements GeneratedSerializer { @@ -51,7 +51,7 @@ public abstract class JsonSerializer implements GeneratedSerializer { protected void writeSerializerBody(TreeLogger logger, SourceWriter w) { String qualifiedSourceName = type.getQualifiedSourceName(); - w.println("public " + JSONValue.class.getName() + " serialize(" + w.println("public " + JsonValue.class.getName() + " serialize(" + qualifiedSourceName + " value, " + ApplicationConnection.class.getName() + " connection) {"); w.indent(); @@ -69,7 +69,7 @@ public abstract class JsonSerializer implements GeneratedSerializer { // T deserialize(Type type, JSONValue jsonValue, ApplicationConnection // connection); w.println("public " + qualifiedSourceName + " deserialize(Type type, " - + JSONValue.class.getName() + " jsonValue, " + + JsonValue.class.getName() + " jsonValue, " + ApplicationConnection.class.getName() + " connection) {"); w.indent(); diff --git a/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/RendererVisitor.java b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/RendererVisitor.java new file mode 100644 index 0000000000..bf1e11c9e3 --- /dev/null +++ b/client-compiler/src/com/vaadin/server/widgetsetutils/metadata/RendererVisitor.java @@ -0,0 +1,111 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * 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.vaadin.server.widgetsetutils.metadata; + +import com.google.gwt.core.ext.TreeLogger; +import com.google.gwt.core.ext.TreeLogger.Type; +import com.google.gwt.core.ext.UnableToCompleteException; +import com.google.gwt.core.ext.typeinfo.JClassType; +import com.google.gwt.core.ext.typeinfo.JMethod; +import com.google.gwt.core.ext.typeinfo.JParameterizedType; +import com.google.gwt.core.ext.typeinfo.JType; +import com.vaadin.client.connectors.AbstractRendererConnector; + +/** + * Generates type data for renderer connectors. + * <ul> + * <li>Stores the return type of the overridden + * {@link AbstractRendererConnector#getRenderer() getRenderer} method to enable + * automatic creation of an instance of the proper renderer type. + * <li>Stores the presentation type of the connector to enable the + * {@link AbstractRendererConnector#decode(elemental.json.JsonValue) decode} + * method to work without having to implement a "getPresentationType" method. + * </ul> + * + * @see WidgetInitVisitor + * + * @since + * @author Vaadin Ltd + */ +public class RendererVisitor extends TypeVisitor { + + @Override + public void visitConnector(TreeLogger logger, JClassType type, + ConnectorBundle bundle) throws UnableToCompleteException { + if (ConnectorBundle.isConnectedRendererConnector(type)) { + doRendererType(logger, type, bundle); + doPresentationType(logger, type, bundle); + } + } + + private static void doRendererType(TreeLogger logger, JClassType type, + ConnectorBundle bundle) { + // The class in which createRenderer is implemented + JClassType createRendererClass = ConnectorBundle.findInheritedMethod( + type, "createRenderer").getEnclosingType(); + + // Needs GWT constructor if createRenderer is not overridden + if (createRendererClass.getQualifiedSourceName().equals( + AbstractRendererConnector.class.getCanonicalName())) { + + JMethod getRenderer = ConnectorBundle.findInheritedMethod(type, + "getRenderer"); + JClassType rendererType = getRenderer.getReturnType().isClass(); + + bundle.setNeedsGwtConstructor(rendererType); + + // Also needs renderer type to find the right GWT constructor + bundle.setNeedsReturnType(type, getRenderer); + + logger.log(Type.DEBUG, "Renderer type of " + type + " is " + + rendererType); + } + } + + private void doPresentationType(TreeLogger logger, JClassType type, + ConnectorBundle bundle) throws UnableToCompleteException { + JType presentationType = getPresentationType(type, logger); + bundle.setPresentationType(type, presentationType); + + logger.log(Type.DEBUG, "Presentation type of " + type + " is " + + presentationType); + } + + private static JType getPresentationType(JClassType type, TreeLogger logger) + throws UnableToCompleteException { + JClassType originalType = type; + while (type != null) { + if (type.getQualifiedBinaryName().equals( + AbstractRendererConnector.class.getName())) { + JParameterizedType parameterized = type.isParameterized(); + if (parameterized == null) { + logger.log( + Type.ERROR, + type.getQualifiedSourceName() + + " must define the generic parameter of the inherited " + + AbstractRendererConnector.class + .getSimpleName()); + throw new UnableToCompleteException(); + } + return parameterized.getTypeArgs()[0]; + } + type = type.getSuperclass(); + } + throw new IllegalArgumentException("The type " + + originalType.getQualifiedSourceName() + " does not extend " + + AbstractRendererConnector.class.getName()); + } +} |