RequestFactoryGenerator generated invalid java classes.

In some cases RequestFactoryGenerator generated classes that implemented the same generic
interface twice with different generic parameters. For example:

class X extends AbstractRequest<ResultType>
implements InstanceRequest<BarProxy, ResultType> { ... }

where AbstractRequest is defined in the library as follows:

class AbstractRequest<X> implements InstanceRequest<BaseProxy, X> {... }

Although the code is not valid java the GWT compiler would ignore the error and generate
working code; but newer versions of the JDT reject the code.

The change here is to add a type argument to AbstractRequest:
AbstractRequest<P extends BaseProxy, X> … implements InstanceRequest<P, X>

Change-Id: Ib9a604ef63f05bbecd8bfed60255f74682607fcc
Review-Link: https://gwt-review.googlesource.com/#/c/2370/

Review by: skybrian@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@11578 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/web/bindery/requestfactory/gwt/rebind/RequestFactoryGenerator.java b/user/src/com/google/web/bindery/requestfactory/gwt/rebind/RequestFactoryGenerator.java
index 7bbd30a..f4bca3c 100644
--- a/user/src/com/google/web/bindery/requestfactory/gwt/rebind/RequestFactoryGenerator.java
+++ b/user/src/com/google/web/bindery/requestfactory/gwt/rebind/RequestFactoryGenerator.java
@@ -47,6 +47,7 @@
 import com.google.web.bindery.requestfactory.gwt.rebind.model.ModelVisitor;
 import com.google.web.bindery.requestfactory.gwt.rebind.model.RequestFactoryModel;
 import com.google.web.bindery.requestfactory.gwt.rebind.model.RequestMethod;
+import com.google.web.bindery.requestfactory.shared.BaseProxy;
 import com.google.web.bindery.requestfactory.shared.EntityProxyId;
 import com.google.web.bindery.requestfactory.shared.JsonRpcContent;
 import com.google.web.bindery.requestfactory.shared.impl.AbstractRequest;
@@ -375,10 +376,14 @@
         sw.println("public %s %s %s(%s) {", typeParameterDeclaration, jmethod.getReturnType()
             .getParameterizedQualifiedSourceName(), jmethod.getName(), parameterDeclaration);
         sw.indent();
+
         // The implements clause covers InstanceRequest
-        // class X extends AbstractRequest<Return> implements Request<Return> {
-        sw.println("class X extends %s<%s> implements %s {", AbstractRequest.class
-            .getCanonicalName(), request.getDataType().getParameterizedQualifiedSourceName(),
+        // class X extends AbstractRequest<FooProxy, Return> implements Request<Return> {
+        sw.println("class X extends %s<%s, %s> implements %s {",
+            AbstractRequest.class.getCanonicalName(),
+            request.getInstanceType() == null ? BaseProxy.class.getCanonicalName() :
+                request.getInstanceType().getQualifiedSourceName(),
+            request.getDataType().getParameterizedQualifiedSourceName(),
             jmethod.getReturnType().getParameterizedQualifiedSourceName());
         sw.indent();
 
diff --git a/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequest.java b/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequest.java
index ea36479..71cd66f 100644
--- a/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequest.java
+++ b/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequest.java
@@ -33,10 +33,12 @@
 /**
  * Abstract implementation of {@link Request}. Each request stores a
  * {@link DeltaValueStoreJsonImpl}.
- * 
+ *
+ * @param <P> proxy type
  * @param <T> return type
  */
-public abstract class AbstractRequest<T> implements Request<T>, InstanceRequest<BaseProxy, T> {
+public abstract class AbstractRequest<P extends BaseProxy, T> implements
+    Request<T>, InstanceRequest<P, T> {
 
   /**
    * Used by generated subtypes.
@@ -84,10 +86,10 @@
   }
 
   /**
-   * This method comes from the {@link InstanceRequest} interface. Instance
-   * methods place the instance in the first parameter slot.
+   * This method comes from the {@link InstanceRequest}
+   * interface. Instance methods place the instance in the first parameter slot.
    */
-  public Request<T> using(BaseProxy instanceObject) {
+  public Request<T> using(P instanceObject) {
     getRequestData().getOrderedParameters()[0] = instanceObject;
     /*
      * Instance methods enqueue themselves when their using() method is called.
diff --git a/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequestContext.java b/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequestContext.java
index 3bcffa3..97f783f 100644
--- a/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequestContext.java
+++ b/user/src/com/google/web/bindery/requestfactory/shared/impl/AbstractRequestContext.java
@@ -108,7 +108,7 @@
      * When {@code true} the {@link AbstractRequestContext#fire()} method will be a no-op.
      */
     public boolean fireDisabled;
-    public final List<AbstractRequest<?>> invocations = new ArrayList<AbstractRequest<?>>();
+    public final List<AbstractRequest<?, ?>> invocations = new ArrayList<AbstractRequest<?, ?>>();
 
     public boolean locked;
     /**
@@ -175,7 +175,7 @@
 
   interface DialectImpl {
 
-    void addInvocation(AbstractRequest<?> request);
+    void addInvocation(AbstractRequest<?, ?> request);
 
     String makePayload();
 
@@ -186,7 +186,7 @@
     /**
      * Called by generated subclasses to enqueue a method invocation.
      */
-    public void addInvocation(AbstractRequest<?> request) {
+    public void addInvocation(AbstractRequest<?, ?> request) {
       /*
        * TODO(bobv): Support for multiple invocations per request needs to be ironed out. Once this
        * is done, addInvocation() can be removed from the DialectImpl interface and restored to to
@@ -312,7 +312,7 @@
     /**
      * Called by generated subclasses to enqueue a method invocation.
      */
-    public void addInvocation(AbstractRequest<?> request) {
+    public void addInvocation(AbstractRequest<?, ?> request) {
       state.invocations.add(request);
       for (Object arg : request.getRequestData().getOrderedParameters()) {
         retainArg(arg);
@@ -557,7 +557,7 @@
 
   @Override
   public <P extends EntityProxy> Request<P> find(final EntityProxyId<P> proxyId) {
-    return new AbstractRequest<P>(this) {
+    return new AbstractRequest<BaseProxy, P>(this) {
       {
         requestContext.addInvocation(this);
       }
@@ -578,7 +578,7 @@
    */
   public void fire() {
     boolean needsReceiver = true;
-    for (AbstractRequest<?> request : state.invocations) {
+    for (AbstractRequest<?, ?> request : state.invocations) {
       if (request.hasReceiver()) {
         needsReceiver = false;
         break;
@@ -693,7 +693,7 @@
   /**
    * Called by generated subclasses to enqueue a method invocation.
    */
-  protected void addInvocation(AbstractRequest<?> request) {
+  protected void addInvocation(AbstractRequest<?, ?> request) {
     state.dialect.addInvocation(request);
   };
 
@@ -736,7 +736,7 @@
     reuse();
     failure.setRequestContext(this);
     Set<Throwable> causes = null;
-    for (AbstractRequest<?> request : new ArrayList<AbstractRequest<?>>(state.invocations)) {
+    for (AbstractRequest<?, ?> request : new ArrayList<AbstractRequest<?, ?>>(state.invocations)) {
       try {
         request.onFail(failure);
       } catch (Throwable t) {
@@ -774,7 +774,7 @@
   protected void violation(final Receiver<Void> receiver, Set<ConstraintViolation<?>> errors) {
     reuse();
     Set<Throwable> causes = null;
-    for (AbstractRequest<?> request : new ArrayList<AbstractRequest<?>>(state.invocations)) {
+    for (AbstractRequest<?, ?> request : new ArrayList<AbstractRequest<?, ?>>(state.invocations)) {
       try {
         request.onViolation(errors);
       } catch (Throwable t) {
@@ -1180,7 +1180,7 @@
     MessageFactory f = MessageFactoryHolder.FACTORY;
 
     List<InvocationMessage> invocationMessages = new ArrayList<InvocationMessage>();
-    for (AbstractRequest<?> invocation : state.invocations) {
+    for (AbstractRequest<?, ?> invocation : state.invocations) {
       // RequestData is produced by the generated subclass
       RequestData data = invocation.getRequestData();
       InvocationMessage message = f.invocation().as();
diff --git a/user/src/com/google/web/bindery/requestfactory/vm/InProcessRequestContext.java b/user/src/com/google/web/bindery/requestfactory/vm/InProcessRequestContext.java
index 86390c8..e382014 100644
--- a/user/src/com/google/web/bindery/requestfactory/vm/InProcessRequestContext.java
+++ b/user/src/com/google/web/bindery/requestfactory/vm/InProcessRequestContext.java
@@ -144,8 +144,8 @@
       }
 
       // Create the request, just filling in the RequestData details
-      final AbstractRequest<Object> req =
-          new AbstractRequest<Object>(InProcessRequestContext.this) {
+      final AbstractRequest<BaseProxy, Object> req =
+          new AbstractRequest<BaseProxy, Object>(InProcessRequestContext.this) {
             @Override
             protected RequestData makeRequestData() {
               data.setPropertyRefs(propertyRefs);