package bluej.debugger.gentype;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;


| A "solid" type is a non-primitive, non-wildcard type. This includes arrays, |* classes, and type parameters. Basically, a "solid" is anything that can be * a component type for a wildcard clause. * * @author Davin McCall */ public abstract class GenTypeSolid extends JavaType{ // force toString(NameTransform) to be reimplemented | |public abstract String toString(NameTransform nt); | |// provide a default implementation for toString(). | |public String toString() | |{ | |return toString(false); | |} | |public boolean isPrimitive() | |{ | |return false; | |} | |public abstract boolean isInterface(); | |/** | Get the erased supertypes of this type, as defined in the JLS 3.0 | section 15.12.2.7. | | @param s The set into which to store the reflectives | public abstract void erasedSuperTypes(Set<Reflective> s);
| Find the minimal set of supertypes of this type which are reference types. For tpars | this is the bounds. For a class/interface this is the type itself. | public abstract GenTypeClass [] getReferenceSupertypes();
| Assuming that this is some solid type that is either a tpar or a | class whose type arguments also match this definition (recursively), | and the given template is a similar type (a constraint if this is | a tpar, or the same class with type arguments acting as constraints).<p> | | For example, if this type is LinkedList<T>, and the template | is LinkedList<Thread>, then this method returns a map containing | the mapping "T -> Thread".<p> |* * The given map may already contain some mappings. In this case, the * existing mappings will be retained or made more specific. * * @param map A map to which mappings should be added | @param template The template to use | abstract public void getParamsFromTemplate(Map<String,GenTypeParameter> map, GenTypeParameter template);
| | Implement methods from GenTypeParameterizable | public GenTypeSolid [] getUpperBounds() { return getIntersectionTypes(); } @Override public GenTypeSolid getUpperBound() { return this; } @Override public GenTypeSolid getLowerBound() { return this; } @Override public JavaType getCapture() { return this; } @Override public GenTypeSolid asSolid() { return this; } @Override public boolean isWildcard() { return false; }
| | Static methods | | Calculate lub, as defined in revised JLS 15.12.2. Essentially this | means, calculate the most specific type to which all the given types are | convertible.<p> | public static GenTypeSolid lub(GenTypeSolid [] ubounds) { Stack<GenTypeClass[]> btstack = new Stack<GenTypeClass[]>(); return lub(ubounds, btstack); }
| | Private static methods | | Lub workhorse method, uses a stack backtrace to avoid infinite recursion. | private static GenTypeSolid lub(GenTypeSolid [] ubounds, Stack<GenTypeClass[]> lubBt) { List<GenTypeSolid> l = new ArrayList<GenTypeSolid>(); Reflective [] mec = minimalErasedCandidateSet(ubounds); for (int i = 0; i < mec.length; i++) { l.add(Candidate(mec[i], ubounds, lubBt)); } GenTypeSolid [] intersecting = l.toArray(new GenTypeSolid[l.size()]); return IntersectionType.getIntersection(intersecting); }
| This is the "Candidate" (and "CandidateInvocation") function as defined |* in the proposed JLS, section 15.12.2.7 * * @param t The class type to find the candidate type for * @param ubounds The complete set of bounding types (see lub()) | @param lubBt A backtrace used to avoid infinite recursion | @return The candidate type | private static GenTypeClass Candidate(Reflective t, GenTypeSolid [] ubounds, Stack<GenTypeClass[]> lubBt) { GenTypeClass [] ri = relevantInvocations(t, ubounds); return leastContainingInvocation(ri, lubBt); }
| Find the least containing invocation from a set of invocations. The | invocations a, b, ... are types based on the same class G. The return is | a generic type G<...> such that all a, b, ... are convertible to the | return type.<p> | | This is "lci" as defined in the JLS 3rd edition section 15.12.2.7 |* * @param types The invocations * @param lubBt A backtrace used to avoid infinite recursion * @return The least containing type private static GenTypeClass leastContainingInvocation(GenTypeClass [] types, Stack<GenTypeClass[]> lubBt) { boolean breakRecursion = false; Iterator<GenTypeClass[]> si = lubBt.iterator(); while (si.hasNext()){ GenTypeSolid [] sbounds = si.next(); int i; for (i = 0; i < sbounds.length; i++) { if (! sbounds[i].equals(types[i])) { break; } } breakRecursion = (i == sbounds.length); } lubBt.push(types); GenTypeClass rtype = types[0]; for (int i = 1; i < types.length; i++) { rtype = leastContainingInvocation(rtype, types[i], lubBt, breakRecursion); } lubBt.pop(); return rtype; }
| Find the least containing invocation from two invocations. | private static GenTypeClass leastContainingInvocation(GenTypeClass a, GenTypeClass b, Stack<GenTypeClass[]> lubBt, boolean breakRecursion) { if (! a.getReflective().getName().equals(b.getReflective().getName())) throw new IllegalArgumentException("Class types must be the same."); if (a.isRaw() || b.isRaw()) return (a.isRaw()) ? a : b; int arrCount = 0; GenTypeClass origA = a; while (a.getArrayComponent() != null){ a = a.getArrayComponent().asClass(); b = b.getArrayComponent().asClass(); if (a == null) { return origA; } arrCount++; } List<GenTypeParameter> lc = new ArrayList<GenTypeParameter>(); Iterator<? extends GenTypeParameter> i = a.getTypeParamList().iterator(); Iterator<? extends GenTypeParameter> j = b.getTypeParamList().iterator(); GenTypeClass oa = a.getOuterType(); GenTypeClass ob = b.getOuterType(); GenTypeClass oc = null; if (oa != null && ob != null) oc = leastContainingInvocation(oa, ob, lubBt, breakRecursion); while (i.hasNext()){ GenTypeParameter atype = (GenTypeParameter) i.next(); GenTypeParameter btype = (GenTypeParameter) j.next(); GenTypeParameter rtype; if (! breakRecursion) rtype = leastContainingTypeArgument(atype, btype, lubBt); else{ rtype = new GenTypeUnbounded(); } lc.add(rtype); } GenTypeClass rval = new GenTypeClass(a.getReflective(), lc, oc); while (arrCount-- > 0){ rval = rval.getArray(); } return rval; }
| Find the "least containing" type of two type parameters. This is "lcta" |* as defined in the JLS section 15.12.2.7 * * @param a The first type parameter * @param b The second type parameter * @param lubBt The backtrace for avoiding infinite recursion | @return The least containing type | private static GenTypeParameter leastContainingTypeArgument(GenTypeParameter a, GenTypeParameter b, Stack<GenTypeClass[]> lubBt) { GenTypeSolid ac = a.asSolid(); GenTypeSolid bc = b.asSolid(); if (ac != null && bc != null) { if (ac.equals(bc)) return ac; else{ return new GenTypeWildcard(lub(new GenTypeSolid [] {ac, bc}, lubBt), null); } } if (ac != null || bc != null) { if (ac == null) { ac = bc; b = a; } GenTypeSolid lbound = b.getLowerBound(); if (lbound != null) { return new GenTypeWildcard(null, IntersectionType.getIntersection(lbound, ac)); } } GenTypeSolid lboundsa = a.getLowerBound(); GenTypeSolid lboundsb = b.getLowerBound(); if (lboundsa != null && lboundsb != null) { return new GenTypeWildcard(null, IntersectionType.getIntersection(lboundsa, lboundsb)); } if (lboundsa != null || lboundsb != null) { if (a.equals(b)) return a; return new GenTypeUnbounded(); } GenTypeSolid uboundsa = a.getUpperBound().asSolid(); GenTypeSolid uboundsb = b.getUpperBound().asSolid(); GenTypeSolid [] args = new GenTypeSolid[2]; args[0] = uboundsa; args[1] = uboundsb; return lub(args); }
| Find the "minimal erased candidate set" of a set of types (MEC as |* defined in the JLS, section 15.12.2.7. This is the set of all (raw) * supertypes common to each type in the given set, with no duplicates or * redundant types (types whose presence is dictated by the presence of a | subtype). | | @param types The types for which to find the MEC. | @return The MEC as an array of Reflective. | private static Reflective [] minimalErasedCandidateSet(GenTypeSolid [] types) { Set<Reflective> rset = new HashSet<Reflective>(); types[0].erasedSuperTypes(rset); for (int i = 1; i < types.length; i++) { Set<Reflective> rset2 = new HashSet<Reflective>(); types[i].erasedSuperTypes(rset2); Iterator<Reflective> j = rset2.iterator(); while (j.hasNext()){ if ( ! rset.contains(j.next())) j.remove(); } rset = rset2; } Iterator<Reflective> i = rset.iterator(); while (i.hasNext()){ Iterator<Reflective> j = rset.iterator(); Reflective ri = (Reflective) i.next(); while (j.hasNext()){ Reflective ji = (Reflective) j.next(); if (ri == ji) continue; if (ri.isAssignableFrom(ji)) { i.remove(); break; } } } Reflective [] rval = new Reflective[rset.size()]; rset.toArray(rval); return rval; }
| Find the "relevant invocations" of some class. That is, given the class, |* find the generic types corresponding to that class which occur in the * given parameter list.<P> * * This is "Inv" described in the JLS section 15.12.2.7 * * @param r The class whose invocations to find * @param ubounds The parameter list to search * @return A list of generic types all based on the class r private static GenTypeClass [] relevantInvocations(Reflective r, GenTypeSolid [] ubounds) { ArrayList<GenTypeClass> rlist = new ArrayList<GenTypeClass>(); for (int i = 0; i < ubounds.length; i++) { GenTypeClass [] blist = ubounds[i].getReferenceSupertypes(); for (int j = 0; j < blist.length; j++) { rlist.add(blist[j].mapToSuper(r.getName())); } } return rlist.toArray(new GenTypeClass[rlist.size()]); } @Override public GenTypeSolid[] getIntersectionTypes() { return new GenTypeSolid[] {this }; } }

.   erasedSuperTypes
.   getReferenceSupertypes
.   getParamsFromTemplate
.   getUpperBounds
.   getUpperBound
.   getLowerBound
.   getCapture
.   asSolid
.   isWildcard
.   lub
.   lub
.   Candidate
.   leastContainingInvocation
.   leastContainingInvocation
.   leastContainingTypeArgument
.   minimalErasedCandidateSet
.   relevantInvocations
.   getIntersectionTypes




394 neLoCode + 52 LoComm