/projects/eclipse_SDK-3.7.1/plugins/org.eclipse.jdt.ui.source_3.7.1.r371_v20110824-0800/org/eclipse/jdt/internal/corext/refactoring/structure/constraints/SuperTypeConstraintsModel.java
Java | 604 lines | 325 code | 56 blank | 223 comment | 75 complexity | b90c1f26c7e353304cf9779b63c0e526 MD5 | raw file
- /*******************************************************************************
- * Copyright (c) 2000, 2011 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 java.util.AbstractSet;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.LinkedHashMap;
- import java.util.Map;
- import java.util.Set;
- import org.eclipse.jdt.core.dom.CastExpression;
- import org.eclipse.jdt.core.dom.IMethodBinding;
- import org.eclipse.jdt.core.dom.ITypeBinding;
- import org.eclipse.jdt.core.dom.IVariableBinding;
- import org.eclipse.jdt.core.dom.Name;
- import org.eclipse.jdt.core.dom.Type;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TypeEnvironment;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.CastVariable2;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ConstraintVariable2;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraint2;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ImmutableTypeVariable2;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.IndependentTypeVariable2;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ParameterTypeVariable2;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ReturnTypeVariable2;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.SubTypeConstraint2;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeEquivalenceSet;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeVariable2;
- import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.VariableVariable2;
- import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
- /**
- * Type constraints model to hold all type constraints to replace type occurrences by a given supertype.
- *
- * @since 3.1
- */
- public final class SuperTypeConstraintsModel {
- /** Customized implementation of a hash set
- * @param <E> the element type */
- private static class HashedSet<E> extends AbstractSet<E> {
- /** The backing hash map */
- private final Map<E, E> fImplementation= new HashMap<E, E>();
- /*
- * @see java.util.AbstractCollection#add(java.lang.Object)
- */
- @Override
- public final boolean add(final E object) {
- return fImplementation.put(object, object) == null;
- }
- /**
- * Attempts to add the specified object to this set.
- *
- * @param object the object to add
- * @return An already existing object considered equal to the specified one, or the newly added object
- */
- public final E addExisting(final E object) {
- final E result= fImplementation.get(object);
- if (result != null)
- return result;
- fImplementation.put(object, object);
- return object;
- }
- /*
- * @see java.util.AbstractCollection#clear()
- */
- @Override
- public final void clear() {
- fImplementation.clear();
- }
- /*
- * @see java.util.AbstractCollection#contains(java.lang.Object)
- */
- @Override
- public final boolean contains(final Object object) {
- return fImplementation.containsKey(object);
- }
- /*
- * @see java.util.AbstractCollection#isEmpty()
- */
- @Override
- public final boolean isEmpty() {
- return fImplementation.isEmpty();
- }
- /*
- * @see java.util.AbstractCollection#iterator()
- */
- @Override
- public final Iterator<E> iterator() {
- return fImplementation.keySet().iterator();
- }
- /*
- * @see java.util.AbstractCollection#remove(java.lang.Object)
- */
- @Override
- public final boolean remove(final Object object) {
- return fImplementation.remove(object) == object;
- }
- /*
- * @see java.util.AbstractCollection#size()
- */
- @Override
- public final int size() {
- return fImplementation.size();
- }
- }
- /** The usage data */
- private static final String DATA_USAGE= "us"; //$NON-NLS-1$
- /** Maximal number of TTypes */
- private static final int MAX_CACHE= 64;
- /**
- * Returns the usage of the specified constraint variable.
- *
- * @param variable the constraint variable
- * @return the usage of the constraint variable (element type: <code>ITypeConstraint2</code>)
- */
- public static Collection<ITypeConstraint2> getVariableUsage(final ConstraintVariable2 variable) {
- final Object data= variable.getData(DATA_USAGE);
- if (data == null) {
- return Collections.emptyList();
- } else if (data instanceof Collection) {
- @SuppressWarnings("unchecked")
- Collection<ITypeConstraint2> collection= (Collection<ITypeConstraint2>) data;
- return Collections.unmodifiableCollection(collection);
- } else {
- return Collections.singletonList((ITypeConstraint2) data);
- }
- }
- /**
- * Is the type represented by the specified binding a constrained type?
- *
- * @param binding the binding to check, or <code>null</code>
- * @return <code>true</code> if it is constrained, <code>false</code> otherwise
- */
- public static boolean isConstrainedType(final ITypeBinding binding) {
- return binding != null && !binding.isSynthetic() && !binding.isPrimitive();
- }
- /**
- * Sets the usage of the specified constraint variable.
- *
- * @param variable the constraint variable
- * @param constraint the type constraint
- */
- public static void setVariableUsage(final ConstraintVariable2 variable, ITypeConstraint2 constraint) {
- final Object data= variable.getData(DATA_USAGE);
- if (data == null) {
- variable.setData(DATA_USAGE, constraint);
- } else if (data instanceof Collection) {
- @SuppressWarnings("unchecked")
- Collection<ITypeConstraint2> collection= (Collection<ITypeConstraint2>) data;
- collection.add(constraint);
- } else {
- final Collection<Object> usage= new ArrayList<Object>(2);
- usage.add(data);
- usage.add(constraint);
- variable.setData(DATA_USAGE, usage);
- }
- }
- /** The cast variables (element type: <code>CastVariable2</code>) */
- private final Collection<CastVariable2> fCastVariables= new ArrayList<CastVariable2>();
- /** The compliance level */
- private int fCompliance= 3;
- /** The set of constraint variables (element type: <code>ConstraintVariable2</code>) */
- private final HashedSet<ConstraintVariable2> fConstraintVariables= new HashedSet<ConstraintVariable2>();
- /** The covariant type constraints (element type: <code>CovariantTypeConstraint</code>) */
- private final Collection<ITypeConstraint2> fCovariantTypeConstraints= new ArrayList<ITypeConstraint2>();
- /** The type environment to use */
- private TypeEnvironment fEnvironment;
- /** The subtype to replace */
- private final TType fSubType;
- /** The supertype as replacement */
- private final TType fSuperType;
- /** The TType cache */
- private Map<String, TType> fTTypeCache= new LinkedHashMap<String, TType>(MAX_CACHE, 0.75f, true) {
- private static final long serialVersionUID= 1L;
- @Override
- protected final boolean removeEldestEntry(Map.Entry<String, TType> entry) {
- return size() > MAX_CACHE;
- }
- };
- /** The set of type constraints (element type: <code>ITypeConstraint2</code>) */
- private final Set<ITypeConstraint2> fTypeConstraints= new HashSet<ITypeConstraint2>();
- /**
- * Creates a new super type constraints model.
- *
- * @param environment the type environment
- * @param subType the subtype to replace
- * @param superType the supertype replacement
- */
- public SuperTypeConstraintsModel(final TypeEnvironment environment, TType subType, TType superType) {
- fEnvironment= environment;
- fSubType= subType;
- fSuperType= superType;
- }
- /**
- * Gets called when the creation of the model begins.
- */
- public final void beginCreation() {
- // Do nothing right now
- }
- /**
- * Creates a cast variable.
- *
- * @param expression the cast expression
- * @param variable the associated constraint variable
- * @return the created cast variable
- */
- public final ConstraintVariable2 createCastVariable(final CastExpression expression, final ConstraintVariable2 variable) {
- ITypeBinding binding= expression.resolveTypeBinding();
- if (binding.isArray())
- binding= binding.getElementType();
- if (isConstrainedType(binding)) {
- final CastVariable2 result= new CastVariable2(createTType(binding), new CompilationUnitRange(RefactoringASTParser.getCompilationUnit(expression), expression), variable);
- fCastVariables.add(result);
- return result;
- }
- return null;
- }
- /**
- * Creates a conditional type constraint.
- *
- * @param expressionVariable the expression type constraint variable
- * @param thenVariable the then type constraint variable
- * @param elseVariable the else type constraint variable
- */
- public final void createConditionalTypeConstraint(final ConstraintVariable2 expressionVariable, final ConstraintVariable2 thenVariable, final ConstraintVariable2 elseVariable) {
- final ITypeConstraint2 constraint= new ConditionalTypeConstraint(expressionVariable, thenVariable, elseVariable);
- if (!fTypeConstraints.contains(constraint)) {
- fTypeConstraints.add(constraint);
- setVariableUsage(expressionVariable, constraint);
- setVariableUsage(thenVariable, constraint);
- setVariableUsage(elseVariable, constraint);
- }
- }
- /**
- * Creates a subtype constraint.
- *
- * @param descendant the descendant type constraint variable
- * @param ancestor the ancestor type constraint variable
- */
- public final void createCovariantTypeConstraint(final ConstraintVariable2 descendant, final ConstraintVariable2 ancestor) {
- final ITypeConstraint2 constraint= new CovariantTypeConstraint(descendant, ancestor);
- if (!fTypeConstraints.contains(constraint)) {
- fTypeConstraints.add(constraint);
- fCovariantTypeConstraints.add(constraint);
- setVariableUsage(descendant, constraint);
- setVariableUsage(ancestor, constraint);
- }
- }
- /**
- * Creates a declaring type variable.
- * <p>
- * A declaring type variable stands for a type where something has been declared.
- * </p>
- *
- * @param type the type binding
- * @return the created declaring type variable
- */
- public final ConstraintVariable2 createDeclaringTypeVariable(ITypeBinding type) {
- if (type.isArray())
- type= type.getElementType();
- type= type.getTypeDeclaration();
- return fConstraintVariables.addExisting(new ImmutableTypeVariable2(createTType(type)));
- }
- /**
- * Creates an equality constraint.
- *
- * @param left the left typeconstraint variable
- * @param right the right typeconstraint variable
- */
- public final void createEqualityConstraint(final ConstraintVariable2 left, final ConstraintVariable2 right) {
- if (left != null && right != null) {
- final TypeEquivalenceSet first= left.getTypeEquivalenceSet();
- final TypeEquivalenceSet second= right.getTypeEquivalenceSet();
- if (first == null) {
- if (second == null) {
- final TypeEquivalenceSet set= new TypeEquivalenceSet(left, right);
- left.setTypeEquivalenceSet(set);
- right.setTypeEquivalenceSet(set);
- } else {
- second.add(left);
- left.setTypeEquivalenceSet(second);
- }
- } else {
- if (second == null) {
- first.add(right);
- right.setTypeEquivalenceSet(first);
- } else if (first == second)
- return;
- else {
- final ConstraintVariable2[] variables= second.getContributingVariables();
- first.addAll(variables);
- for (int index= 0; index < variables.length; index++)
- variables[index].setTypeEquivalenceSet(first);
- }
- }
- }
- }
- /**
- * Creates an exception variable.
- *
- * @param name the name of the thrown exception
- * @return the created exception variable
- */
- public final ConstraintVariable2 createExceptionVariable(final Name name) {
- final ITypeBinding binding= name.resolveTypeBinding();
- if (isConstrainedType(binding))
- return fConstraintVariables.addExisting(new TypeVariable2(createTType(binding), new CompilationUnitRange(RefactoringASTParser.getCompilationUnit(name), name)));
- return null;
- }
- /**
- * Creates an immutable type variable.
- *
- * @param type the type binding
- * @return the created plain type variable
- */
- public final ConstraintVariable2 createImmutableTypeVariable(ITypeBinding type) {
- if (type.isArray())
- type= type.getElementType();
- if (isConstrainedType(type))
- return fConstraintVariables.addExisting(new ImmutableTypeVariable2(createTType(type)));
- return null;
- }
- /**
- * Creates an independent type variable.
- * <p>
- * An independant type variable stands for an arbitrary type.
- * </p>
- *
- * @param type the type binding
- * @return the created independant type variable
- */
- public final ConstraintVariable2 createIndependentTypeVariable(ITypeBinding type) {
- if (type.isArray())
- type= type.getElementType();
- if (isConstrainedType(type))
- return fConstraintVariables.addExisting(new IndependentTypeVariable2(createTType(type)));
- return null;
- }
- /**
- * Creates a new method parameter variable.
- *
- * @param method the method binding
- * @param index the index of the parameter
- * @return the created method parameter variable
- */
- public final ConstraintVariable2 createMethodParameterVariable(final IMethodBinding method, final int index) {
- final ITypeBinding[] parameters= method.getParameterTypes();
- if (parameters.length < 1)
- return null;
- ITypeBinding binding= parameters[Math.min(index, parameters.length - 1)];
- if (binding.isArray())
- binding= binding.getElementType();
- if (isConstrainedType(binding)) {
- ConstraintVariable2 variable= null;
- final TType type= createTType(binding);
- if (method.getDeclaringClass().isFromSource())
- variable= new ParameterTypeVariable2(type, index, method.getMethodDeclaration());
- else
- variable= new ImmutableTypeVariable2(type);
- return fConstraintVariables.addExisting(variable);
- }
- return null;
- }
- /**
- * Creates a new return type variable.
- *
- * @param method the method binding
- * @return the created return type variable
- */
- public final ConstraintVariable2 createReturnTypeVariable(final IMethodBinding method) {
- if (!method.isConstructor()) {
- ITypeBinding binding= method.getReturnType();
- if (binding != null && binding.isArray())
- binding= binding.getElementType();
- if (binding != null && isConstrainedType(binding)) {
- ConstraintVariable2 variable= null;
- final TType type= createTType(binding);
- if (method.getDeclaringClass().isFromSource())
- variable= new ReturnTypeVariable2(type, method);
- else
- variable= new ImmutableTypeVariable2(type);
- return fConstraintVariables.addExisting(variable);
- }
- }
- return null;
- }
- /**
- * Creates a subtype constraint.
- *
- * @param descendant the descendant type constraint variable
- * @param ancestor the ancestor type constraint variable
- */
- public final void createSubtypeConstraint(final ConstraintVariable2 descendant, final ConstraintVariable2 ancestor) {
- final ITypeConstraint2 constraint= new SubTypeConstraint2(descendant, ancestor);
- if (!fTypeConstraints.contains(constraint)) {
- fTypeConstraints.add(constraint);
- setVariableUsage(descendant, constraint);
- setVariableUsage(ancestor, constraint);
- }
- }
- /**
- * Creates a new TType for the corresponding binding.
- *
- * @param binding The type binding
- * @return The corresponding TType
- */
- public final TType createTType(final ITypeBinding binding) {
- final String key= binding.getKey();
- final TType cached= fTTypeCache.get(key);
- if (cached != null)
- return cached;
- final TType type= fEnvironment.create(binding);
- fTTypeCache.put(key, type);
- return type;
- }
- /**
- * Creates a type variable.
- *
- * @param type the type binding
- * @param range the compilation unit range
- * @return the created type variable
- */
- public final ConstraintVariable2 createTypeVariable(ITypeBinding type, final CompilationUnitRange range) {
- if (type.isArray())
- type= type.getElementType();
- if (isConstrainedType(type))
- return fConstraintVariables.addExisting(new TypeVariable2(createTType(type), range));
- return null;
- }
- /**
- * Creates a type variable.
- *
- * @param type the type
- * @return the created type variable
- */
- public final ConstraintVariable2 createTypeVariable(final Type type) {
- ITypeBinding binding= type.resolveBinding();
- if (binding != null) {
- if (binding.isArray())
- binding= binding.getElementType();
- if (isConstrainedType(binding))
- return fConstraintVariables.addExisting(new TypeVariable2(createTType(binding), new CompilationUnitRange(RefactoringASTParser.getCompilationUnit(type), type)));
- }
- return null;
- }
- /**
- * Creates a variable type variable.
- *
- * @param binding the variable binding
- * @return the created variable variable
- */
- public final ConstraintVariable2 createVariableVariable(final IVariableBinding binding) {
- ITypeBinding type= binding.getType();
- if (type.isArray())
- type= type.getElementType();
- if (isConstrainedType(type)) {
- ConstraintVariable2 variable= null;
- final IVariableBinding declaration= binding.getVariableDeclaration();
- if (declaration.isField()) {
- final ITypeBinding declaring= declaration.getDeclaringClass();
- if (!declaring.isFromSource())
- variable= new ImmutableTypeVariable2(createTType(type));
- } else {
- final IMethodBinding declaring= declaration.getDeclaringMethod();
- if (declaring != null && !declaring.getDeclaringClass().isFromSource())
- variable= new ImmutableTypeVariable2(createTType(type));
- }
- if (variable == null)
- variable= new VariableVariable2(createTType(type), declaration);
- return fConstraintVariables.addExisting(variable);
- }
- return null;
- }
- /**
- * Gets called when the creation of the model ends.
- */
- public final void endCreation() {
- fEnvironment= null;
- fTTypeCache= null;
- }
- /**
- * Returns the cast variables of this model.
- *
- * @return the cast variables (element type: <code>CastVariable2</code>)
- */
- public final Collection<CastVariable2> getCastVariables() {
- return Collections.unmodifiableCollection(fCastVariables);
- }
- /**
- * Returns the compliance level to use.
- *
- * @return the compliance level
- */
- public final int getCompliance() {
- return fCompliance;
- }
- /**
- * Returns the constraint variables of this model.
- *
- * @return the constraint variables (element type: <code>ConstraintVariable2</code>)
- */
- public final Collection<ConstraintVariable2> getConstraintVariables() {
- return Collections.unmodifiableCollection(fConstraintVariables);
- }
- /**
- * Returns the subtype to be replaced.
- *
- * @return the subtype to be replaced
- */
- public final TType getSubType() {
- return fSubType;
- }
- /**
- * Returns the supertype as replacement.
- *
- * @return the supertype as replacement
- */
- public final TType getSuperType() {
- return fSuperType;
- }
- /**
- * Returns the type constraints of this model.
- *
- * @return the type constraints (element type: <code>ITypeConstraint2</code>)
- */
- public final Collection<ITypeConstraint2> getTypeConstraints() {
- return Collections.unmodifiableCollection(fTypeConstraints);
- }
- /**
- * Sets the compliance level to use.
- *
- * @param level the compliance level to use. The argument must be one of the <code>AST.JLSx</code> constants.
- */
- public final void setCompliance(final int level) {
- fCompliance= level;
- }
- }