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);