diff --git a/jode/jode/type/ArrayType.java b/jode/jode/type/ArrayType.java index d7357e1..e67a7e5 100644 --- a/jode/jode/type/ArrayType.java +++ b/jode/jode/type/ArrayType.java @@ -17,6 +17,8 @@ * $Id$ */ package jode; +import jode.bytecode.ClassInfo; +import java.util.Vector; /** * This type represents an array type. @@ -24,6 +26,14 @@ package jode; * @author Jochen Hoenicke */ public class ArrayType extends Type { + // The interfaces that an array implements: + final static ClassInfo[] ifaces = { + // Make sure to list all interfaces, even if some interface + // implements another (or change code in getGeneralizedType(). + ClassInfo.forName("java.lang.Cloneable"), + ClassInfo.forName("java.io.Serializable") + }; + Type elementType; public ArrayType(Type elementType) { @@ -43,6 +53,19 @@ public class ArrayType extends Type { return tArray(elementType.getTop()); } + static boolean implementsAllIfaces(ClassInfo[] otherIfaces) { + big: + for (int i=0; i < otherIfaces.length; i++) { + ClassInfo iface = otherIfaces[i]; + for (int j=0; j < ifaces.length; j++) { + if (iface.implementedBy(ifaces[j])) + continue big; + } + return false; + } + return true; + } + /** * Create the type corresponding to the range from bottomType to this. * @param bottomType the start point of the range @@ -50,15 +73,24 @@ public class ArrayType extends Type { */ public Type createRangeType(Type bottomType) { /* tUnknown , tArray(x) -> - * tObject , tArray(x) -> + * obj , tArray(x) -> + * iff tArray extends and implements obj * tArray(y), tArray(x) -> tArray( ) */ - return (bottomType == tUnknown || bottomType == tObject) - ? tRange(tObject, this) - : (bottomType.typecode == TC_ARRAY) - ? tArray(elementType.createRangeType - (((ArrayType)bottomType).elementType)) - : tError; + if (bottomType == tUnknown || bottomType == tObject) + return tRange(tObject, this); + + if (bottomType instanceof ClassInterfacesType) { + ClassInterfacesType bottom = (ClassInterfacesType) bottomType; + if (bottom.clazz == null + && implementsAllIfaces(bottom.ifaces)) + return tRange(bottom, this); + return tError; + } + return (bottomType.typecode == TC_ARRAY) + ? tArray(elementType.createRangeType + (((ArrayType)bottomType).elementType)) + : tError; } /** @@ -72,9 +104,17 @@ public class ArrayType extends Type { * tArray(x), tArray(y) -> tArray(x.getSpecialized(y)) * tArray(x), other -> tError */ - return (type == tUnknown || type == tObject) - ? this - : (type.getTypeCode() == TC_ARRAY) + if (type == tUnknown || type == tObject) + return this; + + if (type instanceof ClassInterfacesType) { + ClassInterfacesType other = (ClassInterfacesType) type; + if (other.clazz == null + && implementsAllIfaces(other.ifaces)) + return this; + return tError; + } + return (type.getTypeCode() == TC_ARRAY) ? tArray(elementType.getSpecializedType (((ArrayType)type).elementType)) : tError; @@ -91,18 +131,93 @@ public class ArrayType extends Type { * tArray(x), tArray(y) -> tArray(x.getGeneralized(y)) * tArray(x), other -> tError */ - return (type == tUnknown) - ? this - : (type.getTypeCode() == TC_CLASS) - ? tObject - : (type.getTypeCode() == TC_ARRAY) - ? tArray(elementType.getGeneralizedType - (((ArrayType)type).elementType)) - : tError; + if (type == tUnknown) + return this; + if (type.getTypeCode() == TC_ARRAY) + return tArray(elementType.getGeneralizedType + (((ArrayType)type).elementType)); + + if (type.getTypeCode() == TC_CLASS) { + ClassInterfacesType other = (ClassInterfacesType) type; + if (implementsAllIfaces(other.ifaces)) { + if (other.clazz == null) + return other; + else + return ClassInterfacesType.create(null, other.ifaces); + } + + if (other.implementsAllIfaces(ifaces)) + return ClassInterfacesType.create(null, ifaces); + + /* Now the more complicated part: find all interfaces, that are + * implemented by one interface or class in each group. + * + * First get all interfaces of this.clazz and this.ifaces. + */ + Vector newIfaces = new Vector(); + iface_loop: + for (int i=0; i < ifaces.length; i++) { + /* Now consider each array interface. If any clazz or + * interface in other implements it, add it to the + * newIfaces vector. */ + if (other.clazz != null + && ifaces[i].implementedBy(other.clazz)) { + newIfaces.addElement(ifaces[i]); + continue iface_loop; + } + for (int j=0; j