blob: 3a43abf66d2020f48a7c050e5f13b4e68668b2b7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Robert M. Fuhrer (rfuhrer@watson.ibm.com), IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets;
import java.util.Iterator;
import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.ArrayType;
import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TTypes;
public class SubTypesSet extends TypeSet {
/**
* The set of "base types" defining the upper bounds of this set.
*/
private TypeSet fUpperBounds;
SubTypesSet(TypeSet superTypes) {
super(superTypes.getTypeSetEnvironment());
fUpperBounds= superTypes;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#isUniverse()
*/
public boolean isUniverse() {
return fUpperBounds.isUniverse() || fUpperBounds.contains(getJavaLangObject());
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#makeClone()
*/
public TypeSet makeClone() {
return this; //new SubTypesSet(fUpperBounds.makeClone());
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object o) {
if (o instanceof SubTypesSet) {
SubTypesSet other= (SubTypesSet) o;
return other.fUpperBounds.equals(fUpperBounds);
// } else if (o instanceof TypeSet) {
// TypeSet other= (TypeSet) o;
// if (other.isUniverse() && isUniverse())
// return true;
// return enumerate().equals(other.enumerate());
} else
return false;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#intersectedWith(org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.EnumeratedTypeSet)
*/
protected TypeSet specialCasesIntersectedWith(TypeSet s2) {
if (fUpperBounds.equals(s2))
return s2; // xsect(subTypes(A),A) = A
if (s2 instanceof SubTypesSet) {
SubTypesSet st2= (SubTypesSet) s2;
if (fUpperBounds.isSingleton() && st2.fUpperBounds.isSingleton()) {
TType t1= this.fUpperBounds.anyMember();
TType t2= st2.fUpperBounds.anyMember();
if (TTypes.canAssignTo(t2, t1))
return new SubTypesSet(st2.fUpperBounds);
} else if (fUpperBounds instanceof SubTypesSet) {
// xsect(subTypes(superTypes(A)), subTypes(A)) = subTypes(A)
SubTypesSet myUpperSubTypes= (SubTypesSet) fUpperBounds;
if (myUpperSubTypes.lowerBound().equals(st2.lowerBound()))
return st2;
}
}
if (s2 instanceof SubTypesOfSingleton) {
SubTypesOfSingleton st2= (SubTypesOfSingleton) s2;
if (fUpperBounds.isSingleton()) {
TType t1= this.fUpperBounds.anyMember();
TType t2= st2.uniqueUpperBound();
if (TTypes.canAssignTo(t2, t1))
return getTypeSetEnvironment().createSubTypesOfSingleton(t2);
} else if (fUpperBounds instanceof SubTypesOfSingleton) {
// xsect(subTypes(superTypes(A)), subTypes(A)) = subTypes(A)
SubTypesOfSingleton myUpperSubTypes= (SubTypesOfSingleton) fUpperBounds;
if (myUpperSubTypes.uniqueLowerBound().equals(st2.uniqueLowerBound()))
return st2;
}
}
if (s2 instanceof SuperTypesSet) {
SuperTypesSet st2= (SuperTypesSet) s2;
if (fUpperBounds.equals(st2.lowerBound()))
return fUpperBounds;
if (fUpperBounds instanceof TypeSetIntersection) {
// (intersect (subTypes (intersect (superTypes A) B))
// (superTypes A)) =>
// (intersect (superTypes A) (subTypes B))
TypeSetIntersection lbXSect= (TypeSetIntersection) fUpperBounds;
TypeSet xsectLeft= lbXSect.getLHS();
TypeSet xsectRight= lbXSect.getRHS();
if (xsectLeft.equals(st2.lowerBound()))
return new TypeSetIntersection(s2, new SubTypesSet(xsectRight));
}
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#subTypes()
*/
public TypeSet subTypes() {
return this; // makeClone();
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#isEmpty()
*/
public boolean isEmpty() {
return fUpperBounds.isEmpty();
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#contains(TType)
*/
public boolean contains(TType t) {
if (fEnumCache != null) return fEnumCache.contains(t);
if (fUpperBounds.contains(t))
return true;
// Find the "upper frontier", i.e. the upper bound, and see whether
// the given type is a subtype of any of those.
Iterator ubIter= fUpperBounds.upperBound().iterator();
for(; ubIter.hasNext(); ) {
TType ub= (TType) ubIter.next();
if (TTypes.canAssignTo(t, ub))
return true;
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#containsAll(org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.EnumeratedTypeSet)
*/
public boolean containsAll(TypeSet s) {
if (fEnumCache != null) return fEnumCache.containsAll(s);
if (fUpperBounds.containsAll(s))
return true;
// Make sure all elements of s are contained in this set
for(Iterator sIter= s.iterator(); sIter.hasNext(); ) {
TType t= (TType) sIter.next();
boolean found= false;
// Scan the "upper frontier", i.e. the upper bound set, and see whether
// 't' is a subtype of any of those.
for(Iterator ubIter= fUpperBounds /*.upperBound() */.iterator(); ubIter.hasNext(); ) {
TType ub= (TType) ubIter.next();
if (TTypes.canAssignTo(t, ub)) {
found= true;
break;
}
}
if (!found) return false;
}
return true;
}
/**
* Returns the element type of the given TType, if an array type, or the
* given TType itself, otherwise.
*/
private TType getElementTypeOf(TType t) {
if (t instanceof ArrayType)
return ((ArrayType) t).getElementType();
return t;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#isSingleton()
*/
public boolean isSingleton() {
if (!fUpperBounds.isSingleton())
return false;
TType t= fUpperBounds.anyMember();
return getElementTypeOf(t).getSubTypes().length == 0;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#anyMember()
*/
public TType anyMember() {
return fUpperBounds.anyMember();
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#upperBound()
*/
public TypeSet upperBound() {
return fUpperBounds; // perhaps should be unmodifiable?
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#lowerBound()
*/
public TypeSet lowerBound() {
return enumerate().lowerBound();
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#iterator()
*/
public Iterator iterator() {
return enumerate().iterator();
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString() {
return "<" + fID + ": subTypes(" + fUpperBounds + ")>"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#hasUniqueLowerBound()
*/
public boolean hasUniqueLowerBound() {
return false;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#hasUniqueUpperBound()
*/
public boolean hasUniqueUpperBound() {
return fUpperBounds.isSingleton();
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#uniqueLowerBound()
*/
public TType uniqueLowerBound() {
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#uniqueUpperBound()
*/
public TType uniqueUpperBound() {
return fUpperBounds.isSingleton() ? fUpperBounds.anyMember() : null;
}
private EnumeratedTypeSet fEnumCache= null;
/* (non-Javadoc)
* @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints.typesets.TypeSet#enumerate()
*/
public EnumeratedTypeSet enumerate() {
if (fEnumCache == null) {
fEnumCache= new EnumeratedTypeSet(getTypeSetEnvironment());
for(Iterator iter= fUpperBounds.iterator(); iter.hasNext(); ) {
TType ub= (TType) iter.next();
if (ub instanceof ArrayType) {
ArrayType at= (ArrayType) ub;
int numDims= at.getDimensions();
for(Iterator elemSubIter=TTypes.getAllSubTypesIterator(at.getElementType()); elemSubIter.hasNext(); )
fEnumCache.add(TTypes.createArrayType((TType) elemSubIter.next(), numDims));
} else {
for (Iterator iterator= TTypes.getAllSubTypesIterator(ub); iterator.hasNext();) {
fEnumCache.fMembers.add(iterator.next());
}
}
fEnumCache.add(ub);
}
// fEnumCache.initComplete();
}
return fEnumCache;
}
}