Resolve GWT issue 5364. Enable RequestFactoryPolymorphicTest. Consolidate base-type code in ModelUtils. Patch by: bobv Review by: rjrjr Review at http://gwt-code-reviews.appspot.com/992801 git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9058 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/editor/rebind/AutoBeanFactoryGenerator.java b/user/src/com/google/gwt/editor/rebind/AutoBeanFactoryGenerator.java index f4698bc..0c0dae5 100644 --- a/user/src/com/google/gwt/editor/rebind/AutoBeanFactoryGenerator.java +++ b/user/src/com/google/gwt/editor/rebind/AutoBeanFactoryGenerator.java
@@ -31,13 +31,14 @@ import com.google.gwt.editor.client.AutoBeanVisitor; import com.google.gwt.editor.client.AutoBeanVisitor.PropertyContext; import com.google.gwt.editor.client.impl.AbstractAutoBean; -import com.google.gwt.editor.client.impl.AbstractAutoBeanFactory; import com.google.gwt.editor.client.impl.AbstractAutoBean.OneShotContext; +import com.google.gwt.editor.client.impl.AbstractAutoBeanFactory; import com.google.gwt.editor.rebind.model.AutoBeanFactoryMethod; import com.google.gwt.editor.rebind.model.AutoBeanFactoryModel; import com.google.gwt.editor.rebind.model.AutoBeanMethod; -import com.google.gwt.editor.rebind.model.AutoBeanType; import com.google.gwt.editor.rebind.model.AutoBeanMethod.Action; +import com.google.gwt.editor.rebind.model.AutoBeanType; +import com.google.gwt.editor.rebind.model.ModelUtils; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; import com.google.gwt.user.rebind.SourceWriter; @@ -91,8 +92,8 @@ StringBuilder parameters = new StringBuilder(); for (JParameter param : jmethod.getParameters()) { parameters.append(",").append( - AutoBeanFactoryModel.ensureBaseType(param.getType()).getQualifiedSourceName()).append( - " ").append(param.getName()); + ModelUtils.getQualifiedBaseName(param.getType())).append(" ").append( + param.getName()); } if (parameters.length() > 0) { parameters = parameters.deleteCharAt(0); @@ -102,13 +103,12 @@ if (jmethod.getThrows().length > 0) { for (JType thrown : jmethod.getThrows()) { throwsDeclaration.append(". ").append( - AutoBeanFactoryModel.ensureBaseType(thrown).getQualifiedSourceName()); + ModelUtils.getQualifiedBaseName(thrown)); } throwsDeclaration.deleteCharAt(0); throwsDeclaration.insert(0, "throws "); } - String returnName = AutoBeanFactoryModel.ensureBaseType( - jmethod.getReturnType()).getQualifiedSourceName(); + String returnName = ModelUtils.getQualifiedBaseName(jmethod.getReturnType()); assert !returnName.contains("extends"); return String.format("%s %s(%s) %s", returnName, jmethod.getName(), parameters, throwsDeclaration); @@ -225,9 +225,8 @@ sw.println("}"); } else { // return (ReturnType) values.get(\"foo\"); - sw.println( - "return (%s) values.get(\"%s\");", - AutoBeanFactoryModel.ensureBaseType(jmethod.getReturnType()).getQualifiedSourceName(), + sw.println("return (%s) values.get(\"%s\");", + ModelUtils.getQualifiedBaseName(jmethod.getReturnType()), method.getPropertyName()); } } @@ -411,7 +410,7 @@ // Foo toReturn=FooAutoBean.this.get("getFoo", getWrapped().getFoo()); sw.println( "%s toReturn = %3$s.this.get(\"%2$s\", getWrapped().%2$s());", - AutoBeanFactoryModel.ensureBaseType(jmethod.getReturnType()).getQualifiedSourceName(), + ModelUtils.getQualifiedBaseName(jmethod.getReturnType()), methodName, type.getSimpleSourceName()); // Non-value types might need to be wrapped @@ -442,7 +441,7 @@ // Type toReturn = getWrapped().doFoo(params); sw.println( "%s toReturn = %s.this.getWrapped().%s(%s);", - AutoBeanFactoryModel.ensureBaseType(jmethod.getReturnType()).getQualifiedSourceName(), + ModelUtils.ensureBaseType(jmethod.getReturnType()).getQualifiedSourceName(), type.getSimpleSourceName(), methodName, arguments); // Non-value types might need to be wrapped writeReturnWrapper(sw, type, method);
diff --git a/user/src/com/google/gwt/editor/rebind/model/AutoBeanFactoryModel.java b/user/src/com/google/gwt/editor/rebind/model/AutoBeanFactoryModel.java index 8fac3b2..c8d6646 100644 --- a/user/src/com/google/gwt/editor/rebind/model/AutoBeanFactoryModel.java +++ b/user/src/com/google/gwt/editor/rebind/model/AutoBeanFactoryModel.java
@@ -17,7 +17,6 @@ import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; -import com.google.gwt.core.ext.typeinfo.JArrayType; import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JGenericType; import com.google.gwt.core.ext.typeinfo.JMethod; @@ -47,28 +46,6 @@ public class AutoBeanFactoryModel { private static final JType[] EMPTY_JTYPE = new JType[0]; - @SuppressWarnings("unchecked") - public static <T extends JType> T ensureBaseType(T maybeParameterized) { - if (maybeParameterized.isArray() != null) { - JArrayType array = maybeParameterized.isArray(); - return (T) array.getOracle().getArrayType( - ensureBaseType(array.getComponentType())); - } - if (maybeParameterized.isTypeParameter() != null) { - return (T) maybeParameterized.isTypeParameter().getBaseType(); - } - if (maybeParameterized.isParameterized() != null) { - return (T) maybeParameterized.isParameterized().getBaseType(); - } - if (maybeParameterized.isRawType() != null) { - return (T) maybeParameterized.isRawType().getBaseType(); - } - if (maybeParameterized.isWildcard() != null) { - return (T) maybeParameterized.isWildcard().getBaseType(); - } - return maybeParameterized; - } - private final JGenericType autoBeanInterface; private final JClassType autoBeanFactoryInterface; private final List<JClassType> categoryTypes; @@ -212,7 +189,7 @@ } public AutoBeanType getPeer(JClassType beanType) { - beanType = ensureBaseType(beanType); + beanType = ModelUtils.ensureBaseType(beanType); return peers.get(beanType); } @@ -377,7 +354,7 @@ } private AutoBeanType getAutoBeanType(JClassType beanType) { - beanType = ensureBaseType(beanType); + beanType = ModelUtils.ensureBaseType(beanType); AutoBeanType toReturn = peers.get(beanType); if (toReturn == null) { AutoBeanType.Builder builder = new AutoBeanType.Builder(); @@ -413,7 +390,7 @@ // Check using base types to account for erasure semantics JParameterizedType expectedFirst = oracle.getParameterizedType( - autoBeanInterface, new JClassType[] {ensureBaseType(beanType)}); + autoBeanInterface, new JClassType[] {ModelUtils.ensureBaseType(beanType)}); return expectedFirst.isAssignableTo(paramAsClass); }
diff --git a/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java b/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java index d69f295..1a2c815 100644 --- a/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java +++ b/user/src/com/google/gwt/editor/rebind/model/ModelUtils.java
@@ -1,12 +1,12 @@ /* * 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 @@ -15,6 +15,7 @@ */ package com.google.gwt.editor.rebind.model; +import com.google.gwt.core.ext.typeinfo.JArrayType; import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JParameterizedType; import com.google.gwt.core.ext.typeinfo.JType; @@ -53,6 +54,28 @@ AUTOBOX_MAP = Collections.unmodifiableMap(autoBoxMap); } + @SuppressWarnings("unchecked") + public static <T extends JType> T ensureBaseType(T maybeParameterized) { + if (maybeParameterized.isArray() != null) { + JArrayType array = maybeParameterized.isArray(); + return (T) array.getOracle().getArrayType( + ensureBaseType(array.getComponentType())); + } + if (maybeParameterized.isTypeParameter() != null) { + return (T) maybeParameterized.isTypeParameter().getBaseType(); + } + if (maybeParameterized.isParameterized() != null) { + return (T) maybeParameterized.isParameterized().getBaseType(); + } + if (maybeParameterized.isRawType() != null) { + return (T) maybeParameterized.isRawType().getBaseType(); + } + if (maybeParameterized.isWildcard() != null) { + return (T) maybeParameterized.isWildcard().getBaseType(); + } + return maybeParameterized; + } + public static JClassType[] findParameterizationOf(JClassType intfType, JClassType subType) { assert intfType.isAssignableFrom(subType) : subType.getParameterizedQualifiedSourceName() @@ -71,6 +94,15 @@ return null; } + /** + * Given a JType, return the source name of the class that is most proximately + * assignable to the type. This method will resolve type parameters as well as + * wildcard types. + */ + public static String getQualifiedBaseName(JType type) { + return ensureBaseType(type).getErasedType().getQualifiedSourceName(); + } + public static boolean isValueType(TypeOracle oracle, JType type) { JClassType classType = type.isClassOrInterface(); if (classType == null) {
diff --git a/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java b/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java index bb26a22..53aaeed 100644 --- a/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java +++ b/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java
@@ -23,11 +23,13 @@ import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.JMethod; import com.google.gwt.core.ext.typeinfo.JParameter; +import com.google.gwt.core.ext.typeinfo.JTypeParameter; import com.google.gwt.core.ext.typeinfo.TypeOracle; import com.google.gwt.editor.client.AutoBean; import com.google.gwt.editor.client.AutoBeanFactory; import com.google.gwt.editor.client.AutoBeanFactory.Category; import com.google.gwt.editor.client.AutoBeanFactory.NoWrap; +import com.google.gwt.editor.rebind.model.ModelUtils; import com.google.gwt.requestfactory.client.impl.AbstractRequest; import com.google.gwt.requestfactory.client.impl.AbstractRequestContext; import com.google.gwt.requestfactory.client.impl.AbstractRequestFactory; @@ -158,11 +160,17 @@ StringBuilder parameterArray = new StringBuilder(); // final Foo foo, final Bar bar, final Baz baz StringBuilder parameterDeclaration = new StringBuilder(); + // <P extends Blah> + StringBuilder typeParameterDeclaration = new StringBuilder(); if (request.isInstance()) { // Leave a spot for the using() method to fill in later parameterArray.append(",null"); } + for (JTypeParameter param : jmethod.getTypeParameters()) { + typeParameterDeclaration.append(",").append( + param.getQualifiedSourceName()); + } for (JParameter param : jmethod.getParameters()) { parameterArray.append(",").append(param.getName()); parameterDeclaration.append(",final ").append( @@ -175,15 +183,17 @@ if (parameterDeclaration.length() > 0) { parameterDeclaration.deleteCharAt(0); } + if (typeParameterDeclaration.length() > 0) { + typeParameterDeclaration.deleteCharAt(0).insert(0, "<").append(">"); + } // public Request<Foo> doFoo(final Foo foo) { - sw.println("public %s %s(%s) {", + sw.println("public %s %s %s(%s) {", typeParameterDeclaration, jmethod.getReturnType().getParameterizedQualifiedSourceName(), jmethod.getName(), parameterDeclaration); sw.indent(); - // Have to cover the old Request sub-interfaces - // TODO: ProxyListRequest et al. be removed? - // class X extends AbstractRequest<Return> implements ReturnType { + // 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(), @@ -221,16 +231,19 @@ // decodeReturnObjectList(FooEntityProxy.class,obj, (List)decoded); String decodeMethod = request.isValueType() ? "decodeReturnValueList" : "decodeReturnObjectList"; - sw.println("%s(%s.class, obj, (%s)decoded);", decodeMethod, - request.getCollectionElementType().getQualifiedSourceName(), + sw.println( + "%s(%s.class, obj, (%s)decoded);", + decodeMethod, + ModelUtils.getQualifiedBaseName(request.getCollectionElementType()), collectionType.getCanonicalName()); } else if (request.isValueType()) { // decoded = ValueCodex.cFString(Integer.class, String.valueOf(obj)); sw.println( "decoded = %s.convertFromString(%s.class, String.valueOf(obj));", ValueCodex.class.getCanonicalName(), - request.getDataType().getQualifiedSourceName()); + ModelUtils.getQualifiedBaseName(request.getDataType())); } else if (request.isEntityType()) { + // Implicitly erased sw.println("decoded = decodeReturnObject(%s.class, obj);", request.getEntityType().getQualifiedSourceName()); } else {
diff --git a/user/src/com/google/gwt/requestfactory/rebind/model/EntityProxyModel.java b/user/src/com/google/gwt/requestfactory/rebind/model/EntityProxyModel.java index 418448a..52989d1 100644 --- a/user/src/com/google/gwt/requestfactory/rebind/model/EntityProxyModel.java +++ b/user/src/com/google/gwt/requestfactory/rebind/model/EntityProxyModel.java
@@ -49,6 +49,7 @@ } public void setQualifiedSourceName(String name) { + assert !name.contains(" "); toReturn.qualifiedSourceName = name; }
diff --git a/user/src/com/google/gwt/requestfactory/rebind/model/RequestFactoryModel.java b/user/src/com/google/gwt/requestfactory/rebind/model/RequestFactoryModel.java index 9165f71..6684536 100644 --- a/user/src/com/google/gwt/requestfactory/rebind/model/RequestFactoryModel.java +++ b/user/src/com/google/gwt/requestfactory/rebind/model/RequestFactoryModel.java
@@ -1,12 +1,12 @@ /* * 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 @@ -164,8 +164,8 @@ contextType.getQualifiedSourceName(), Service.class.getSimpleName()); return; } - Class<?> serviceClass = serviceAnnotation.value(); - contextBuilder.setServiceClass(serviceClass); + Class<?> serviceClass = serviceAnnotation.value(); + contextBuilder.setServiceClass(serviceClass); List<RequestMethod> requestMethods = new ArrayList<RequestMethod>(); for (JMethod method : contextType.getInheritableMethods()) { @@ -177,7 +177,8 @@ RequestMethod.Builder methodBuilder = new RequestMethod.Builder(); methodBuilder.setDeclarationMethod(method); - if (!validateContextMethodAndSetDataType(methodBuilder, method, serviceClass)) { + if (!validateContextMethodAndSetDataType(methodBuilder, method, + serviceClass)) { continue; } @@ -208,6 +209,7 @@ private EntityProxyModel getEntityProxyType(JClassType entityProxyType) throws UnableToCompleteException { + entityProxyType = ModelUtils.ensureBaseType(entityProxyType); EntityProxyModel toReturn = peers.get(entityProxyType); if (toReturn == null) { EntityProxyModel.Builder inProgress = peerBuilders.get(entityProxyType); @@ -219,7 +221,7 @@ EntityProxyModel.Builder builder = new EntityProxyModel.Builder(); peerBuilders.put(entityProxyType, builder); - builder.setQualifiedSourceName(entityProxyType.getQualifiedSourceName()); + builder.setQualifiedSourceName(ModelUtils.getQualifiedBaseName(entityProxyType)); // Get the server domain object type ProxyFor proxyFor = entityProxyType.getAnnotation(ProxyFor.class); @@ -301,7 +303,7 @@ * Examine a RequestContext method to see if it returns a transportable type. */ private boolean validateContextMethodAndSetDataType( - RequestMethod.Builder methodBuilder, JMethod method, Class<?> serviceClass) + RequestMethod.Builder methodBuilder, JMethod method, Class<?> serviceClass) throws UnableToCompleteException { JClassType requestReturnType = method.getReturnType().isInterface(); JClassType invocationReturnType; @@ -313,12 +315,11 @@ } /* - * TODO: bad assumption - * Implicit assumption is that the Service and ProxyFor + * TODO: bad assumption Implicit assumption is that the Service and ProxyFor * classes are the same. This is because an instance method should - * technically be looked up on the class that is the instance parameter, - * and not on the serviceClass, which consists of static service methods. - * Can't be fixed until it is fixed in JsonRequestProcessor. + * technically be looked up on the class that is the instance parameter, and + * not on the serviceClass, which consists of static service methods. Can't + * be fixed until it is fixed in JsonRequestProcessor. */ Method domainMethod = validateExistsAndNotOverriden(method, serviceClass, false); @@ -330,8 +331,7 @@ if (isStatic(domainMethod)) { poison("Method %s.%s is an instance method, " + "while the corresponding method on %s is static", - method.getEnclosingType().getName(), - method.getName(), + method.getEnclosingType().getName(), method.getName(), serviceClass.getName()); return false; } @@ -344,8 +344,7 @@ if (!isStatic(domainMethod)) { poison("Method %s.%s is a static method, " + "while the corresponding method on %s is not", - method.getEnclosingType().getName(), - method.getName(), + method.getEnclosingType().getName(), method.getName(), serviceClass.getName()); return false; } @@ -367,8 +366,7 @@ Class<?>[] domainParams = domainMethod.getParameterTypes(); if (params.length != domainParams.length) { poison("Method %s.%s parameters do not match same method on %s", - method.getEnclosingType().getName(), - method.getName(), + method.getEnclosingType().getName(), method.getName(), serviceClass.getName()); } for (int i = 0; i < params.length; ++i) { @@ -377,16 +375,14 @@ paramsOk = validateTransportableType(new RequestMethod.Builder(), param.getType(), false) && paramsOk; - paramsOk = validateProxyAndDomainTypeEquals(param.getType(), domainParam, i, - methodLocation(method), methodLocation(domainMethod)) - && paramsOk; + paramsOk = validateProxyAndDomainTypeEquals(param.getType(), domainParam, + i, methodLocation(method), methodLocation(domainMethod)) && paramsOk; } return validateTransportableType(methodBuilder, invocationReturnType, true) && validateProxyAndDomainTypeEquals(invocationReturnType, - domainMethod.getReturnType(), -1, methodLocation(method), - methodLocation(domainMethod)) - && paramsOk; + domainMethod.getReturnType(), -1, methodLocation(method), + methodLocation(domainMethod)) && paramsOk; } /** @@ -397,8 +393,8 @@ JMethod proxyMethod = requestMethod.getDeclarationMethod(); // check if method exists on domain object Class<?> domainType = entityBuilder.peek().getProxyFor(); - Method domainMethod = validateExistsAndNotOverriden(proxyMethod, domainType, - true); + Method domainMethod = validateExistsAndNotOverriden(proxyMethod, + domainType, true); if (domainMethod == null) { return false; } @@ -408,27 +404,24 @@ // compare return type of domain to proxy return type String returnTypeName = domainMethod.getReturnType().getName(); // isEntityType() returns true for collections, but we want the Collection - String propertyTypeName = - requestMethod.isCollectionType() || requestMethod.isValueType() ? - requestMethod.getDataType().getQualifiedBinaryName() : - requestMethod.getEntityType().getProxyFor().getName(); + String propertyTypeName = requestMethod.isCollectionType() + || requestMethod.isValueType() + ? requestMethod.getDataType().getQualifiedBinaryName() + : requestMethod.getEntityType().getProxyFor().getName(); if (!returnTypeName.equals(propertyTypeName)) { - poison("Method %s.%s return type %s does not match return type %s " - + " of method %s.%s", domainType.getName(), - domainMethod.getName(), returnTypeName, - propertyTypeName, - proxyMethod.getEnclosingType().getName(), proxyMethod.getName()); + poison("Method %s.%s return type %s does not match return type %s " + + " of method %s.%s", domainType.getName(), domainMethod.getName(), + returnTypeName, propertyTypeName, + proxyMethod.getEnclosingType().getName(), proxyMethod.getName()); return false; } } JParameter[] proxyParams = proxyMethod.getParameters(); Class<?>[] domainParams = domainMethod.getParameterTypes(); if (proxyParams.length != domainParams.length) { - poison("Method %s.%s parameter mismatch with %s.%s", - proxyMethod.getEnclosingType().getName(), - proxyMethod.getName(), - domainType.getName(), - domainMethod.getName()); + poison("Method %s.%s parameter mismatch with %s.%s", + proxyMethod.getEnclosingType().getName(), proxyMethod.getName(), + domainType.getName(), domainMethod.getName()); return false; } for (int i = 0; i < proxyParams.length; i++) { @@ -436,11 +429,9 @@ Class<?> domainParam = domainParams[i]; if (!validateProxyAndDomainTypeEquals(proxyParam, domainParam, i, methodLocation(proxyMethod), methodLocation(domainMethod))) { - poison("Parameter %d of %s.%s doesn't match method %s.%s", - i, proxyMethod.getEnclosingType().getName(), - proxyMethod.getName(), - domainType.getName(), - domainMethod.getName()); + poison("Parameter %d of %s.%s doesn't match method %s.%s", i, + proxyMethod.getEnclosingType().getName(), proxyMethod.getName(), + domainType.getName(), domainMethod.getName()); return false; } } @@ -452,16 +443,17 @@ */ private boolean validateDomainType(Class<?> domainType) { try { - domainType.getMethod("getId"); + domainType.getMethod("getId"); } catch (NoSuchMethodException e) { - poison("The class %s is missing method getId()", domainType.getName()); - return false; + poison("The class %s is missing method getId()", domainType.getName()); + return false; } try { - domainType.getMethod("getVersion"); + domainType.getMethod("getVersion"); } catch (NoSuchMethodException e) { - poison("The class %s is missing method getVersion()", domainType.getName()); - return false; + poison("The class %s is missing method getVersion()", + domainType.getName()); + return false; } return true; } @@ -502,18 +494,18 @@ // allow int to match int or Integer matchOk = proxyType.getQualifiedSourceName().equals( ModelUtils.maybeAutobox(domainType).getName()) - || proxyType.getQualifiedSourceName().equals(domainType.getName()); + || proxyType.getQualifiedSourceName().equals(domainType.getName()); } else { - matchOk = getEntityProxyType( - proxyType.isClassOrInterface()).getProxyFor().equals(domainType); + matchOk = getEntityProxyType(proxyType.isClassOrInterface()).getProxyFor().equals( + domainType); } if (!matchOk) { if (paramNumber < 0) { - poison("Return type of method %s does not match method %s", clientMethod, - serverMethod); + poison("Return type of method %s does not match method %s", + clientMethod, serverMethod); } else { - poison("Parameter %d of method %s does not match method %s", - paramNumber, clientMethod, serverMethod); + poison("Parameter %d of method %s does not match method %s", + paramNumber, clientMethod, serverMethod); } } return matchOk;
diff --git a/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java b/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java index 44de728..d4ec7e4 100644 --- a/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java +++ b/user/test/com/google/gwt/requestfactory/RequestFactorySuite.java
@@ -18,6 +18,7 @@ import com.google.gwt.junit.tools.GWTTestSuite; import com.google.gwt.requestfactory.client.FindServiceTest; import com.google.gwt.requestfactory.client.RequestFactoryExceptionHandlerTest; +import com.google.gwt.requestfactory.client.RequestFactoryPolymorphicTest; import com.google.gwt.requestfactory.client.RequestFactoryStringTest; import com.google.gwt.requestfactory.client.RequestFactoryTest; import com.google.gwt.requestfactory.client.ui.EditorTest; @@ -35,6 +36,7 @@ suite.addTestSuite(RequestFactoryTest.class); suite.addTestSuite(RequestFactoryStringTest.class); suite.addTestSuite(RequestFactoryExceptionHandlerTest.class); + suite.addTestSuite(RequestFactoryPolymorphicTest.class); suite.addTestSuite(FindServiceTest.class); return suite; }