public ProducedType getIteratedType(ProducedType type) { ProducedType st = type.getSupertype(getIterableDeclaration()); if (st != null && st.getTypeArguments().size() == 1) { return st.getTypeArgumentList().get(0); } else { return null; } }
public ProducedType getValueType(ProducedType type) { ProducedType st = type.getSupertype(getEntryDeclaration()); if (st != null && st.getTypeArguments().size() == 2) { return st.getTypeArgumentList().get(1); } else { return null; } }
/** * Eliminate the given type from the union type. (Performs a set complement operation.) Note that * this operation is not robust and only works if this is a union of the given type with some * other types that don't involve the given type. */ public ProducedType minus(ClassOrInterface ci) { if (getDeclaration().equals(ci)) { return new BottomType(getDeclaration().getUnit()).getType(); } else if (getDeclaration() instanceof UnionType) { List<ProducedType> types = new ArrayList<ProducedType>(); for (ProducedType ct : getCaseTypes()) { if (ct.getSupertype(ci) == null) { addToUnion(types, ct.minus(ci)); } } UnionType ut = new UnionType(getDeclaration().getUnit()); ut.setCaseTypes(types); return ut.getType(); } else { return this; } }
private ProducedType qualifiedByDeclaringType() { ProducedType qt = getQualifyingType(); if (qt == null) { return this; } else { ProducedType pt = new ProducedType(); pt.setDeclaration(getDeclaration()); pt.setTypeArguments(getTypeArguments()); // replace the qualifying type with // the supertype of the qualifying // type that declares this nested // type, substituting type arguments ProducedType declaringType = qt.getSupertype((TypeDeclaration) getDeclaration().getContainer()); pt.setQualifyingType(declaringType); return pt; } }
private ProducedType getCommonSupertype( final List<ProducedType> caseTypes, TypeDeclaration dec, final TypeDeclaration selfTypeToIgnore) { // now try to construct a common produced // type that is a common supertype by taking // the type args and unioning them List<ProducedType> args = new ArrayList<ProducedType>(); for (TypeParameter tp : dec.getTypeParameters()) { List<ProducedType> list2 = new ArrayList<ProducedType>(); ProducedType result; if (tp.isContravariant()) { for (ProducedType pt : caseTypes) { ProducedType st = pt.getSupertype(dec, selfTypeToIgnore); if (st == null) { return null; } addToIntersection(list2, st.getTypeArguments().get(tp)); } IntersectionType it = new IntersectionType(getDeclaration().getUnit()); it.setSatisfiedTypes(list2); result = it.canonicalize().getType(); } else { for (ProducedType pt : caseTypes) { ProducedType st = pt.getSupertype(dec, selfTypeToIgnore); if (st == null) { return null; } addToUnion(list2, st.getTypeArguments().get(tp)); } UnionType ut = new UnionType(getDeclaration().getUnit()); ut.setCaseTypes(list2); result = ut.getType(); } args.add(result); } // check that the unioned type args // satisfy the type constraints for (int i = 0; i < args.size(); i++) { TypeParameter tp = dec.getTypeParameters().get(i); for (ProducedType ub : tp.getSatisfiedTypes()) { if (!args.get(i).isSubtypeOf(ub)) { return null; } } } // recurse to the qualifying type ProducedType outerType; if (dec.isMember()) { TypeDeclaration outer = (TypeDeclaration) dec.getContainer(); List<ProducedType> list = new ArrayList<ProducedType>(); for (ProducedType pt : caseTypes) { ProducedType st = pt.getQualifyingType().getSupertype(outer, null); list.add(st); } outerType = getCommonSupertype(list, outer, null); } else { outerType = null; } // make the resulting type ProducedType candidateResult = dec.getProducedType(outerType, args); // check the the resulting type is *really* // a subtype (take variance into account) for (ProducedType pt : caseTypes) { if (!pt.isSubtypeOf(candidateResult)) { return null; } } return candidateResult; }
/** Search for the most-specialized supertype satisfying the given predicate. */ private ProducedType getSupertype( final Criteria c, List<ProducedType> list, final TypeDeclaration ignoringSelfType) { if (c.satisfies(getDeclaration())) { return qualifiedByDeclaringType(); } if (isWellDefined() && Util.addToSupertypes(list, this)) { // search for the most-specific supertype // for the given declaration ProducedType result = null; ProducedType extendedType = getInternalExtendedType(); if (extendedType != null) { ProducedType possibleResult = extendedType.getSupertype(c, list, ignoringSelfType); if (possibleResult != null) { result = possibleResult; } } for (ProducedType dst : getInternalSatisfiedTypes()) { ProducedType possibleResult = dst.getSupertype(c, list, ignoringSelfType); if (possibleResult != null && (result == null || possibleResult.isSubtypeOf(result, ignoringSelfType))) { result = possibleResult; } } if (!getDeclaration().equals(ignoringSelfType)) { ProducedType selfType = getInternalSelfType(); if (selfType != null) { ProducedType possibleResult = selfType.getSupertype(c, list, ignoringSelfType); if (possibleResult != null && (result == null || possibleResult.isSubtypeOf(result, ignoringSelfType))) { result = possibleResult; } } } final List<ProducedType> caseTypes = getInternalCaseTypes(); if (caseTypes != null && !caseTypes.isEmpty()) { // first find a common superclass or superinterface // declaration that satisfies the criteria, ignoring // type arguments for now Criteria c2 = new Criteria() { @Override public boolean satisfies(TypeDeclaration type) { if (c.satisfies(type)) { for (ProducedType ct : caseTypes) { if (ct.getSupertype(type, ignoringSelfType) == null) { return false; } } return true; } else { return false; } } }; ProducedType stc = caseTypes.get(0).getSupertype(c2, list, ignoringSelfType); if (stc != null) { // we found the declaration, now try to construct a // produced type that is a true common supertype ProducedType candidateResult = getCommonSupertype(caseTypes, stc.getDeclaration(), ignoringSelfType); if (candidateResult != null && (result == null || candidateResult.isSubtypeOf(result, ignoringSelfType))) { result = candidateResult; } } } return result; } else { return null; } }
/** * Substitute invocation type arguments into an upper bound on a type parameter of the invocation, * where this type represents an upper bound. * * @param receiver the type that receives the invocation * @param member the invoked member * @param typeArguments the explicit or inferred type arguments of the invocation * @return the upper bound of a type parameter, after performing all type argument substitution */ public ProducedType getProducedType( ProducedType receiver, Declaration member, List<ProducedType> typeArguments) { ProducedType rst = (receiver == null) ? null : receiver.getSupertype((TypeDeclaration) member.getContainer()); return new Substitution().substitute(this, arguments(member, rst, typeArguments)); }
/** Is this type exactly the same type as the given type? */ public boolean isExactly(ProducedType type) { if (getDeclaration() instanceof BottomType) { return type.getDeclaration() instanceof BottomType; } else if (getDeclaration() instanceof UnionType) { List<ProducedType> cases = getCaseTypes(); if (type.getDeclaration() instanceof UnionType) { List<ProducedType> otherCases = type.getCaseTypes(); if (cases.size() != otherCases.size()) { return false; } else { for (ProducedType c : cases) { boolean found = false; for (ProducedType oc : otherCases) { if (c.isExactly(oc)) { found = true; break; } } if (!found) { return false; } } return true; } } else if (cases.size() == 1) { ProducedType st = cases.get(0); return st.isExactly(type); } else { return false; } } else if (getDeclaration() instanceof IntersectionType) { List<ProducedType> types = getSatisfiedTypes(); if (type.getDeclaration() instanceof IntersectionType) { List<ProducedType> otherTypes = type.getSatisfiedTypes(); if (types.size() != otherTypes.size()) { return false; } else { for (ProducedType c : types) { boolean found = false; for (ProducedType oc : otherTypes) { if (c.isExactly(oc)) { found = true; break; } } if (!found) { return false; } } return true; } } else if (types.size() == 1) { ProducedType st = types.get(0); return st.isExactly(type); } else { return false; } } else if (type.getDeclaration() instanceof UnionType) { List<ProducedType> otherCases = type.getCaseTypes(); if (otherCases.size() == 1) { ProducedType st = otherCases.get(0); return this.isExactly(st); } else { return false; } } else if (type.getDeclaration() instanceof IntersectionType) { List<ProducedType> otherTypes = type.getSatisfiedTypes(); if (otherTypes.size() == 1) { ProducedType st = otherTypes.get(0); return this.isExactly(st); } else { return false; } } else { if (!type.getDeclaration().equals(getDeclaration())) { return false; } else { ProducedType qt = getQualifyingType(); ProducedType tqt = type.getQualifyingType(); if (qt == null) { if (tqt != null) { return false; } } else { if (tqt == null) { return false; } else { TypeDeclaration totd = (TypeDeclaration) type.getDeclaration().getContainer(); ProducedType tqts = tqt.getSupertype(totd); TypeDeclaration otd = (TypeDeclaration) getDeclaration().getContainer(); ProducedType qts = qt.getSupertype(otd); if (!qts.isExactly(tqts)) { return false; } } } for (TypeParameter p : getDeclaration().getTypeParameters()) { ProducedType arg = getTypeArguments().get(p); ProducedType otherArg = type.getTypeArguments().get(p); if (arg == null || otherArg == null) { return false; /*throw new RuntimeException( "Missing type argument for: " + p.getName() + " of " + getDeclaration().getName());*/ } else if (!arg.isExactly(otherArg)) { return false; } } return true; } } }
/** Is this type a subtype of the given type? Ignore a certain self type constraint. */ public boolean isSubtypeOf(ProducedType type, TypeDeclaration selfTypeToIgnore) { if (getDeclaration() instanceof BottomType) { return true; } else if (type.getDeclaration() instanceof BottomType) { return false; } else if (getDeclaration() instanceof UnionType) { for (ProducedType ct : getInternalCaseTypes()) { if (ct == null || !ct.isSubtypeOf(type, selfTypeToIgnore)) { return false; } } return true; } else if (type.getDeclaration() instanceof UnionType) { for (ProducedType ct : type.getInternalCaseTypes()) { if (ct != null && isSubtypeOf(ct, selfTypeToIgnore)) { return true; } } return false; } else if (type.getDeclaration() instanceof IntersectionType) { for (ProducedType ct : type.getInternalSatisfiedTypes()) { if (ct != null && !isSubtypeOf(ct, selfTypeToIgnore)) { return false; } } return true; } else if (getDeclaration() instanceof IntersectionType) { for (ProducedType ct : getInternalSatisfiedTypes()) { if (ct == null || ct.isSubtypeOf(type, selfTypeToIgnore)) { return true; } } return false; } else { ProducedType st = getSupertype(type.getDeclaration(), selfTypeToIgnore); if (st == null) { return false; } else { ProducedType stqt = st.getQualifyingType(); ProducedType tqt = type.getQualifyingType(); if (stqt == null) { if (tqt != null) { // probably extraneous! return false; } } else { if (tqt == null) { // probably extraneous! return false; } else { // note that the qualifying type of the // given type may be an invariant subtype // of the type that declares the member // type, as long as it doesn't refine the // member type TypeDeclaration totd = (TypeDeclaration) type.getDeclaration().getContainer(); ProducedType tqts = tqt.getSupertype(totd); if (!stqt.isSubtypeOf(tqts)) { return false; } } } for (TypeParameter p : type.getDeclaration().getTypeParameters()) { ProducedType arg = st.getTypeArguments().get(p); ProducedType otherArg = type.getTypeArguments().get(p); if (arg == null || otherArg == null) { /*throw new RuntimeException("Missing type argument for type parameter: " + p.getName() + " of " + type.getDeclaration().getName());*/ return false; } else if (p.isCovariant()) { if (!arg.isSubtypeOf(otherArg)) { return false; } } else if (p.isContravariant()) { if (!otherArg.isSubtypeOf(arg)) { return false; } } else { if (!arg.isExactly(otherArg)) { return false; } } } return true; } } }
public boolean isIterableType(ProducedType pt) { return pt.getSupertype(getIterableDeclaration()) != null; }
public boolean isEntryType(ProducedType pt) { return pt.getSupertype(getEntryDeclaration()) != null; }