Reformulate RPC generated TypeHandlers to create fewer classes.

This is a reformulation of the TypeHandler change, which causes the generated serializer class to serve as the TypeHandler interface implementor.  The current implementation uses an inner class, which causes twice as many types to get generated.

http://gwt-code-reviews.appspot.com/1037801/show


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9143 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/rpc/impl/SerializerBase.java b/user/src/com/google/gwt/user/client/rpc/impl/SerializerBase.java
index 228f679..79132e5 100644
--- a/user/src/com/google/gwt/user/client/rpc/impl/SerializerBase.java
+++ b/user/src/com/google/gwt/user/client/rpc/impl/SerializerBase.java
@@ -88,7 +88,7 @@
       methodMapNative.deserialize(stream, instance, typeSignature);
     } else {
       TypeHandler typeHandler = getTypeHandler(typeSignature);
-      typeHandler.deserialize(stream, instance);
+      typeHandler.deserial(stream, instance);
     }
   }
 
@@ -108,7 +108,7 @@
       return methodMapNative.instantiate(stream, typeSignature);
     } else {
       TypeHandler typeHandler = getTypeHandler(typeSignature);
-      return typeHandler.instantiate(stream);
+      return typeHandler.create(stream);
     }
   }
 
@@ -119,7 +119,7 @@
       methodMapNative.serialize(stream, instance, typeSignature);
     } else {
       TypeHandler typeHandler = getTypeHandler(typeSignature);
-      typeHandler.serialize(stream, instance);
+      typeHandler.serial(stream, instance);
     }
   }
 
diff --git a/user/src/com/google/gwt/user/client/rpc/impl/TypeHandler.java b/user/src/com/google/gwt/user/client/rpc/impl/TypeHandler.java
index 68a9cc0..2fa99c3 100644
--- a/user/src/com/google/gwt/user/client/rpc/impl/TypeHandler.java
+++ b/user/src/com/google/gwt/user/client/rpc/impl/TypeHandler.java
@@ -23,12 +23,11 @@
  * An interface to serializer or deserialize objects of a particular type.
  */
 public interface TypeHandler {
-  void deserialize(SerializationStreamReader reader, Object object)
+  Object create(SerializationStreamReader reader) throws SerializationException;
+
+  void deserial(SerializationStreamReader reader, Object object)
       throws SerializationException;
 
-  Object instantiate(SerializationStreamReader reader)
-      throws SerializationException;
-
-  void serialize(SerializationStreamWriter writer, Object object)
+  void serial(SerializationStreamWriter writer, Object object)
       throws SerializationException;
 }
diff --git a/user/src/com/google/gwt/user/rebind/rpc/FieldSerializerCreator.java b/user/src/com/google/gwt/user/rebind/rpc/FieldSerializerCreator.java
index ef1a153..b25a8ca 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/FieldSerializerCreator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/FieldSerializerCreator.java
@@ -51,7 +51,7 @@
  * fully qualified type names everywhere
  */
 public class FieldSerializerCreator {
-  
+
   private static final String WEAK_MAPPING_CLASS_NAME = WeakMapping.class.getName();
 
   private final JClassType customFieldSerializer;
@@ -111,8 +111,6 @@
     }
     assert sourceWriter != null;
 
-    maybeWriteTypeHandlerClass();
-
     writeFieldAccessors();
 
     writeConcreteTypeMethod();
@@ -123,6 +121,8 @@
 
     writeSerializeMethod();
 
+    maybeWriteTypeHandlerImpl();
+
     sourceWriter.commit(logger);
 
     return fieldSerializerName;
@@ -138,7 +138,7 @@
     }
     return true;
   }
-  
+
   private String createArrayInstantiationExpression(JArrayType array) {
     StringBuilder sb = new StringBuilder();
 
@@ -195,6 +195,9 @@
     composerFactory.addImport(SerializationStreamReader.class.getCanonicalName());
     composerFactory.addImport(SerializationStreamWriter.class.getCanonicalName());
     composerFactory.addAnnotationDeclaration("@SuppressWarnings(\"deprecation\")");
+    if (needsTypeHandler()) {
+      composerFactory.addImplementedInterface(TypeHandler.class.getCanonicalName());
+    }
     return composerFactory.createSourceWriter(ctx, printWriter);
   }
 
@@ -331,70 +334,34 @@
   }
 
   /**
-   * Write a {@link TypeHandler} for the class, used by Java.
+   * Implement {@link TypeHandler} for the class, used by Java.
    * 
    * <pre>
-   * public static class Handler implements
-   *     com.google.gwt.user.client.rpc.impl.TypeHandler {
-   *   public void deserialize(SerializationStreamReader reader, Object object)
-   *       throws SerializationException {
-   *     com.google.gwt.sample.client.Student_FieldSerializer.deserialize(
-   *         reader, (com.google.gwt.sample.client.Student) object);
-   *   }
+   * public void deserial(SerializationStreamReader reader, Object object)
+   *     throws SerializationException {
+   *   com.google.gwt.sample.client.Student_FieldSerializer.deserialize(
+   *       reader, (com.google.gwt.sample.client.Student) object);
+   * }
    * 
-   *   public Object instantiate(SerializationStreamReader reader)
-   *       throws SerializationException {
-   *     return com.google.gwt.sample.client.Student_FieldSerializer.instantiate(reader);
-   *   }
+   * public Object create(SerializationStreamReader reader)
+   *     throws SerializationException {
+   *   return com.google.gwt.sample.client.Student_FieldSerializer.instantiate(reader);
+   * }
    * 
-   *   public void serialize(SerializationStreamWriter writer, Object object)
-   *       throws SerializationException {
-   *     com.google.gwt.sample.client.Student_FieldSerializer.serialize(
-   *         writer, (com.google.gwt.sample.client.Student) object);
-   *   }
+   * public void serial(SerializationStreamWriter writer, Object object)
+   *     throws SerializationException {
+   *   com.google.gwt.sample.client.Student_FieldSerializer.serialize(
+   *       writer, (com.google.gwt.sample.client.Student) object);
    * }
    * </pre>
    */
-  private void maybeWriteTypeHandlerClass() {
-    if (serializableClass.isEnum() == null && serializableClass.isAbstract()) {
-      /*
-       * Field serializers are shared by all of the RemoteService proxies in a
-       * compilation. Therefore, we have to generate an instantiate method even
-       * if the type is not instantiable relative to the RemoteService which
-       * caused this field serializer to be created. If the type is not
-       * instantiable relative to any of the RemoteService proxies, dead code
-       * optimizations will cause the method to be removed from the compiled
-       * output.
-       * 
-       * Enumerated types require an instantiate method even if they are
-       * abstract. You will have an abstract enum in cases where the enum type
-       * is sub-classed. Non-default instantiable classes cannot have
-       * instantiate methods.
-       */
+  private void maybeWriteTypeHandlerImpl() {
+    if (!needsTypeHandler()) {
       return;
     }
-    sourceWriter.println("public static class Handler implements "
-        + TypeHandler.class.getCanonicalName() + " {");
-    sourceWriter.indent();
 
-    // Deserialization method
-    sourceWriter.println("public void deserialize(SerializationStreamReader reader, Object object) throws SerializationException {");
-    if (customFieldSerializer != null) {
-      JMethod deserializationMethod = CustomFieldSerializerValidator.getDeserializationMethod(
-          customFieldSerializer, serializableClass);
-      JType castType = deserializationMethod.getParameters()[1].getType();
-      String typeSig = getTypeSig(deserializationMethod);
-      sourceWriter.indentln(customFieldSerializer.getQualifiedSourceName()
-          + "." + typeSig + "deserialize(reader, ("
-          + castType.getQualifiedSourceName() + ")object);");
-    } else {
-      sourceWriter.indentln(fieldSerializerName + ".deserialize(reader, ("
-          + serializableClass.getQualifiedSourceName() + ")object);");
-    }
-    sourceWriter.println("}");
-
-    // Instantiation method
-    sourceWriter.println("public Object instantiate(SerializationStreamReader reader) throws SerializationException {");
+    // Create method
+    sourceWriter.println("public Object create(SerializationStreamReader reader) throws SerializationException {");
     sourceWriter.indent();
     if (serializableClass.isEnum() != null
         || serializableClass.isDefaultInstantiable()
@@ -417,9 +384,27 @@
     }
     sourceWriter.outdent();
     sourceWriter.println("}");
+    sourceWriter.println();
 
-    // Serialization method
-    sourceWriter.println("public void serialize(SerializationStreamWriter writer, Object object) throws SerializationException {");
+    // Deserial method
+    sourceWriter.println("public void deserial(SerializationStreamReader reader, Object object) throws SerializationException {");
+    if (customFieldSerializer != null) {
+      JMethod deserializationMethod = CustomFieldSerializerValidator.getDeserializationMethod(
+          customFieldSerializer, serializableClass);
+      JType castType = deserializationMethod.getParameters()[1].getType();
+      String typeSig = getTypeSig(deserializationMethod);
+      sourceWriter.indentln(customFieldSerializer.getQualifiedSourceName()
+          + "." + typeSig + "deserialize(reader, ("
+          + castType.getQualifiedSourceName() + ")object);");
+    } else {
+      sourceWriter.indentln(fieldSerializerName + ".deserialize(reader, ("
+          + serializableClass.getQualifiedSourceName() + ")object);");
+    }
+    sourceWriter.println("}");
+    sourceWriter.println();
+
+    // Serial method
+    sourceWriter.println("public void serial(SerializationStreamWriter writer, Object object) throws SerializationException {");
     if (customFieldSerializer != null) {
       JMethod serializationMethod = CustomFieldSerializerValidator.getSerializationMethod(
           customFieldSerializer, serializableClass);
@@ -434,8 +419,7 @@
     }
 
     sourceWriter.println("}");
-    sourceWriter.outdent();
-    sourceWriter.println("}");
+    sourceWriter.println();
   }
 
   /**
@@ -455,6 +439,16 @@
     return field.isPrivate();
   }
 
+  /**
+   * Enumerated types can be instantiated even if they are abstract. You will
+   * have an abstract enum in cases where the enum type is sub-classed.
+   * Non-default instantiable classes cannot have instantiate methods.
+   */
+  private boolean needsTypeHandler() {
+    return serializableClass.isEnum() != null
+        || !serializableClass.isAbstract();
+  }
+
   private void writeArrayDeserializationStatements(JArrayType isArray) {
     JType componentType = isArray.getComponentType();
     String readMethodName = Shared.getStreamReadMethodNameFor(componentType);
@@ -504,7 +498,7 @@
           + getDepth(serializableClass)
           + "\", streamReader.readString());");
     }
-    
+
     for (JField serializableField : serializableFields) {
       JType fieldType = serializableField.getType();
 
@@ -547,14 +541,14 @@
      * If the type is capable of making a round trip between the client and
      * server, retrieve the additional server-only field data from {@link WeakMapping}.
      */
-    
+
     if (serializableClass.isEnhanced()) {
       sourceWriter.println("streamWriter.writeString((String) "
           + WEAK_MAPPING_CLASS_NAME
           + ".get(instance, \"server-enhanced-data-"
           + getDepth(serializableClass) + "\"));");
     }
-    
+
     for (JField serializableField : serializableFields) {
       JType fieldType = serializableField.getType();
 
@@ -634,7 +628,7 @@
     } else {
       writeClassDeserializationStatements();
     }
-      
+
     sourceWriter.outdent();
     sourceWriter.println("}");
     sourceWriter.println();
diff --git a/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java b/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
index 19676ed..ef8f3ff 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/TypeSerializerCreator.java
@@ -355,7 +355,7 @@
           + type.getQualifiedSourceName();
       srcWriter.println("result.put(\"" + typeString + "\", new "
           + SerializationUtils.getStandardSerializerName((JClassType) type)
-          + ".Handler());");
+          + "());");
     }
 
     srcWriter.println("return result;");