|
|
|
@ -33,24 +33,23 @@ import java.util.Stack; |
|
|
|
|
* interfaces or the class type or any of their super types. |
|
|
|
|
* |
|
|
|
|
* @author Jochen Hoenicke */ |
|
|
|
|
public class ClassInterfacesType extends MyType { |
|
|
|
|
public class ClassInterfacesType extends Type { |
|
|
|
|
|
|
|
|
|
Class clazz; |
|
|
|
|
Class ifaces[]; |
|
|
|
|
|
|
|
|
|
public final static Class cObject = new Object().getClass(); |
|
|
|
|
|
|
|
|
|
public ClassInterfacesType(Type clazzType) { |
|
|
|
|
super(104, "{"+clazzType.getTypeSignature()+"}"); |
|
|
|
|
public ClassInterfacesType(String clazzName) { |
|
|
|
|
super(TC_CLASS); |
|
|
|
|
try { |
|
|
|
|
Class cdecl = |
|
|
|
|
Class.forName(clazzType.getClassName().toString()); |
|
|
|
|
if (cdecl.isInterface()) { |
|
|
|
|
clazz = cObject; |
|
|
|
|
Class clazz = Class.forName(clazzName); |
|
|
|
|
if (clazz.isInterface()) { |
|
|
|
|
this.clazz = cObject; |
|
|
|
|
ifaces = new Class[1]; |
|
|
|
|
ifaces[0] = cdecl; |
|
|
|
|
ifaces[0] = clazz; |
|
|
|
|
} else { |
|
|
|
|
clazz = cdecl; |
|
|
|
|
this.clazz = clazz; |
|
|
|
|
ifaces = new Class[0]; |
|
|
|
|
} |
|
|
|
|
} catch (ClassNotFoundException ex) { |
|
|
|
@ -58,20 +57,31 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public ClassInterfacesType(Class clazz, |
|
|
|
|
Class[] ifaces) { |
|
|
|
|
super(104, "{}"); |
|
|
|
|
StringBuffer sig = new StringBuffer("{"); |
|
|
|
|
if (clazz != null) |
|
|
|
|
sig.append("L").append(clazz.getName()).append(";"); |
|
|
|
|
for (int i=0;i < ifaces.length; i++) |
|
|
|
|
sig.append("L").append(ifaces[i].getName()).append(";"); |
|
|
|
|
sig.append("}"); |
|
|
|
|
typeSig = sig.toString(); |
|
|
|
|
public ClassInterfacesType(Class clazz) { |
|
|
|
|
super(TC_CLASS); |
|
|
|
|
if (clazz.isInterface()) { |
|
|
|
|
this.clazz = cObject; |
|
|
|
|
ifaces = new Class[1]; |
|
|
|
|
ifaces[0] = clazz; |
|
|
|
|
} else { |
|
|
|
|
this.clazz = clazz; |
|
|
|
|
ifaces = new Class[0]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public ClassInterfacesType(Class clazz, Class[] ifaces) { |
|
|
|
|
super(TC_CLASS); |
|
|
|
|
this.clazz = clazz; |
|
|
|
|
this.ifaces = ifaces; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static Type create(Class clazz, Class[] ifaces) { |
|
|
|
|
/* Make sure that every {java.lang.Object} equals tObject */ |
|
|
|
|
if (ifaces.length == 0 && (clazz == cObject || clazz == null)) |
|
|
|
|
return tObject; |
|
|
|
|
return new ClassInterfacesType(clazz, ifaces); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public final static boolean superClassOf(Class parent, Class clazz) { |
|
|
|
|
while (clazz != parent && clazz != null) { |
|
|
|
|
clazz = clazz.getSuperclass(); |
|
|
|
@ -92,40 +102,51 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Checks if the given type range may be not empty. |
|
|
|
|
* This means, that bottom.clazz is extended by top.clazz |
|
|
|
|
* and that all interfaces in bottom are implemented by an |
|
|
|
|
* interface or by top.clazz. <p> |
|
|
|
|
* |
|
|
|
|
* if that is true, a class range type is created, otherwise |
|
|
|
|
* tError is returned. |
|
|
|
|
* Create the type corresponding to the range from bottomType to |
|
|
|
|
* this. Checks if the given type range may be not empty. This |
|
|
|
|
* means, that bottom.clazz is extended by this.clazz and that all |
|
|
|
|
* interfaces in bottom are implemented by an interface or by |
|
|
|
|
* clazz. |
|
|
|
|
* @param bottom the start point of the range |
|
|
|
|
* @return the range type, or tError if range is empty. |
|
|
|
|
*/ |
|
|
|
|
public final static Type createRangeType(ClassInterfacesType bottom, |
|
|
|
|
ClassInterfacesType top) { |
|
|
|
|
public Type createRangeType(Type bottomType) { |
|
|
|
|
|
|
|
|
|
if (bottomType == tUnknown || bottomType == tObject) |
|
|
|
|
return (this == tObject) ? tObject : tRange(tObject, this); |
|
|
|
|
|
|
|
|
|
if (bottomType.typecode != TC_CLASS) |
|
|
|
|
return tError; |
|
|
|
|
|
|
|
|
|
ClassInterfacesType bottom = (ClassInterfacesType) bottomType; |
|
|
|
|
|
|
|
|
|
if (bottom.clazz != null |
|
|
|
|
&& bottom.clazz != cObject) { |
|
|
|
|
/* The searched type must be a class type. |
|
|
|
|
*/ |
|
|
|
|
if (top.ifaces.length != 0 |
|
|
|
|
|| !superClassOf(bottom.clazz,top.clazz)) |
|
|
|
|
if (this.ifaces.length != 0 |
|
|
|
|
|| !superClassOf(bottom.clazz,this.clazz)) |
|
|
|
|
return tError; |
|
|
|
|
|
|
|
|
|
/* All interfaces must be implemented by top.clazz |
|
|
|
|
/* All interfaces must be implemented by this.clazz |
|
|
|
|
*/ |
|
|
|
|
for (int i=0; i < bottom.ifaces.length; i++) { |
|
|
|
|
if (!implementedBy(bottom.ifaces[i], top.clazz)) |
|
|
|
|
if (!implementedBy(bottom.ifaces[i], this.clazz)) |
|
|
|
|
return tError; |
|
|
|
|
} |
|
|
|
|
return new ClassRangeType |
|
|
|
|
(bottom, new ClassInterfacesType(top.clazz, |
|
|
|
|
new Class[0])); |
|
|
|
|
|
|
|
|
|
if (bottom.clazz == this.clazz |
|
|
|
|
&& bottom.ifaces.length == 0) |
|
|
|
|
return bottom; |
|
|
|
|
|
|
|
|
|
return tRange(bottom, create(this.clazz, new Class[0])); |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
/* Now bottom.clazz is null, find all top.class/interfaces |
|
|
|
|
* that implement all bottom.ifaces. |
|
|
|
|
/* Now bottom.clazz is null (or tObject), find all |
|
|
|
|
* classes/interfaces that implement all bottom.ifaces. |
|
|
|
|
*/ |
|
|
|
|
Class clazz = top.clazz; |
|
|
|
|
Class clazz = this.clazz; |
|
|
|
|
if (clazz != null) { |
|
|
|
|
for (int i=0; i < bottom.ifaces.length; i++) { |
|
|
|
|
if (!implementedBy(bottom.ifaces[i], clazz)) { |
|
|
|
@ -136,46 +157,60 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
} |
|
|
|
|
Vector ifaces = new Vector(); |
|
|
|
|
big_loop: |
|
|
|
|
for (int j=0; j < top.ifaces.length; j++) { |
|
|
|
|
for (int j=0; j < this.ifaces.length; j++) { |
|
|
|
|
for (int i=0; i < bottom.ifaces.length; i++) { |
|
|
|
|
if (!implementedBy(bottom.ifaces[i], top.ifaces[j])) |
|
|
|
|
if (!implementedBy(bottom.ifaces[i], this.ifaces[j])) |
|
|
|
|
continue big_loop; |
|
|
|
|
} |
|
|
|
|
ifaces.addElement(top.ifaces[j]); |
|
|
|
|
ifaces.addElement(this.ifaces[j]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* If bottom and the new top are the same single interface
|
|
|
|
|
* return it. |
|
|
|
|
*/ |
|
|
|
|
if (clazz == null |
|
|
|
|
&& bottom.ifaces.length == 1 && ifaces.size() == 1 |
|
|
|
|
&& bottom.ifaces[0] == ifaces.elementAt(0)) |
|
|
|
|
return bottom; |
|
|
|
|
|
|
|
|
|
Class[] ifaceArray = |
|
|
|
|
new Class[ifaces.size()]; |
|
|
|
|
ifaces.copyInto(ifaceArray); |
|
|
|
|
return new ClassRangeType |
|
|
|
|
(bottom, new ClassInterfacesType(clazz, ifaceArray)); |
|
|
|
|
return tRange(bottom, create(clazz, ifaceArray)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns the specialized type of t1 and t2. |
|
|
|
|
* Returns the specialized type of this and type. |
|
|
|
|
* We have two classes and multiple interfaces. The result |
|
|
|
|
* should be the object that is the the child of both objects |
|
|
|
|
* and the union of all interfaces. |
|
|
|
|
*/ |
|
|
|
|
public static Type getSpecializedType(ClassInterfacesType t1, |
|
|
|
|
ClassInterfacesType t2) { |
|
|
|
|
public Type getSpecializedType(Type type) { |
|
|
|
|
|
|
|
|
|
if (type.getTypeCode() == TC_UNKNOWN) |
|
|
|
|
return this; |
|
|
|
|
if (type.getTypeCode() == TC_ARRAY && this == tObject) |
|
|
|
|
return type; |
|
|
|
|
if (type.getTypeCode() != TC_CLASS) |
|
|
|
|
return tError; |
|
|
|
|
|
|
|
|
|
ClassInterfacesType other = (ClassInterfacesType) type; |
|
|
|
|
Class clazz = null; |
|
|
|
|
Vector ifaces = new Vector(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* First determine the clazz, one of the two classes must be a sub |
|
|
|
|
* class of the other or null. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
if (t1.clazz == null) |
|
|
|
|
clazz = t2.clazz; |
|
|
|
|
else if (t2.clazz == null) |
|
|
|
|
clazz = t1.clazz; |
|
|
|
|
else if (superClassOf(t1.clazz, t2.clazz)) |
|
|
|
|
clazz = t2.clazz; |
|
|
|
|
else if (superClassOf(t2.clazz, t1.clazz)) |
|
|
|
|
clazz = t1.clazz; |
|
|
|
|
if (this.clazz == null) |
|
|
|
|
clazz = other.clazz; |
|
|
|
|
else if (other.clazz == null) |
|
|
|
|
clazz = this.clazz; |
|
|
|
|
else if (superClassOf(this.clazz, other.clazz)) |
|
|
|
|
clazz = other.clazz; |
|
|
|
|
else if (superClassOf(other.clazz, this.clazz)) |
|
|
|
|
clazz = this.clazz; |
|
|
|
|
else |
|
|
|
|
return tError; |
|
|
|
|
|
|
|
|
@ -183,15 +218,15 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
* But we can simplify this, if an interface is implemented by |
|
|
|
|
* another or by the class, we can omit it. |
|
|
|
|
*/ |
|
|
|
|
big_loop_t1: |
|
|
|
|
for (int i=0; i< t1.ifaces.length; i++) { |
|
|
|
|
Class iface = t1.ifaces[i]; |
|
|
|
|
big_loop_this: |
|
|
|
|
for (int i=0; i< this.ifaces.length; i++) { |
|
|
|
|
Class iface = this.ifaces[i]; |
|
|
|
|
if (clazz != null && implementedBy(iface, clazz)) { |
|
|
|
|
continue big_loop_t1; |
|
|
|
|
continue big_loop_this; |
|
|
|
|
} |
|
|
|
|
for (int j=0; j<t2.ifaces.length; j++) { |
|
|
|
|
if (implementedBy(iface, t2.ifaces[j])) { |
|
|
|
|
continue big_loop_t1; |
|
|
|
|
for (int j=0; j<other.ifaces.length; j++) { |
|
|
|
|
if (implementedBy(iface, other.ifaces[j])) { |
|
|
|
|
continue big_loop_this; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -200,15 +235,15 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
*/ |
|
|
|
|
ifaces.addElement(iface); |
|
|
|
|
} |
|
|
|
|
big_loop_t2: |
|
|
|
|
for (int i=0; i< t2.ifaces.length; i++) { |
|
|
|
|
Class iface = t2.ifaces[i]; |
|
|
|
|
big_loop_other: |
|
|
|
|
for (int i=0; i< other.ifaces.length; i++) { |
|
|
|
|
Class iface = other.ifaces[i]; |
|
|
|
|
if (clazz != null && implementedBy(iface, clazz)) { |
|
|
|
|
continue big_loop_t2; |
|
|
|
|
continue big_loop_other; |
|
|
|
|
} |
|
|
|
|
for (int j=0; j<ifaces.size(); j++) { |
|
|
|
|
if (implementedBy(iface, (Class) ifaces.elementAt(j))) { |
|
|
|
|
continue big_loop_t2; |
|
|
|
|
continue big_loop_other; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -223,32 +258,38 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
|
|
|
|
|
Class[] ifaceArray = new Class[ifaces.size()]; |
|
|
|
|
ifaces.copyInto(ifaceArray); |
|
|
|
|
return new ClassInterfacesType(clazz, ifaceArray); |
|
|
|
|
return create(clazz, ifaceArray); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns the generalized type of t1 and t2. |
|
|
|
|
* Returns the generalized type of this and type. |
|
|
|
|
* We have two classes and multiple interfaces. The result |
|
|
|
|
* should be the object that is the the parent of both objects and |
|
|
|
|
* all interfaces, that one class or interface of t1 and of t2 |
|
|
|
|
* all interfaces, that one class or interface of this and of type |
|
|
|
|
* implements. |
|
|
|
|
*/ |
|
|
|
|
public static Type getGeneralizedType(ClassInterfacesType t1, |
|
|
|
|
ClassInterfacesType t2) { |
|
|
|
|
public Type getGeneralizedType(Type type) { |
|
|
|
|
|
|
|
|
|
Class clazz; |
|
|
|
|
Vector ifaces = new Vector(); |
|
|
|
|
|
|
|
|
|
if (type.getTypeCode() == TC_UNKNOWN) |
|
|
|
|
return this; |
|
|
|
|
if (type.getTypeCode() == TC_ARRAY) |
|
|
|
|
return tObject; |
|
|
|
|
if (type.getTypeCode() != TC_CLASS) |
|
|
|
|
return tError; |
|
|
|
|
|
|
|
|
|
ClassInterfacesType other = (ClassInterfacesType) type; |
|
|
|
|
|
|
|
|
|
/* First the easy part, determine the clazz */ |
|
|
|
|
if (t1.clazz == null) |
|
|
|
|
clazz = t2.clazz; |
|
|
|
|
else if (t2.clazz == null) |
|
|
|
|
clazz = t1.clazz; |
|
|
|
|
if (this.clazz == null || other.clazz == null) |
|
|
|
|
clazz = null; |
|
|
|
|
else { |
|
|
|
|
clazz = t1.clazz; |
|
|
|
|
clazz = this.clazz; |
|
|
|
|
|
|
|
|
|
while(clazz != null) { |
|
|
|
|
if (superClassOf(clazz, t2.clazz)) |
|
|
|
|
if (superClassOf(clazz, other.clazz)) |
|
|
|
|
break; |
|
|
|
|
clazz = clazz.getSuperclass(); |
|
|
|
|
} |
|
|
|
@ -259,12 +300,12 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
/* Now the more complicated part: find all interfaces, that are |
|
|
|
|
* implemented by one interface or class in each group. |
|
|
|
|
* |
|
|
|
|
* First get all interfaces of t1.clazz and t1.ifaces. |
|
|
|
|
* First get all interfaces of this.clazz and this.ifaces. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
Stack allIfaces = new Stack(); |
|
|
|
|
if (t1.clazz != null) { |
|
|
|
|
Class c = t1.clazz; |
|
|
|
|
if (this.clazz != null) { |
|
|
|
|
Class c = this.clazz; |
|
|
|
|
while (clazz != c) { |
|
|
|
|
Class clazzIfaces[] = c.getInterfaces(); |
|
|
|
|
for (int i=0; i<clazzIfaces.length; i++) |
|
|
|
@ -272,11 +313,11 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
c = c.getSuperclass(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for (int i=0; i<t1.ifaces.length; i++) |
|
|
|
|
allIfaces.push(t1.ifaces[i]); |
|
|
|
|
for (int i=0; i<this.ifaces.length; i++) |
|
|
|
|
allIfaces.push(this.ifaces[i]); |
|
|
|
|
|
|
|
|
|
/* Now consider each interface. If any clazz or interface
|
|
|
|
|
* in t2 implements it, add it to the ifaces vector. |
|
|
|
|
* in other implements it, add it to the ifaces vector. |
|
|
|
|
* Otherwise consider all sub interfaces. |
|
|
|
|
*/ |
|
|
|
|
iface_loop: |
|
|
|
@ -287,12 +328,12 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
*/ |
|
|
|
|
continue iface_loop; |
|
|
|
|
|
|
|
|
|
if (t2.clazz != null && implementedBy(iface, t2.clazz)) { |
|
|
|
|
if (other.clazz != null && implementedBy(iface, other.clazz)) { |
|
|
|
|
ifaces.addElement(iface); |
|
|
|
|
continue iface_loop; |
|
|
|
|
} |
|
|
|
|
for (int i=0; i<t2.ifaces.length; i++) { |
|
|
|
|
if (implementedBy(iface, t2.ifaces[i])) { |
|
|
|
|
for (int i=0; i<other.ifaces.length; i++) { |
|
|
|
|
if (implementedBy(iface, other.ifaces[i])) { |
|
|
|
|
ifaces.addElement(iface); |
|
|
|
|
continue iface_loop; |
|
|
|
|
} |
|
|
|
@ -308,12 +349,14 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
|
|
|
|
|
Class[] ifaceArray = new Class[ifaces.size()]; |
|
|
|
|
ifaces.copyInto(ifaceArray); |
|
|
|
|
return new ClassInterfacesType(clazz, ifaceArray); |
|
|
|
|
return create(clazz, ifaceArray); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public String typeString(String string, boolean flag1, boolean flag2) |
|
|
|
|
public String toString() |
|
|
|
|
{ |
|
|
|
|
if (jode.Decompiler.isTypeDebugging) { |
|
|
|
|
if (this == tObject) |
|
|
|
|
return "<tObject>"; |
|
|
|
|
StringBuffer sb = new StringBuffer("{"); |
|
|
|
|
String comma = ""; |
|
|
|
|
if (clazz != null) { |
|
|
|
@ -324,14 +367,35 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
sb.append(comma).append(ifaces[i].getName()); |
|
|
|
|
comma = ", "; |
|
|
|
|
} |
|
|
|
|
return sb.append("}").append(string).toString(); |
|
|
|
|
return sb.append("}").toString(); |
|
|
|
|
} else { |
|
|
|
|
if (clazz != null) |
|
|
|
|
return clazz.toString() + string; |
|
|
|
|
return clazz.getName(); |
|
|
|
|
else if (ifaces.length > 0) |
|
|
|
|
return ifaces[0].toString() + string; |
|
|
|
|
return ifaces[0].getName(); |
|
|
|
|
else |
|
|
|
|
return tError.toString() + string; |
|
|
|
|
return "{<error>}"; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public boolean equals(Object o) { |
|
|
|
|
if (o == this) |
|
|
|
|
return true; |
|
|
|
|
if (o instanceof ClassInterfacesType) { |
|
|
|
|
ClassInterfacesType type = (ClassInterfacesType) o; |
|
|
|
|
if (type.clazz == clazz |
|
|
|
|
&& type.ifaces.length == ifaces.length) { |
|
|
|
|
big_loop: |
|
|
|
|
for (int i=0; i< type.ifaces.length; i++) { |
|
|
|
|
for (int j=0; j<ifaces.length; j++) { |
|
|
|
|
if (type.ifaces[i] == ifaces[j]) |
|
|
|
|
continue big_loop; |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|