Issue 5582

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


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9495 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/rebind/rpc/TypeConstrainer.java b/user/src/com/google/gwt/user/rebind/rpc/TypeConstrainer.java
index efdb324..888838d 100644
--- a/user/src/com/google/gwt/user/rebind/rpc/TypeConstrainer.java
+++ b/user/src/com/google/gwt/user/rebind/rpc/TypeConstrainer.java
@@ -355,9 +355,10 @@
       public void endVisit(JTypeParameter param) {
         JClassType constr = constraints.get(param);
         if (constr != null) {
-          replacement = constr;
+          // further transform the substituted type recursively 
+          replacement = transform(constr);
         }
-      }
+      } 
     };
     return substituter.transform(type);
   }
diff --git a/user/test/com/google/gwt/rpc/client/RpcRecursiveClassTest.java b/user/test/com/google/gwt/rpc/client/RpcRecursiveClassTest.java
new file mode 100644
index 0000000..de09087
--- /dev/null
+++ b/user/test/com/google/gwt/rpc/client/RpcRecursiveClassTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.rpc.client;
+
+import com.google.gwt.user.client.rpc.RecursiveClassTest;
+
+/**
+ * Tests RPC system using existing tests by overriding module name.
+ */
+public class RpcRecursiveClassTest extends RecursiveClassTest {
+
+  @Override
+  public String getModuleName() {
+    return "com.google.gwt.rpc.RPCSuite";
+  }
+
+}
\ No newline at end of file
diff --git a/user/test/com/google/gwt/user/RPCSuite.gwt.xml b/user/test/com/google/gwt/user/RPCSuite.gwt.xml
index 0a1658c..fba0744 100644
--- a/user/test/com/google/gwt/user/RPCSuite.gwt.xml
+++ b/user/test/com/google/gwt/user/RPCSuite.gwt.xml
@@ -39,5 +39,9 @@
     class='com.google.gwt.user.server.rpc.AnnotatedRpcTokenTestServiceImpl' />
   <servlet path='/unicodeEscape'
     class='com.google.gwt.user.server.rpc.UnicodeEscapingServiceImpl' />
+  <servlet path='/recursiveclass'
+    class='com.google.gwt.user.server.rpc.RecursiveClassTestServiceImpl' />
+  <servlet path='/finalfields'
+    class='com.google.gwt.user.server.rpc.FinalFieldsTestServiceImpl' />
 
 </module>
diff --git a/user/test/com/google/gwt/user/RPCSuite.java b/user/test/com/google/gwt/user/RPCSuite.java
index 8f0182a..44a5478 100644
--- a/user/test/com/google/gwt/user/RPCSuite.java
+++ b/user/test/com/google/gwt/user/RPCSuite.java
@@ -38,6 +38,7 @@
 import com.google.gwt.user.client.rpc.InheritanceTestWithTypeObfuscation;
 import com.google.gwt.user.client.rpc.ObjectGraphTest;
 import com.google.gwt.user.client.rpc.ObjectGraphTestWithTypeObfuscation;
+import com.google.gwt.user.client.rpc.RecursiveClassTest;
 import com.google.gwt.user.client.rpc.RpcTokenTest;
 import com.google.gwt.user.client.rpc.RunTimeSerializationErrorsTest;
 import com.google.gwt.user.client.rpc.UnicodeEscapingTest;
@@ -101,6 +102,7 @@
     suite.addTestSuite(RpcTokenTest.class);
     suite.addTestSuite(UnicodeEscapingTest.class);
     suite.addTestSuite(RunTimeSerializationErrorsTest.class);
+    suite.addTestSuite(RecursiveClassTest.class);
 
     // This test turns on the type-elision feature of RPC
     suite.addTestSuite(ValueTypesTestWithTypeObfuscation.class);
diff --git a/user/test/com/google/gwt/user/client/rpc/RecursiveClassTest.java b/user/test/com/google/gwt/user/client/rpc/RecursiveClassTest.java
new file mode 100644
index 0000000..e0cb51b
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/rpc/RecursiveClassTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.user.client.rpc;
+
+import com.google.gwt.user.client.rpc.RecursiveClassTestService.ResultNode;
+import com.google.gwt.core.client.GWT;
+
+
+/**
+ * Class used to test generics with wild cards and recursive references.
+ */
+public class RecursiveClassTest extends RpcTestBase {
+
+  /**
+   * This method is used to test generics with wild cards and recursive references.
+   */
+  public void testRecursiveClass() {
+    RecursiveClassTestServiceAsync service = getServiceAsync();
+    delayTestFinishForRpc();
+   
+    service.greetServer("Hello", new AsyncCallback<ResultNode>() {
+      public void onFailure(Throwable caught) {
+        TestSetValidator.rethrowException(caught);
+      }
+
+      public void onSuccess(ResultNode result) {
+        assertNotNull(result);
+        assertTrue(TestSetValidator.isValidRecurisveClassObject(result));
+        finishTest();
+      }
+    });
+  }
+  
+  /**
+   * Create a remote service proxy to talk to the server-side Greeting service.
+   */
+  private RecursiveClassTestServiceAsync getServiceAsync() {
+    if (recursiveClassTestService == null) {
+      recursiveClassTestService = (RecursiveClassTestServiceAsync) GWT.create(RecursiveClassTestService.class);
+      ((ServiceDefTarget) recursiveClassTestService).setServiceEntryPoint(GWT.getModuleBaseURL()
+          + "recursiveclass");
+    }
+    return recursiveClassTestService;
+  }
+
+  private RecursiveClassTestServiceAsync recursiveClassTestService;
+
+}
+
diff --git a/user/test/com/google/gwt/user/client/rpc/RecursiveClassTestService.java b/user/test/com/google/gwt/user/client/rpc/RecursiveClassTestService.java
new file mode 100644
index 0000000..6d7ac83
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/rpc/RecursiveClassTestService.java
@@ -0,0 +1,54 @@
+/*
+ * 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.user.client.rpc;
+
+import java.io.Serializable;
+
+/**
+ * Service used to test generics with wild cards and recursive references.
+ */
+public interface RecursiveClassTestService extends RemoteService {
+
+  /**
+   * This class has a self-reference and wild cards in its parameterization.
+   */
+  public class ResultNode<T extends ResultNode<?>> implements Serializable {
+    private static final long serialVersionUID = -3560238969723137110L;
+
+    public int dataType;
+    public int id1;
+    public int id2;
+    public int id3;
+    public int id4;
+    public int numChildren;
+    public String data;
+    public T next;
+
+
+    public ResultNode() {
+    }
+  }
+  
+  /**
+   * Subclass of the self-referencing class; necessary to test a previous bug.
+   */
+  public class SubResultNode<S extends ResultNode<?>> extends ResultNode<S> {
+    int i;
+  }
+  
+  <U extends ResultNode<U>> ResultNode<U> greetServer(String name) throws IllegalArgumentException;
+}
diff --git a/user/test/com/google/gwt/user/client/rpc/RecursiveClassTestServiceAsync.java b/user/test/com/google/gwt/user/client/rpc/RecursiveClassTestServiceAsync.java
new file mode 100644
index 0000000..2914b04
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/rpc/RecursiveClassTestServiceAsync.java
@@ -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.user.client.rpc;
+
+import com.google.gwt.user.client.rpc.RecursiveClassTestService.ResultNode;
+
+/**
+ * Service used to test generics with wild cards and recursive references
+ */
+public interface RecursiveClassTestServiceAsync {
+  <U extends ResultNode<?>> void greetServer(String input, AsyncCallback<ResultNode> callback)
+    throws IllegalArgumentException;
+}
diff --git a/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java b/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
index 4c8b783..d65dbf7 100644
--- a/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
+++ b/user/test/com/google/gwt/user/client/rpc/TestSetValidator.java
@@ -23,6 +23,7 @@
 import com.google.gwt.user.client.rpc.TestSetFactory.SerializableGraphWithCFS;
 import com.google.gwt.user.client.rpc.TestSetFactory.SerializablePrivateNoArg;
 import com.google.gwt.user.client.rpc.TestSetFactory.SerializableWithTwoArrays;
+import com.google.gwt.user.client.rpc.RecursiveClassTestService.ResultNode;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -560,6 +561,10 @@
     assertSame(result, child.getParent());
     return true;
   }
+  
+  public static boolean isValidRecurisveClassObject(ResultNode<? extends ResultNode<?>> result) {
+    return (result != null);
+  }
 
   public static boolean isValidSingletonList(List<MarkerTypeSingleton> list) {
     if (list == null || list.size() != 1) {
diff --git a/user/test/com/google/gwt/user/server/rpc/RecursiveClassTestServiceImpl.java b/user/test/com/google/gwt/user/server/rpc/RecursiveClassTestServiceImpl.java
new file mode 100644
index 0000000..500cba1
--- /dev/null
+++ b/user/test/com/google/gwt/user/server/rpc/RecursiveClassTestServiceImpl.java
@@ -0,0 +1,35 @@
+/*
+ * 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.user.server.rpc;
+
+import com.google.gwt.user.client.rpc.RecursiveClassTestService;
+
+/**
+ * The server side implementation of the RPC service.
+ *
+ */
+public class RecursiveClassTestServiceImpl extends RemoteServiceServlet
+    implements RecursiveClassTestService {
+
+  /* (non-Javadoc)
+   * @see com.google.gwt.user.client.rpc.RecursiveClassTestService#greetServer(java.lang.String)
+   */
+  public <T extends ResultNode<T>> ResultNode<T> greetServer(String name)
+      throws IllegalArgumentException {
+     return new ResultNode<T>();
+  }
+  
+}