| /******************************************************************************* |
| * Copyright (c) 2000, 2006 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.corext.refactoring.structure.constraints; |
| |
| import org.eclipse.core.runtime.Assert; |
| |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.HierarchyType; |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType; |
| import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet; |
| |
| /** |
| * Optimized type sets for supertype constraint problems. |
| */ |
| public abstract class SuperTypeSet implements ITypeSet { |
| |
| /** Implementation of an empty set */ |
| private static class SuperTypeEmptySet extends SuperTypeSet { |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet#chooseSingleType() |
| */ |
| public final TType chooseSingleType() { |
| return null; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet#isEmpty() |
| */ |
| public final boolean isEmpty() { |
| return true; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet#restrictedTo(org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet) |
| */ |
| public final ITypeSet restrictedTo(final ITypeSet set) { |
| return this; |
| } |
| |
| /* |
| * @see java.lang.Object#toString() |
| */ |
| public final String toString() { |
| return "EMPTY"; //$NON-NLS-1$ |
| } |
| } |
| |
| /** Implementation of a singleton */ |
| private static class SuperTypeSingletonSet extends SuperTypeSet { |
| |
| /** The type */ |
| private final TType fType; |
| |
| /** |
| * Creates a new super type singleton set. |
| * |
| * @param type the type |
| */ |
| private SuperTypeSingletonSet(final TType type) { |
| fType= type; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet#chooseSingleType() |
| */ |
| public final TType chooseSingleType() { |
| return fType; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet#isEmpty() |
| */ |
| public final boolean isEmpty() { |
| return false; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet#restrictedTo(org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet) |
| */ |
| public final ITypeSet restrictedTo(final ITypeSet set) { |
| final TType leftErasure= fType.getErasure(); |
| if (set instanceof SuperTypeUniverse) { |
| return this; |
| } else if (set instanceof SuperTypeSingletonSet) { |
| if (this == set) |
| return this; |
| if (fType.isNullType()) |
| return this; |
| final SuperTypeSingletonSet singleton= (SuperTypeSingletonSet) set; |
| final TType rightErasure= singleton.fType.getErasure(); |
| if (leftErasure.isGenericType() || rightErasure.isGenericType()) { |
| if (rightErasure.equals(leftErasure) || ((HierarchyType) leftErasure).isSubType((HierarchyType) rightErasure)) |
| return this; |
| } |
| if (rightErasure.isJavaLangObject()) |
| return this; |
| if (leftErasure.canAssignTo(rightErasure)) |
| return this; |
| return SuperTypeSet.getEmpty(); |
| } else if (set instanceof SuperTypeTuple) { |
| if (fType.isNullType()) |
| return this; |
| final SuperTypeTuple tuple= (SuperTypeTuple) set; |
| final TType rightErasure= tuple.fSuperType.getErasure(); |
| if (leftErasure.isGenericType() || rightErasure.isGenericType()) { |
| if (rightErasure.equals(leftErasure) || ((HierarchyType) leftErasure).isSubType((HierarchyType) rightErasure)) |
| return this; |
| } |
| if (rightErasure.isJavaLangObject()) |
| return this; |
| if (leftErasure.canAssignTo(rightErasure)) |
| return this; |
| return SuperTypeSet.createTypeSet(tuple.fSubType); |
| } else if (set instanceof SuperTypeEmptySet) { |
| return set; |
| } else |
| Assert.isTrue(false); |
| return null; |
| } |
| |
| /* |
| * @see java.lang.Object#toString() |
| */ |
| public final String toString() { |
| return fType.getPrettySignature(); |
| } |
| } |
| |
| /** Implementation of a tuple */ |
| private static class SuperTypeTuple extends SuperTypeSet { |
| |
| /** The other type */ |
| private final TType fSubType; |
| |
| /** The super type */ |
| private final TType fSuperType; |
| |
| /** |
| * Creates a new super type tuple. |
| * |
| * @param subType the sub type |
| * @param superType the super type |
| */ |
| private SuperTypeTuple(final TType subType, final TType superType) { |
| fSubType= subType; |
| fSuperType= superType; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet#chooseSingleType() |
| */ |
| public final TType chooseSingleType() { |
| return fSuperType; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet#isEmpty() |
| */ |
| public final boolean isEmpty() { |
| return false; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet#restrictedTo(org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet) |
| */ |
| public final ITypeSet restrictedTo(final ITypeSet set) { |
| if (set instanceof SuperTypeUniverse) { |
| return this; |
| } else if (set instanceof SuperTypeSingletonSet) { |
| final SuperTypeSingletonSet singleton= (SuperTypeSingletonSet) set; |
| final TType rightErasure= singleton.fType.getErasure(); |
| final TType subErasure= fSubType.getErasure(); |
| final TType superErasure= fSuperType.getErasure(); |
| if (subErasure.isGenericType() || superErasure.isGenericType() || rightErasure.isGenericType()) { |
| if ((rightErasure.equals(subErasure) || ((HierarchyType) subErasure).isSubType((HierarchyType) rightErasure)) && (rightErasure.equals(superErasure) || ((HierarchyType) superErasure).isSubType((HierarchyType) rightErasure))) |
| return this; |
| } |
| if (rightErasure.isJavaLangObject()) |
| return this; |
| if (subErasure.canAssignTo(rightErasure) && superErasure.canAssignTo(rightErasure)) |
| return this; |
| return SuperTypeSet.createTypeSet(fSubType); |
| } else if (set instanceof SuperTypeTuple) { |
| return this; |
| } else if (set instanceof SuperTypeEmptySet) { |
| return set; |
| } else |
| Assert.isTrue(false); |
| return null; |
| } |
| |
| /* |
| * @see java.lang.Object#toString() |
| */ |
| public final String toString() { |
| return "[" + fSubType.getPrettySignature() + ", " + fSuperType.getPrettySignature() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| } |
| } |
| |
| /** Implementation of the type universe */ |
| private static class SuperTypeUniverse extends SuperTypeSet { |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet#chooseSingleType() |
| */ |
| public final TType chooseSingleType() { |
| return null; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet#isEmpty() |
| */ |
| public final boolean isEmpty() { |
| return false; |
| } |
| |
| /* |
| * @see org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet#restrictedTo(org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeSet) |
| */ |
| public final ITypeSet restrictedTo(final ITypeSet set) { |
| return set; |
| } |
| |
| /* |
| * @see java.lang.Object#toString() |
| */ |
| public final String toString() { |
| return "UNIVERSE"; //$NON-NLS-1$ |
| } |
| } |
| |
| /** The empty set */ |
| private static final ITypeSet fgEmpty= new SuperTypeEmptySet(); |
| |
| /** The universe */ |
| private static final ITypeSet fgUniverse= new SuperTypeUniverse(); |
| |
| /** |
| * Creates a new type set. |
| * |
| * @param type the type to contain, or <code>null</code> |
| * @return the type set, or the universe if <code>type</code> is <code>null</code> |
| */ |
| public static ITypeSet createTypeSet(final TType type) { |
| if (type == null) |
| return fgUniverse; |
| return new SuperTypeSingletonSet(type); |
| } |
| |
| /** |
| * Creates a new type set. |
| * |
| * @param subType the sub type |
| * @param superType the super type |
| * @return the type set, or the universe if <code>type</code> is <code>null</code> |
| */ |
| public static ITypeSet createTypeSet(final TType subType, final TType superType) { |
| if (subType == null || superType == null) |
| return fgUniverse; |
| return new SuperTypeTuple(subType, superType); |
| } |
| |
| /** |
| * Returns the empty set. |
| * |
| * @return the empty set |
| */ |
| public static ITypeSet getEmpty() { |
| return fgEmpty; |
| } |
| |
| /** |
| * Returns the universe set. |
| * |
| * @return the universe set |
| */ |
| public static ITypeSet getUniverse() { |
| return fgUniverse; |
| } |
| } |