Revision: 7343 Author: [email protected] Date: Mon Dec 21 10:20:58 2009 Log: Fixes issue 1822. Arrays now implement Serializable and Cloneable.
Review by: scottb http://code.google.com/p/google-web-toolkit/source/detail?r=7343 Modified: /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java /trunk/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java /trunk/user/test/com/google/gwt/dev/jjs/test/ClassCastTest.java ======================================= --- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java Wed Dec 9 09:10:40 2009 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java Mon Dec 21 10:20:58 2009 @@ -71,10 +71,10 @@ public static final Set<String> INDEX_TYPES_SET = new LinkedHashSet<String>( Arrays.asList(new String[] { - "java.lang.Object", "java.lang.String", "java.lang.Class", - "java.lang.CharSequence", "java.lang.Comparable", "java.lang.Enum", - "java.lang.Iterable", "java.util.Iterator", - "com.google.gwt.core.client.GWT", + "java.io.Serializable", "java.lang.Object", "java.lang.String", + "java.lang.Class", "java.lang.CharSequence", "java.lang.Cloneable", + "java.lang.Comparable", "java.lang.Enum", "java.lang.Iterable", + "java.util.Iterator", "com.google.gwt.core.client.GWT", "com.google.gwt.core.client.JavaScriptObject", "com.google.gwt.lang.ClassLiteralHolder", "com.google.gwt.core.client.RunAsyncCallback", @@ -313,6 +313,10 @@ private Map<JReferenceType, Integer> typeIdMap = new HashMap<JReferenceType, Integer>(); + private JInterfaceType typeJavaIoSerializable; + + private JInterfaceType typeJavaLangCloneable; + private JClassType typeJavaLangEnum; private JClassType typeJavaLangObject; @@ -334,10 +338,10 @@ /** * Constructor. * - * @param enableSourceInfoDescendants Controls whether or not SourceInfo nodes - * created via the JProgram will record descendant information. - * Enabling this feature will collect extra data during the - * compilation cycle, but at a cost of memory and object allocations. + * @param correlator Controls whether or not SourceInfo nodes created via the + * JProgram will record descendant information. Enabling this feature + * will collect extra data during the compilation cycle, but at a + * cost of memory and object allocations. */ public JProgram(CorrelationFactory correlator) { super(correlator.makeSourceInfo(SourceOrigin.create(0, @@ -467,6 +471,11 @@ if (INDEX_TYPES_SET.contains(sname)) { indexedTypes.put(x.getShortName(), x); + if (sname.equals("java.lang.Cloneable")) { + typeJavaLangCloneable = x; + } else if (sname.equals("java.io.Serializable")) { + typeJavaIoSerializable = x; + } } return x; @@ -720,6 +729,9 @@ // unrelated return typeJavaLangObject; + } else if (greater == IS_ARRAY + && ((tLesser == typeJavaLangCloneable) || (tLesser == typeJavaIoSerializable))) { + return tLesser; } else { // unrelated: the best commonality between an interface and array, or ======================================= --- /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java Wed Dec 9 09:10:40 2009 +++ /trunk/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java Mon Dec 21 10:20:58 2009 @@ -262,6 +262,9 @@ */ private final Map<JMethod, Map<JClassType, Set<JMethod>>> virtualUpRefMap = new IdentityHashMap<JMethod, Map<JClassType, Set<JMethod>>>(); + private JDeclaredType javaIoSerializable; + private JDeclaredType javaLangCloneable; + public JTypeOracle(JProgram program) { this.program = program; } @@ -310,6 +313,12 @@ } } + /* + * Warning: If this code is ever updated to consider casts of array types + * to interface types, then be sure to consider that casting an array to + * Serializable and Cloneable succeeds. Currently all casts of an array to + * an interface return true, which is overly conservative but is safe. + */ } else if (type instanceof JClassType) { JClassType cType = (JClassType) type; @@ -369,6 +378,10 @@ } } } + + if (qType == javaIoSerializable || qType == javaLangCloneable) { + return true; + } } else if (type instanceof JClassType) { JClassType cType = (JClassType) type; @@ -402,6 +415,9 @@ public void computeBeforeAST() { javaLangObject = program.getTypeJavaLangObject(); + javaIoSerializable = program.getFromTypeMap(Serializable.class.getName()); + javaLangCloneable = program.getFromTypeMap(Cloneable.class.getName()); + superClassMap.clear(); subClassMap.clear(); superInterfaceMap.clear(); ======================================= --- /trunk/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java Wed Dec 9 09:10:40 2009 +++ /trunk/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java Mon Dec 21 10:20:58 2009 @@ -64,6 +64,8 @@ private SourceInfo synthSource; private JReferenceType typeNull; private JTypeOracle typeOracle; + private JReferenceType intfSerializable; + private JReferenceType intfCloneable; public void testCanTheoreticallyCast() { assertFalse(typeOracle.canTheoreticallyCast(classBnn, typeNull)); @@ -90,6 +92,12 @@ assertTrue(typeOracle.canTheoreticallyCast(intfIBase, classBase)); assertFalse(typeOracle.canTheoreticallyCast(intfJ, classA)); + + assertTrue(typeOracle.canTheoreticallyCast(arrayOfA, intfSerializable)); + assertTrue(typeOracle.canTheoreticallyCast(intfSerializable, arrayOfA)); + + assertTrue(typeOracle.canTheoreticallyCast(arrayOfA, intfCloneable)); + assertTrue(typeOracle.canTheoreticallyCast(intfCloneable, arrayOfA)); } public void testCanTriviallyCast() { @@ -133,6 +141,12 @@ assertTrue(typeOracle.canTriviallyCast(classJso, classJso1)); assertTrue(typeOracle.canTriviallyCast(classJso, classJso1)); + + assertTrue(typeOracle.canTriviallyCast(arrayOfA, intfSerializable)); + assertFalse(typeOracle.canTriviallyCast(intfSerializable, arrayOfA)); + + assertTrue(typeOracle.canTriviallyCast(arrayOfA, intfCloneable)); + assertFalse(typeOracle.canTriviallyCast(intfCloneable, arrayOfA)); /* * Test that two types cannot both be trivially castable to each other, @@ -172,6 +186,9 @@ assertSame(classObject, generalizeTypes(intfI, arrayOfInt)); + assertSame(intfSerializable, generalizeTypes(intfSerializable, arrayOfA)); + assertSame(intfCloneable, generalizeTypes(intfCloneable, arrayOfA)); + for (JReferenceType type1 : severalTypes()) { for (JReferenceType type2 : severalTypes()) { JReferenceType generalized = generalizeTypes(type1, type2); @@ -187,6 +204,8 @@ assertSame(classB, program.strongerType(classB, classBase)); assertSame(classB, program.strongerType(classBase, classB)); assertSame(intfI, program.strongerType(intfI, intfJ)); + assertSame(arrayOfA, program.strongerType(intfSerializable, arrayOfA)); + assertSame(arrayOfA, program.strongerType(intfCloneable, arrayOfA)); } @Override @@ -220,6 +239,9 @@ classJso = createClass("com.google.gwt.core.client.JavaScriptObject", classObject, false, false); + intfSerializable = createInterface("java.io.Serializable"); + intfCloneable = createInterface("java.lang.Cloneable"); + intfIBase = createInterface("IBase"); intfI = createInterface("I"); ======================================= --- /trunk/user/test/com/google/gwt/dev/jjs/test/ClassCastTest.java Wed Sep 3 13:46:24 2008 +++ /trunk/user/test/com/google/gwt/dev/jjs/test/ClassCastTest.java Mon Dec 21 10:20:58 2009 @@ -16,9 +16,12 @@ package com.google.gwt.dev.jjs.test; import com.google.gwt.junit.client.GWTTestCase; +import com.google.gwt.user.client.ui.Widget; + +import java.io.Serializable; /** - * TODO: document me. + * Test type casts and <code>instanceof</code>. */ @SuppressWarnings("unused") public class ClassCastTest extends GWTTestCase { @@ -32,13 +35,26 @@ static abstract class Food { } - private final Food foodItem = new Apple(); - - private final CanEatRaw rawFoodItem = new Apple(); - + private volatile Object arrayOfInt = new int[3]; + private volatile Object arrayOfWidget = new Widget[4]; + private volatile Food foodItem = new Apple(); + private volatile CanEatRaw rawFoodItem = new Apple(); + + @Override public String getModuleName() { return "com.google.gwt.dev.jjs.CompilerSuite"; } + + public void testArrayInterfaces() { + assertTrue(arrayOfInt instanceof Serializable); + assertTrue(arrayOfWidget instanceof Serializable); + + assertTrue(arrayOfInt instanceof Cloneable); + assertTrue(arrayOfWidget instanceof Cloneable); + + assertFalse(arrayOfInt instanceof Food); + assertFalse(arrayOfWidget instanceof Food); + } public void testBaseToInterface() { Apple apple = (Apple) foodItem; -- http://groups.google.com/group/Google-Web-Toolkit-Contributors
