From 1339141e8e3e33535341ab906fecc2c6893a6c19 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 1 Oct 1998 08:56:57 +0000 Subject: [PATCH] Initial revision git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@48 379699f6-c40d-0410-875b-85095c16579e --- jode/jode/type/ClassInterfacesType.java | 340 ++++++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 jode/jode/type/ClassInterfacesType.java diff --git a/jode/jode/type/ClassInterfacesType.java b/jode/jode/type/ClassInterfacesType.java new file mode 100644 index 0000000..eb1219b --- /dev/null +++ b/jode/jode/type/ClassInterfacesType.java @@ -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.

+ * + * 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.

+ * + * 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 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 0) + return ifaces[0].getType().typeString(string, flag1, flag2); + else + return tError.typeString(string,flag1,flag2); + } + } +} +