git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@48 379699f6-c40d-0410-875b-85095c16579estable
parent
243f1dbed4
commit
1339141e8e
@ -0,0 +1,340 @@ |
||||
/* ClassInterfacesType Copyright (C) 1997-1998 Jochen Hoenicke. |
||||
* |
||||
* This program is free software; you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation; either version 2, or (at your option) |
||||
* any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program; see the file COPYING. If not, write to |
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
||||
* |
||||
* $Id$ |
||||
*/ |
||||
package jode; |
||||
import sun.tools.java.*; |
||||
import java.util.Vector; |
||||
import java.util.Stack; |
||||
|
||||
/** |
||||
* This class represents a type aproximation, consisting of multiple |
||||
* interfaces and a class type.<p> |
||||
* |
||||
* If this is the bottom boundary, this specifies, which class our |
||||
* type must extend and which interfaces it must implement. |
||||
* |
||||
* If this is the top boundary, this gives all interfaces and classes |
||||
* that may extend the type. I.e. the type may be one of the |
||||
* interfaces or the class type or any of their super types. |
||||
* |
||||
* @author Jochen Hoenicke */ |
||||
public class ClassInterfacesType extends MyType { |
||||
|
||||
ClassDeclaration clazz; |
||||
ClassDeclaration ifaces[]; |
||||
|
||||
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]; |
||||
ifaces[0] = cdecl; |
||||
} else { |
||||
clazz = cdecl; |
||||
ifaces = new ClassDeclaration[0]; |
||||
} |
||||
} catch (ClassNotFound ex) { |
||||
throw new AssertError(ex.toString()); |
||||
} |
||||
} |
||||
|
||||
public ClassInterfacesType(ClassDeclaration clazz, |
||||
ClassDeclaration[] ifaces) { |
||||
super(104, "{}"); |
||||
StringBuffer sig = new StringBuffer("{"); |
||||
if (clazz != null) |
||||
sig.append(clazz.getType().getTypeSignature()); |
||||
for (int i=0;i < ifaces.length; i++) |
||||
sig.append(ifaces[i].getType().getTypeSignature()); |
||||
sig.append("}"); |
||||
typeSig = sig.toString(); |
||||
this.clazz = clazz; |
||||
this.ifaces = ifaces; |
||||
} |
||||
|
||||
/** |
||||
* 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. |
||||
*/ |
||||
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; |
||||
|
||||
/* 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; |
||||
} |
||||
return new ClassRangeType |
||||
(bottom, new ClassInterfacesType(top.clazz, |
||||
new ClassDeclaration[0])); |
||||
|
||||
} 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; |
||||
} |
||||
} |
||||
} |
||||
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]); |
||||
} |
||||
ClassDeclaration[] ifaceArray = |
||||
new ClassDeclaration[ifaces.size()]; |
||||
ifaces.copyInto(ifaceArray); |
||||
return new ClassRangeType |
||||
(bottom, new ClassInterfacesType(clazz, ifaceArray)); |
||||
} |
||||
} catch (ClassNotFound ex) { |
||||
return tError; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Returns the specialized type of t1 and t2. |
||||
* 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) { |
||||
|
||||
ClassDeclaration 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)) { |
||||
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); |
||||
} |
||||
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)) { |
||||
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; |
||||
} |
||||
|
||||
ClassDeclaration[] ifaceArray = new ClassDeclaration[ifaces.size()]; |
||||
ifaces.copyInto(ifaceArray); |
||||
return new ClassInterfacesType(clazz, ifaceArray); |
||||
} |
||||
|
||||
/** |
||||
* Returns the generalized type of t1 and t2. |
||||
* 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 |
||||
* implements. |
||||
*/ |
||||
public static Type getGeneralizedType(ClassInterfacesType t1, |
||||
ClassInterfacesType t2) { |
||||
|
||||
ClassDeclaration 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; |
||||
|
||||
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; |
||||
} |
||||
|
||||
/* 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(); |
||||
for (int i=0; i<clazzIfaces.length; i++) |
||||
allIfaces.push(clazzIfaces[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; |
||||
|
||||
if (t2.clazz != null && idef.implementedBy(env, t2.clazz)) { |
||||
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; |
||||
} |
||||
|
||||
ClassDeclaration[] ifaceArray = new ClassDeclaration[ifaces.size()]; |
||||
ifaces.copyInto(ifaceArray); |
||||
return new ClassInterfacesType(clazz, ifaceArray); |
||||
} |
||||
|
||||
public String typeString(String string, boolean flag1, boolean flag2) |
||||
{ |
||||
if (jode.Decompiler.isTypeDebugging) { |
||||
StringBuffer sb = new StringBuffer("{"); |
||||
String comma = ""; |
||||
if (clazz != null) { |
||||
sb = sb.append(clazz.getName()); |
||||
comma = ", "; |
||||
} |
||||
for (int i=0; i< ifaces.length; i++) { |
||||
sb.append(comma).append(ifaces[i].getName()); |
||||
comma = ", "; |
||||
} |
||||
return sb.append("}").append(string).toString(); |
||||
} else { |
||||
if (clazz != null) |
||||
return clazz.getType().typeString(string, flag1, flag2); |
||||
else if (ifaces.length > 0) |
||||
return ifaces[0].getType().typeString(string, flag1, flag2); |
||||
else |
||||
return tError.typeString(string,flag1,flag2); |
||||
} |
||||
} |
||||
} |
||||
|
Loading…
Reference in new issue