|
|
|
@ -35,41 +35,62 @@ import java.util.Stack; |
|
|
|
|
* @author Jochen Hoenicke */ |
|
|
|
|
public class ClassInterfacesType extends MyType { |
|
|
|
|
|
|
|
|
|
ClassDeclaration clazz; |
|
|
|
|
ClassDeclaration ifaces[]; |
|
|
|
|
Class clazz; |
|
|
|
|
Class ifaces[]; |
|
|
|
|
|
|
|
|
|
public final static Class cObject = new Object().getClass(); |
|
|
|
|
|
|
|
|
|
public ClassInterfacesType(Type clazzType) { |
|
|
|
|
super(104, "{"+clazzType.getTypeSignature()+"}"); |
|
|
|
|
ClassDeclaration cdecl = |
|
|
|
|
new ClassDeclaration(clazzType.getClassName()); |
|
|
|
|
try { |
|
|
|
|
if (cdecl.getClassDefinition(env).isInterface()) { |
|
|
|
|
clazz = new ClassDeclaration(Constants.idJavaLangObject); |
|
|
|
|
ifaces = new ClassDeclaration[1]; |
|
|
|
|
Class cdecl = |
|
|
|
|
Class.forName(clazzType.getClassName().toString()); |
|
|
|
|
if (cdecl.isInterface()) { |
|
|
|
|
clazz = cObject; |
|
|
|
|
ifaces = new Class[1]; |
|
|
|
|
ifaces[0] = cdecl; |
|
|
|
|
} else { |
|
|
|
|
clazz = cdecl; |
|
|
|
|
ifaces = new ClassDeclaration[0]; |
|
|
|
|
ifaces = new Class[0]; |
|
|
|
|
} |
|
|
|
|
} catch (ClassNotFound ex) { |
|
|
|
|
} catch (ClassNotFoundException ex) { |
|
|
|
|
throw new AssertError(ex.toString()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public ClassInterfacesType(ClassDeclaration clazz, |
|
|
|
|
ClassDeclaration[] ifaces) { |
|
|
|
|
public ClassInterfacesType(Class clazz, |
|
|
|
|
Class[] ifaces) { |
|
|
|
|
super(104, "{}"); |
|
|
|
|
StringBuffer sig = new StringBuffer("{"); |
|
|
|
|
if (clazz != null) |
|
|
|
|
sig.append(clazz.getType().getTypeSignature()); |
|
|
|
|
sig.append("L").append(clazz.getName()).append(";"); |
|
|
|
|
for (int i=0;i < ifaces.length; i++) |
|
|
|
|
sig.append(ifaces[i].getType().getTypeSignature()); |
|
|
|
|
sig.append("L").append(ifaces[i].getName()).append(";"); |
|
|
|
|
sig.append("}"); |
|
|
|
|
typeSig = sig.toString(); |
|
|
|
|
this.clazz = clazz; |
|
|
|
|
this.ifaces = ifaces; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public final static boolean superClassOf(Class parent, Class clazz) { |
|
|
|
|
while (clazz != parent && clazz != null) { |
|
|
|
|
clazz = clazz.getSuperclass(); |
|
|
|
|
} |
|
|
|
|
return clazz == parent; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public final static boolean implementedBy(Class iface, Class clazz) { |
|
|
|
|
while (clazz != iface && clazz != null) { |
|
|
|
|
Class[] ifaces = clazz.getInterfaces(); |
|
|
|
|
for (int i=0; i< ifaces.length; i++) { |
|
|
|
|
if (implementedBy(iface, ifaces[i])) |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
clazz = clazz.getSuperclass(); |
|
|
|
|
} |
|
|
|
|
return clazz != null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Checks if the given type range may be not empty. |
|
|
|
|
* This means, that bottom.clazz is extended by top.clazz |
|
|
|
@ -81,63 +102,53 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
*/ |
|
|
|
|
public final static Type createRangeType(ClassInterfacesType bottom, |
|
|
|
|
ClassInterfacesType top) { |
|
|
|
|
try { |
|
|
|
|
if (bottom.clazz != null |
|
|
|
|
&& bottom.clazz.getType() != tObject) { |
|
|
|
|
/* The searched type must be a class type. |
|
|
|
|
*/ |
|
|
|
|
if (top.ifaces.length != 0 |
|
|
|
|
|| !bottom.clazz.getClassDefinition(env). |
|
|
|
|
superClassOf(env,top.clazz)) |
|
|
|
|
return tError; |
|
|
|
|
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)) |
|
|
|
|
return tError; |
|
|
|
|
|
|
|
|
|
/* All interfaces must be implemented by top.clazz |
|
|
|
|
*/ |
|
|
|
|
for (int i=0; i < bottom.ifaces.length; i++) { |
|
|
|
|
if (!bottom.ifaces[i].getClassDefinition(env). |
|
|
|
|
implementedBy(env,top.clazz)) |
|
|
|
|
return tError; |
|
|
|
|
/* All interfaces must be implemented by top.clazz |
|
|
|
|
*/ |
|
|
|
|
for (int i=0; i < bottom.ifaces.length; i++) { |
|
|
|
|
if (!implementedBy(bottom.ifaces[i], top.clazz)) |
|
|
|
|
return tError; |
|
|
|
|
} |
|
|
|
|
return new ClassRangeType |
|
|
|
|
(bottom, new ClassInterfacesType(top.clazz, |
|
|
|
|
new ClassDeclaration[0])); |
|
|
|
|
return new ClassRangeType |
|
|
|
|
(bottom, new ClassInterfacesType(top.clazz, |
|
|
|
|
new Class[0])); |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
/* Now bottom.clazz is null, find all top.class/interfaces |
|
|
|
|
* that implement all bottom.ifaces. |
|
|
|
|
*/ |
|
|
|
|
ClassDeclaration clazz = top.clazz; |
|
|
|
|
if (clazz != null) { |
|
|
|
|
for (int i=0; i < bottom.ifaces.length; i++) { |
|
|
|
|
ClassDefinition idef = |
|
|
|
|
bottom.ifaces[i].getClassDefinition(env); |
|
|
|
|
if (!idef.implementedBy(env, clazz)) { |
|
|
|
|
clazz = null; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
/* Now bottom.clazz is null, find all top.class/interfaces |
|
|
|
|
* that implement all bottom.ifaces. |
|
|
|
|
*/ |
|
|
|
|
Class clazz = top.clazz; |
|
|
|
|
if (clazz != null) { |
|
|
|
|
for (int i=0; i < bottom.ifaces.length; i++) { |
|
|
|
|
if (!implementedBy(bottom.ifaces[i], clazz)) { |
|
|
|
|
clazz = null; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Vector ifaces = new Vector(); |
|
|
|
|
big_loop: |
|
|
|
|
for (int j=0; j < top.ifaces.length; j++) { |
|
|
|
|
for (int i=0; i < bottom.ifaces.length; i++) { |
|
|
|
|
ClassDefinition idef = |
|
|
|
|
bottom.ifaces[i].getClassDefinition(env); |
|
|
|
|
if (!idef.implementedBy(env, top.ifaces[j])) |
|
|
|
|
continue big_loop; |
|
|
|
|
} |
|
|
|
|
ifaces.addElement(top.ifaces[j]); |
|
|
|
|
} |
|
|
|
|
Vector ifaces = new Vector(); |
|
|
|
|
big_loop: |
|
|
|
|
for (int j=0; j < top.ifaces.length; j++) { |
|
|
|
|
for (int i=0; i < bottom.ifaces.length; i++) { |
|
|
|
|
if (!implementedBy(bottom.ifaces[i], top.ifaces[j])) |
|
|
|
|
continue big_loop; |
|
|
|
|
} |
|
|
|
|
ClassDeclaration[] ifaceArray = |
|
|
|
|
new ClassDeclaration[ifaces.size()]; |
|
|
|
|
ifaces.addElement(top.ifaces[j]); |
|
|
|
|
} |
|
|
|
|
Class[] ifaceArray = |
|
|
|
|
new Class[ifaces.size()]; |
|
|
|
|
ifaces.copyInto(ifaceArray); |
|
|
|
|
return new ClassRangeType |
|
|
|
|
(bottom, new ClassInterfacesType(clazz, ifaceArray)); |
|
|
|
|
} |
|
|
|
|
} catch (ClassNotFound ex) { |
|
|
|
|
return tError; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -149,77 +160,68 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
public static Type getSpecializedType(ClassInterfacesType t1, |
|
|
|
|
ClassInterfacesType t2) { |
|
|
|
|
|
|
|
|
|
ClassDeclaration clazz = null; |
|
|
|
|
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. |
|
|
|
|
*/ |
|
|
|
|
try { |
|
|
|
|
if (t1.clazz == null) |
|
|
|
|
clazz = t2.clazz; |
|
|
|
|
else if (t2.clazz == null) |
|
|
|
|
clazz = t1.clazz; |
|
|
|
|
else if (t1.clazz. |
|
|
|
|
getClassDefinition(env).superClassOf(env, t2.clazz)) |
|
|
|
|
clazz = t2.clazz; |
|
|
|
|
else if (t2.clazz. |
|
|
|
|
getClassDefinition(env).superClassOf(env, t1.clazz)) |
|
|
|
|
clazz = t1.clazz; |
|
|
|
|
else |
|
|
|
|
return tError; |
|
|
|
|
|
|
|
|
|
/* The interfaces are simply the union of both interfaces set. |
|
|
|
|
* 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++) { |
|
|
|
|
ClassDeclaration iface = t1.ifaces[i]; |
|
|
|
|
ClassDefinition idef = iface.getClassDefinition(env); |
|
|
|
|
if (clazz != null && idef.implementedBy(env, clazz)) { |
|
|
|
|
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; |
|
|
|
|
else |
|
|
|
|
return tError; |
|
|
|
|
|
|
|
|
|
/* The interfaces are simply the union of both interfaces set. |
|
|
|
|
* 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]; |
|
|
|
|
if (clazz != null && implementedBy(iface, clazz)) { |
|
|
|
|
continue big_loop_t1; |
|
|
|
|
} |
|
|
|
|
for (int j=0; j<t2.ifaces.length; j++) { |
|
|
|
|
if (implementedBy(iface, t2.ifaces[j])) { |
|
|
|
|
continue big_loop_t1; |
|
|
|
|
} |
|
|
|
|
for (int j=0; j<t2.ifaces.length; j++) { |
|
|
|
|
if (idef.implementedBy(env, t2.ifaces[j])) { |
|
|
|
|
continue big_loop_t1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* This interface is not implemented by any of the other |
|
|
|
|
* ifaces. Add it to the interfaces vector. |
|
|
|
|
*/ |
|
|
|
|
ifaces.addElement(iface); |
|
|
|
|
/* This interface is not implemented by any of the other |
|
|
|
|
* ifaces. Add it to the interfaces vector. |
|
|
|
|
*/ |
|
|
|
|
ifaces.addElement(iface); |
|
|
|
|
} |
|
|
|
|
big_loop_t2: |
|
|
|
|
for (int i=0; i< t2.ifaces.length; i++) { |
|
|
|
|
Class iface = t2.ifaces[i]; |
|
|
|
|
if (clazz != null && implementedBy(iface, clazz)) { |
|
|
|
|
continue big_loop_t2; |
|
|
|
|
} |
|
|
|
|
big_loop_t2: |
|
|
|
|
for (int i=0; i< t2.ifaces.length; i++) { |
|
|
|
|
ClassDeclaration iface = t2.ifaces[i]; |
|
|
|
|
ClassDefinition idef = iface.getClassDefinition(env); |
|
|
|
|
if (clazz != null && idef.implementedBy(env, clazz)) { |
|
|
|
|
for (int j=0; j<ifaces.size(); j++) { |
|
|
|
|
if (implementedBy(iface, (Class) ifaces.elementAt(j))) { |
|
|
|
|
continue big_loop_t2; |
|
|
|
|
} |
|
|
|
|
for (int j=0; j<ifaces.size(); j++) { |
|
|
|
|
if (idef.implementedBy |
|
|
|
|
(env, (ClassDeclaration) ifaces.elementAt(j))) { |
|
|
|
|
continue big_loop_t2; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* This interface is not implemented by any of the other |
|
|
|
|
* ifaces. Add it to the interfaces vector. |
|
|
|
|
*/ |
|
|
|
|
ifaces.addElement(iface); |
|
|
|
|
} |
|
|
|
|
if (clazz.getType() == tObject && ifaces.size() > 0) |
|
|
|
|
/* Every interface implies tObject, so remove it */ |
|
|
|
|
clazz = null; |
|
|
|
|
|
|
|
|
|
} catch (ClassNotFound ex) { |
|
|
|
|
return tError; |
|
|
|
|
/* This interface is not implemented by any of the other |
|
|
|
|
* ifaces. Add it to the interfaces vector. |
|
|
|
|
*/ |
|
|
|
|
ifaces.addElement(iface); |
|
|
|
|
} |
|
|
|
|
if (clazz == cObject && ifaces.size() > 0) |
|
|
|
|
/* Every interface implies tObject, so remove it */ |
|
|
|
|
clazz = null; |
|
|
|
|
|
|
|
|
|
ClassDeclaration[] ifaceArray = new ClassDeclaration[ifaces.size()]; |
|
|
|
|
Class[] ifaceArray = new Class[ifaces.size()]; |
|
|
|
|
ifaces.copyInto(ifaceArray); |
|
|
|
|
return new ClassInterfacesType(clazz, ifaceArray); |
|
|
|
|
} |
|
|
|
@ -234,81 +236,77 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
public static Type getGeneralizedType(ClassInterfacesType t1, |
|
|
|
|
ClassInterfacesType t2) { |
|
|
|
|
|
|
|
|
|
ClassDeclaration clazz; |
|
|
|
|
Class clazz; |
|
|
|
|
Vector ifaces = new Vector(); |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
/* First the easy part, determine the clazz */ |
|
|
|
|
if (t1.clazz == null) |
|
|
|
|
clazz = t2.clazz; |
|
|
|
|
else if (t2.clazz == null) |
|
|
|
|
clazz = t1.clazz; |
|
|
|
|
else { |
|
|
|
|
clazz = t1.clazz; |
|
|
|
|
/* First the easy part, determine the clazz */ |
|
|
|
|
if (t1.clazz == null) |
|
|
|
|
clazz = t2.clazz; |
|
|
|
|
else if (t2.clazz == null) |
|
|
|
|
clazz = t1.clazz; |
|
|
|
|
else { |
|
|
|
|
clazz = t1.clazz; |
|
|
|
|
|
|
|
|
|
while(clazz != null) { |
|
|
|
|
ClassDefinition cdef = clazz.getClassDefinition(env); |
|
|
|
|
if (cdef.superClassOf(env, t2.clazz)) |
|
|
|
|
break; |
|
|
|
|
clazz = cdef.getSuperClass(env); |
|
|
|
|
} |
|
|
|
|
if (clazz.getType() == tObject) |
|
|
|
|
clazz = null; |
|
|
|
|
while(clazz != null) { |
|
|
|
|
if (superClassOf(clazz, t2.clazz)) |
|
|
|
|
break; |
|
|
|
|
clazz = clazz.getSuperclass(); |
|
|
|
|
} |
|
|
|
|
if (clazz == cObject) |
|
|
|
|
clazz = null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Now the more complicated part: find all interfaces, that are |
|
|
|
|
/* 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. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
Stack allIfaces = new Stack(); |
|
|
|
|
if (t1.clazz != null) { |
|
|
|
|
ClassDeclaration clazzIfaces[] = |
|
|
|
|
t1.clazz.getClassDefinition(env).getInterfaces(); |
|
|
|
|
Stack allIfaces = new Stack(); |
|
|
|
|
if (t1.clazz != null) { |
|
|
|
|
Class c = t1.clazz; |
|
|
|
|
while (clazz != c) { |
|
|
|
|
Class clazzIfaces[] = c.getInterfaces(); |
|
|
|
|
for (int i=0; i<clazzIfaces.length; i++) |
|
|
|
|
allIfaces.push(clazzIfaces[i]); |
|
|
|
|
c = c.getSuperclass(); |
|
|
|
|
} |
|
|
|
|
for (int i=0; i<t1.ifaces.length; i++) |
|
|
|
|
} |
|
|
|
|
for (int i=0; i<t1.ifaces.length; i++) |
|
|
|
|
allIfaces.push(t1.ifaces[i]); |
|
|
|
|
|
|
|
|
|
/* Now consider each interface. If any clazz or interface
|
|
|
|
|
* in t2 implements it, add it to the ifaces vector. |
|
|
|
|
* Otherwise consider all sub interfaces. |
|
|
|
|
*/ |
|
|
|
|
iface_loop: |
|
|
|
|
while (!allIfaces.isEmpty()) { |
|
|
|
|
ClassDeclaration iface = (ClassDeclaration) allIfaces.pop(); |
|
|
|
|
ClassDefinition idef = iface.getClassDefinition(env); |
|
|
|
|
if (clazz != null && idef.implementedBy(env, clazz)) |
|
|
|
|
/* We can skip this, as clazz does already imply it. |
|
|
|
|
*/ |
|
|
|
|
continue iface_loop; |
|
|
|
|
iface_loop: |
|
|
|
|
while (!allIfaces.isEmpty()) { |
|
|
|
|
Class iface = (Class) allIfaces.pop(); |
|
|
|
|
if (clazz != null && implementedBy(iface, clazz)) |
|
|
|
|
/* We can skip this, as clazz does already imply it. |
|
|
|
|
*/ |
|
|
|
|
continue iface_loop; |
|
|
|
|
|
|
|
|
|
if (t2.clazz != null && idef.implementedBy(env, t2.clazz)) { |
|
|
|
|
if (t2.clazz != null && implementedBy(iface, t2.clazz)) { |
|
|
|
|
ifaces.addElement(iface); |
|
|
|
|
continue iface_loop; |
|
|
|
|
} |
|
|
|
|
for (int i=0; i<t2.ifaces.length; i++) { |
|
|
|
|
if (implementedBy(iface, t2.ifaces[i])) { |
|
|
|
|
ifaces.addElement(iface); |
|
|
|
|
continue iface_loop; |
|
|
|
|
} |
|
|
|
|
for (int i=0; i<t2.ifaces.length; i++) { |
|
|
|
|
if (idef.implementedBy(env, t2.ifaces[i])) { |
|
|
|
|
ifaces.addElement(iface); |
|
|
|
|
continue iface_loop; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* This interface is not implemented by any of the other |
|
|
|
|
* ifaces. Try its parent interfaces now. |
|
|
|
|
*/ |
|
|
|
|
ClassDeclaration clazzIfaces[] = idef.getInterfaces(); |
|
|
|
|
for (int i=0; i<clazzIfaces.length; i++) |
|
|
|
|
allIfaces.push(clazzIfaces[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} catch (ClassNotFound ex) { |
|
|
|
|
return tError; |
|
|
|
|
/* This interface is not implemented by any of the other |
|
|
|
|
* ifaces. Try its parent interfaces now. |
|
|
|
|
*/ |
|
|
|
|
Class clazzIfaces[] = iface.getInterfaces(); |
|
|
|
|
for (int i=0; i<clazzIfaces.length; i++) |
|
|
|
|
allIfaces.push(clazzIfaces[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ClassDeclaration[] ifaceArray = new ClassDeclaration[ifaces.size()]; |
|
|
|
|
Class[] ifaceArray = new Class[ifaces.size()]; |
|
|
|
|
ifaces.copyInto(ifaceArray); |
|
|
|
|
return new ClassInterfacesType(clazz, ifaceArray); |
|
|
|
|
} |
|
|
|
@ -329,12 +327,11 @@ public class ClassInterfacesType extends MyType { |
|
|
|
|
return sb.append("}").append(string).toString(); |
|
|
|
|
} else { |
|
|
|
|
if (clazz != null) |
|
|
|
|
return clazz.getType().typeString(string, flag1, flag2); |
|
|
|
|
return clazz.toString() + string; |
|
|
|
|
else if (ifaces.length > 0) |
|
|
|
|
return ifaces[0].getType().typeString(string, flag1, flag2); |
|
|
|
|
return ifaces[0].toString() + string; |
|
|
|
|
else |
|
|
|
|
return tError.typeString(string,flag1,flag2); |
|
|
|
|
return tError.toString() + string; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|