| /******************************************************************************* |
| * Copyright (c) 2000, 2011 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * 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.TType; |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TTypes; |
| |
| public class TypeSetIntersection extends TypeSet { |
| private TypeSet fLHS; |
| private TypeSet fRHS; |
| |
| public TypeSetIntersection(TypeSet lhs, TypeSet rhs) { |
| super(lhs.getTypeSetEnvironment()); |
| fLHS= lhs; |
| fRHS= rhs; |
| } |
| |
| /** |
| * @return Returns the LHS. |
| */ |
| public TypeSet getLHS() { |
| return fLHS; |
| } |
| |
| /** |
| * @return Returns the RHS. |
| */ |
| public TypeSet getRHS() { |
| return fRHS; |
| } |
| |
| @Override |
| public boolean isUniverse() { |
| return fLHS.isUniverse() && fRHS.isUniverse(); |
| } |
| |
| @Override |
| public TypeSet makeClone() { |
| return this; //new TypeSetIntersection(fLHS.makeClone(), fRHS.makeClone()); |
| } |
| |
| @Override |
| public boolean isEmpty() { |
| if (fLHS.isEmpty() || fRHS.isEmpty()) |
| return true; |
| if (fLHS.isUniverse() || fRHS.isUniverse()) |
| return false; |
| // Another quick check we can make before jumping to the expensive stuff |
| if (fLHS.contains(getJavaLangObject()) && fRHS.contains(getJavaLangObject())) |
| return false; |
| |
| // TypeSet lhsLB= fLHS.lowerBound(); |
| // TypeSet rhsUB= fRHS.upperBound(); |
| // |
| // // Avoid the infinite recursion that will occur if lhsLB == fLHS && rhsUB == fRHS |
| // if ((!lhsLB.equals(fLHS) || !rhsUB.equals(fRHS)) && |
| // !lhsLB.intersectedWith(rhsUB).isEmpty()) |
| // return false; |
| // |
| // if (areAllSuperTypesOf(lhsLB, rhsUB)) |
| // return true; |
| // |
| // TypeSet lhsUB= fLHS.upperBound(); |
| // TypeSet rhsLB= fRHS.lowerBound(); |
| // |
| // if (!lhsUB.intersectedWith(rhsLB).isEmpty()) |
| // return false; |
| // |
| // if (areAllSuperTypesOf(rhsLB, lhsUB)) |
| // return true; |
| |
| return false; |
| } |
| |
| @Override |
| public boolean contains(TType t) { |
| return fLHS.contains(t) && fRHS.contains(t); |
| } |
| |
| @Override |
| public boolean containsAll(TypeSet s) { |
| return fLHS.containsAll(s) && fRHS.containsAll(s); |
| } |
| |
| @Override |
| public TypeSet subTypes() { |
| if (isUniverse() || contains(getJavaLangObject())) |
| return getTypeSetEnvironment().getUniverseTypeSet(); |
| // sub(xsect(sub(a),sub(b))) == xsect(sub(a),sub(b)) |
| if ((fLHS instanceof SubTypesSet || fLHS instanceof SubTypesOfSingleton) && |
| (fRHS instanceof SubTypesSet || fRHS instanceof SubTypesOfSingleton)) |
| return this; |
| return getTypeSetEnvironment().createSubTypesSet(this); |
| } |
| |
| @Override |
| public TypeSet superTypes() { |
| // super(xsect(super(a),super(b))) == xsect(super(a),super(b)) |
| if ((fLHS instanceof SuperTypesSet || fLHS instanceof SuperTypesOfSingleton) && |
| (fRHS instanceof SuperTypesSet || fRHS instanceof SuperTypesOfSingleton)) |
| return this; |
| return getTypeSetEnvironment().createSuperTypesSet(this); |
| } |
| |
| @Override |
| public TypeSet upperBound() { |
| if (fLHS.contains(getJavaLangObject()) && fRHS.contains(getJavaLangObject())) |
| return new SingletonTypeSet(getTypeSetEnvironment().getJavaLangObject(), getTypeSetEnvironment()); |
| |
| if (fEnumCache != null) return fEnumCache.upperBound(); |
| |
| EnumeratedTypeSet lhsSet= fLHS.enumerate(); |
| EnumeratedTypeSet rhsSet= fRHS.enumerate(); |
| TypeSet xsect= lhsSet.intersectedWith(rhsSet); |
| |
| return xsect.upperBound(); |
| } |
| |
| @Override |
| public TypeSet lowerBound() { |
| if (fLHS.hasUniqueLowerBound() && fRHS.hasUniqueLowerBound()) { |
| TType lhsBound= fLHS.uniqueLowerBound(); |
| TType rhsBound= fRHS.uniqueLowerBound(); |
| |
| if (lhsBound.equals(rhsBound)) |
| return new SingletonTypeSet(lhsBound, getTypeSetEnvironment()); |
| else if (TTypes.canAssignTo(lhsBound, rhsBound)) |
| return new SingletonTypeSet(rhsBound, getTypeSetEnvironment()); |
| else if (TTypes.canAssignTo(rhsBound, lhsBound)) |
| return new SingletonTypeSet(lhsBound, getTypeSetEnvironment()); |
| } |
| if (fEnumCache != null) return fEnumCache.lowerBound(); |
| |
| EnumeratedTypeSet lhsSet= fLHS.enumerate(); |
| EnumeratedTypeSet rhsSet= fRHS.enumerate(); |
| TypeSet xsect= lhsSet.intersectedWith(rhsSet); |
| |
| return xsect.lowerBound(); |
| } |
| |
| @Override |
| protected TypeSet specialCasesIntersectedWith(TypeSet s2) { |
| if (s2.equals(fLHS)) // xsect(s2,xsect(s2,?)) = xsect(s2,?) |
| return this; |
| if (s2.equals(fRHS)) // xsect(s2,xsect(?,s2)) = xsect(?,s2) |
| return this; |
| if (s2 instanceof TypeSetIntersection) { |
| TypeSetIntersection x2= (TypeSetIntersection) s2; |
| // |
| // The following should use a "quick equals()" guaranteed to be constant-time |
| // |
| // xsect(xsect(A,B),xsect(A,C)) = xsect(xsect(A,B),C) |
| if (fLHS.equals(x2.fLHS)) |
| return new TypeSetIntersection(this, x2.fRHS); |
| // xsect(xsect(A,B),xsect(C,A)) = xsect(xsect(A,B),C) |
| if (fLHS.equals(x2.fRHS)) |
| return new TypeSetIntersection(this, x2.fLHS); |
| // xsect(xsect(A,B),xsect(B,C)) = xsect(xsect(A,B),C) |
| if (fRHS.equals(x2.fLHS)) |
| return new TypeSetIntersection(this, x2.fRHS); |
| // xsect(xsect(A,B),xsect(C,B)) = xsect(xsect(A,B),C) |
| if (fRHS.equals(x2.fRHS)) |
| return new TypeSetIntersection(this, x2.fLHS); |
| } |
| return null; |
| } |
| |
| @Override |
| public boolean isSingleton() { |
| if (fEnumCache != null) return fEnumCache.isSingleton(); |
| |
| int count= 0; |
| for(Iterator<TType> lhsIter= fLHS.iterator(); lhsIter.hasNext(); ) { |
| TType t= lhsIter.next(); |
| if (fRHS.contains(t)) |
| count++; |
| if (count > 1) |
| return false; |
| } |
| return (count == 1); |
| } |
| |
| @Override |
| public TType anyMember() { |
| if (fEnumCache != null) return fEnumCache.anyMember(); |
| |
| for(Iterator<TType> lhsIter= fLHS.iterator(); lhsIter.hasNext(); ) { |
| TType t= lhsIter.next(); |
| if (fRHS.contains(t)) |
| return t; |
| } |
| return null; |
| } |
| |
| @Override |
| public Iterator<TType> iterator() { |
| return enumerate().iterator(); |
| |
| // return new Iterator() { |
| // private Iterator fLHSIter= fLHS.iterator(); |
| // private TType fNext= null; |
| // public void remove() { |
| // throw new IllegalStateException("Unimplemented"); |
| // } |
| // private void advance() { |
| // for(; fLHSIter.hasNext(); ) { |
| // TType t= (TType) fLHSIter.next(); |
| // if (fRHS.contains(t)) { |
| // fNext= t; |
| // break; |
| // } |
| // } |
| // } |
| // public boolean hasNext() { |
| // if (fNext == null) |
| // advance(); |
| // return fNext != null; |
| // } |
| // public Object next() { |
| // if (fNext == null) |
| // advance(); |
| // if (fNext == null) |
| // throw new NoSuchElementException("No more elements in TypeSetIntersection"); |
| // TType result= fNext; |
| // fNext= null; |
| // return result; |
| // } |
| // }; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof TypeSetIntersection) { |
| TypeSetIntersection other= (TypeSetIntersection) o; |
| return other.fLHS.equals(fLHS) && other.fRHS.equals(fRHS); |
| } else |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return fLHS.hashCode() * 37 + fRHS.hashCode(); |
| } |
| |
| @Override |
| public String toString() { |
| return "<" + fID + ": intersect(" + fLHS + "," + fRHS + ")>"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
| } |
| |
| @Override |
| public boolean hasUniqueLowerBound() { |
| return false; |
| } |
| |
| @Override |
| public boolean hasUniqueUpperBound() { |
| return false; |
| } |
| |
| @Override |
| public TType uniqueLowerBound() { |
| return null; |
| } |
| |
| @Override |
| public TType uniqueUpperBound() { |
| return null; |
| } |
| |
| private EnumeratedTypeSet fEnumCache= null; |
| |
| @Override |
| public EnumeratedTypeSet enumerate() { |
| if (fEnumCache == null) { |
| EnumeratedTypeSet lhsSet= fLHS.enumerate(); |
| EnumeratedTypeSet rhsSet= fRHS.enumerate(); |
| fEnumCache= lhsSet.intersectedWith(rhsSet).enumerate(); |
| } |
| |
| return fEnumCache; |
| } |
| } |