PageRenderTime 42ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/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

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 604 lines | 325 code | 56 blank | 223 comment | 75 complexity | b90c1f26c7e353304cf9779b63c0e526 MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2000, 2011 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. *******************************************************************************/
  11. package org.eclipse.jdt.internal.corext.refactoring.structure.constraints;
  12. import java.util.AbstractSet;
  13. import java.util.ArrayList;
  14. import java.util.Collection;
  15. import java.util.Collections;
  16. import java.util.HashMap;
  17. import java.util.HashSet;
  18. import java.util.Iterator;
  19. import java.util.LinkedHashMap;
  20. import java.util.Map;
  21. import java.util.Set;
  22. import org.eclipse.jdt.core.dom.CastExpression;
  23. import org.eclipse.jdt.core.dom.IMethodBinding;
  24. import org.eclipse.jdt.core.dom.ITypeBinding;
  25. import org.eclipse.jdt.core.dom.IVariableBinding;
  26. import org.eclipse.jdt.core.dom.Name;
  27. import org.eclipse.jdt.core.dom.Type;
  28. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange;
  29. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType;
  30. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TypeEnvironment;
  31. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.CastVariable2;
  32. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ConstraintVariable2;
  33. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraint2;
  34. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ImmutableTypeVariable2;
  35. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.IndependentTypeVariable2;
  36. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ParameterTypeVariable2;
  37. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ReturnTypeVariable2;
  38. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.SubTypeConstraint2;
  39. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeEquivalenceSet;
  40. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeVariable2;
  41. import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.VariableVariable2;
  42. import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
  43. /**
  44. * Type constraints model to hold all type constraints to replace type occurrences by a given supertype.
  45. *
  46. * @since 3.1
  47. */
  48. public final class SuperTypeConstraintsModel {
  49. /** Customized implementation of a hash set
  50. * @param <E> the element type */
  51. private static class HashedSet<E> extends AbstractSet<E> {
  52. /** The backing hash map */
  53. private final Map<E, E> fImplementation= new HashMap<E, E>();
  54. /*
  55. * @see java.util.AbstractCollection#add(java.lang.Object)
  56. */
  57. @Override
  58. public final boolean add(final E object) {
  59. return fImplementation.put(object, object) == null;
  60. }
  61. /**
  62. * Attempts to add the specified object to this set.
  63. *
  64. * @param object the object to add
  65. * @return An already existing object considered equal to the specified one, or the newly added object
  66. */
  67. public final E addExisting(final E object) {
  68. final E result= fImplementation.get(object);
  69. if (result != null)
  70. return result;
  71. fImplementation.put(object, object);
  72. return object;
  73. }
  74. /*
  75. * @see java.util.AbstractCollection#clear()
  76. */
  77. @Override
  78. public final void clear() {
  79. fImplementation.clear();
  80. }
  81. /*
  82. * @see java.util.AbstractCollection#contains(java.lang.Object)
  83. */
  84. @Override
  85. public final boolean contains(final Object object) {
  86. return fImplementation.containsKey(object);
  87. }
  88. /*
  89. * @see java.util.AbstractCollection#isEmpty()
  90. */
  91. @Override
  92. public final boolean isEmpty() {
  93. return fImplementation.isEmpty();
  94. }
  95. /*
  96. * @see java.util.AbstractCollection#iterator()
  97. */
  98. @Override
  99. public final Iterator<E> iterator() {
  100. return fImplementation.keySet().iterator();
  101. }
  102. /*
  103. * @see java.util.AbstractCollection#remove(java.lang.Object)
  104. */
  105. @Override
  106. public final boolean remove(final Object object) {
  107. return fImplementation.remove(object) == object;
  108. }
  109. /*
  110. * @see java.util.AbstractCollection#size()
  111. */
  112. @Override
  113. public final int size() {
  114. return fImplementation.size();
  115. }
  116. }
  117. /** The usage data */
  118. private static final String DATA_USAGE= "us"; //$NON-NLS-1$
  119. /** Maximal number of TTypes */
  120. private static final int MAX_CACHE= 64;
  121. /**
  122. * Returns the usage of the specified constraint variable.
  123. *
  124. * @param variable the constraint variable
  125. * @return the usage of the constraint variable (element type: <code>ITypeConstraint2</code>)
  126. */
  127. public static Collection<ITypeConstraint2> getVariableUsage(final ConstraintVariable2 variable) {
  128. final Object data= variable.getData(DATA_USAGE);
  129. if (data == null) {
  130. return Collections.emptyList();
  131. } else if (data instanceof Collection) {
  132. @SuppressWarnings("unchecked")
  133. Collection<ITypeConstraint2> collection= (Collection<ITypeConstraint2>) data;
  134. return Collections.unmodifiableCollection(collection);
  135. } else {
  136. return Collections.singletonList((ITypeConstraint2) data);
  137. }
  138. }
  139. /**
  140. * Is the type represented by the specified binding a constrained type?
  141. *
  142. * @param binding the binding to check, or <code>null</code>
  143. * @return <code>true</code> if it is constrained, <code>false</code> otherwise
  144. */
  145. public static boolean isConstrainedType(final ITypeBinding binding) {
  146. return binding != null && !binding.isSynthetic() && !binding.isPrimitive();
  147. }
  148. /**
  149. * Sets the usage of the specified constraint variable.
  150. *
  151. * @param variable the constraint variable
  152. * @param constraint the type constraint
  153. */
  154. public static void setVariableUsage(final ConstraintVariable2 variable, ITypeConstraint2 constraint) {
  155. final Object data= variable.getData(DATA_USAGE);
  156. if (data == null) {
  157. variable.setData(DATA_USAGE, constraint);
  158. } else if (data instanceof Collection) {
  159. @SuppressWarnings("unchecked")
  160. Collection<ITypeConstraint2> collection= (Collection<ITypeConstraint2>) data;
  161. collection.add(constraint);
  162. } else {
  163. final Collection<Object> usage= new ArrayList<Object>(2);
  164. usage.add(data);
  165. usage.add(constraint);
  166. variable.setData(DATA_USAGE, usage);
  167. }
  168. }
  169. /** The cast variables (element type: <code>CastVariable2</code>) */
  170. private final Collection<CastVariable2> fCastVariables= new ArrayList<CastVariable2>();
  171. /** The compliance level */
  172. private int fCompliance= 3;
  173. /** The set of constraint variables (element type: <code>ConstraintVariable2</code>) */
  174. private final HashedSet<ConstraintVariable2> fConstraintVariables= new HashedSet<ConstraintVariable2>();
  175. /** The covariant type constraints (element type: <code>CovariantTypeConstraint</code>) */
  176. private final Collection<ITypeConstraint2> fCovariantTypeConstraints= new ArrayList<ITypeConstraint2>();
  177. /** The type environment to use */
  178. private TypeEnvironment fEnvironment;
  179. /** The subtype to replace */
  180. private final TType fSubType;
  181. /** The supertype as replacement */
  182. private final TType fSuperType;
  183. /** The TType cache */
  184. private Map<String, TType> fTTypeCache= new LinkedHashMap<String, TType>(MAX_CACHE, 0.75f, true) {
  185. private static final long serialVersionUID= 1L;
  186. @Override
  187. protected final boolean removeEldestEntry(Map.Entry<String, TType> entry) {
  188. return size() > MAX_CACHE;
  189. }
  190. };
  191. /** The set of type constraints (element type: <code>ITypeConstraint2</code>) */
  192. private final Set<ITypeConstraint2> fTypeConstraints= new HashSet<ITypeConstraint2>();
  193. /**
  194. * Creates a new super type constraints model.
  195. *
  196. * @param environment the type environment
  197. * @param subType the subtype to replace
  198. * @param superType the supertype replacement
  199. */
  200. public SuperTypeConstraintsModel(final TypeEnvironment environment, TType subType, TType superType) {
  201. fEnvironment= environment;
  202. fSubType= subType;
  203. fSuperType= superType;
  204. }
  205. /**
  206. * Gets called when the creation of the model begins.
  207. */
  208. public final void beginCreation() {
  209. // Do nothing right now
  210. }
  211. /**
  212. * Creates a cast variable.
  213. *
  214. * @param expression the cast expression
  215. * @param variable the associated constraint variable
  216. * @return the created cast variable
  217. */
  218. public final ConstraintVariable2 createCastVariable(final CastExpression expression, final ConstraintVariable2 variable) {
  219. ITypeBinding binding= expression.resolveTypeBinding();
  220. if (binding.isArray())
  221. binding= binding.getElementType();
  222. if (isConstrainedType(binding)) {
  223. final CastVariable2 result= new CastVariable2(createTType(binding), new CompilationUnitRange(RefactoringASTParser.getCompilationUnit(expression), expression), variable);
  224. fCastVariables.add(result);
  225. return result;
  226. }
  227. return null;
  228. }
  229. /**
  230. * Creates a conditional type constraint.
  231. *
  232. * @param expressionVariable the expression type constraint variable
  233. * @param thenVariable the then type constraint variable
  234. * @param elseVariable the else type constraint variable
  235. */
  236. public final void createConditionalTypeConstraint(final ConstraintVariable2 expressionVariable, final ConstraintVariable2 thenVariable, final ConstraintVariable2 elseVariable) {
  237. final ITypeConstraint2 constraint= new ConditionalTypeConstraint(expressionVariable, thenVariable, elseVariable);
  238. if (!fTypeConstraints.contains(constraint)) {
  239. fTypeConstraints.add(constraint);
  240. setVariableUsage(expressionVariable, constraint);
  241. setVariableUsage(thenVariable, constraint);
  242. setVariableUsage(elseVariable, constraint);
  243. }
  244. }
  245. /**
  246. * Creates a subtype constraint.
  247. *
  248. * @param descendant the descendant type constraint variable
  249. * @param ancestor the ancestor type constraint variable
  250. */
  251. public final void createCovariantTypeConstraint(final ConstraintVariable2 descendant, final ConstraintVariable2 ancestor) {
  252. final ITypeConstraint2 constraint= new CovariantTypeConstraint(descendant, ancestor);
  253. if (!fTypeConstraints.contains(constraint)) {
  254. fTypeConstraints.add(constraint);
  255. fCovariantTypeConstraints.add(constraint);
  256. setVariableUsage(descendant, constraint);
  257. setVariableUsage(ancestor, constraint);
  258. }
  259. }
  260. /**
  261. * Creates a declaring type variable.
  262. * <p>
  263. * A declaring type variable stands for a type where something has been declared.
  264. * </p>
  265. *
  266. * @param type the type binding
  267. * @return the created declaring type variable
  268. */
  269. public final ConstraintVariable2 createDeclaringTypeVariable(ITypeBinding type) {
  270. if (type.isArray())
  271. type= type.getElementType();
  272. type= type.getTypeDeclaration();
  273. return fConstraintVariables.addExisting(new ImmutableTypeVariable2(createTType(type)));
  274. }
  275. /**
  276. * Creates an equality constraint.
  277. *
  278. * @param left the left typeconstraint variable
  279. * @param right the right typeconstraint variable
  280. */
  281. public final void createEqualityConstraint(final ConstraintVariable2 left, final ConstraintVariable2 right) {
  282. if (left != null && right != null) {
  283. final TypeEquivalenceSet first= left.getTypeEquivalenceSet();
  284. final TypeEquivalenceSet second= right.getTypeEquivalenceSet();
  285. if (first == null) {
  286. if (second == null) {
  287. final TypeEquivalenceSet set= new TypeEquivalenceSet(left, right);
  288. left.setTypeEquivalenceSet(set);
  289. right.setTypeEquivalenceSet(set);
  290. } else {
  291. second.add(left);
  292. left.setTypeEquivalenceSet(second);
  293. }
  294. } else {
  295. if (second == null) {
  296. first.add(right);
  297. right.setTypeEquivalenceSet(first);
  298. } else if (first == second)
  299. return;
  300. else {
  301. final ConstraintVariable2[] variables= second.getContributingVariables();
  302. first.addAll(variables);
  303. for (int index= 0; index < variables.length; index++)
  304. variables[index].setTypeEquivalenceSet(first);
  305. }
  306. }
  307. }
  308. }
  309. /**
  310. * Creates an exception variable.
  311. *
  312. * @param name the name of the thrown exception
  313. * @return the created exception variable
  314. */
  315. public final ConstraintVariable2 createExceptionVariable(final Name name) {
  316. final ITypeBinding binding= name.resolveTypeBinding();
  317. if (isConstrainedType(binding))
  318. return fConstraintVariables.addExisting(new TypeVariable2(createTType(binding), new CompilationUnitRange(RefactoringASTParser.getCompilationUnit(name), name)));
  319. return null;
  320. }
  321. /**
  322. * Creates an immutable type variable.
  323. *
  324. * @param type the type binding
  325. * @return the created plain type variable
  326. */
  327. public final ConstraintVariable2 createImmutableTypeVariable(ITypeBinding type) {
  328. if (type.isArray())
  329. type= type.getElementType();
  330. if (isConstrainedType(type))
  331. return fConstraintVariables.addExisting(new ImmutableTypeVariable2(createTType(type)));
  332. return null;
  333. }
  334. /**
  335. * Creates an independent type variable.
  336. * <p>
  337. * An independant type variable stands for an arbitrary type.
  338. * </p>
  339. *
  340. * @param type the type binding
  341. * @return the created independant type variable
  342. */
  343. public final ConstraintVariable2 createIndependentTypeVariable(ITypeBinding type) {
  344. if (type.isArray())
  345. type= type.getElementType();
  346. if (isConstrainedType(type))
  347. return fConstraintVariables.addExisting(new IndependentTypeVariable2(createTType(type)));
  348. return null;
  349. }
  350. /**
  351. * Creates a new method parameter variable.
  352. *
  353. * @param method the method binding
  354. * @param index the index of the parameter
  355. * @return the created method parameter variable
  356. */
  357. public final ConstraintVariable2 createMethodParameterVariable(final IMethodBinding method, final int index) {
  358. final ITypeBinding[] parameters= method.getParameterTypes();
  359. if (parameters.length < 1)
  360. return null;
  361. ITypeBinding binding= parameters[Math.min(index, parameters.length - 1)];
  362. if (binding.isArray())
  363. binding= binding.getElementType();
  364. if (isConstrainedType(binding)) {
  365. ConstraintVariable2 variable= null;
  366. final TType type= createTType(binding);
  367. if (method.getDeclaringClass().isFromSource())
  368. variable= new ParameterTypeVariable2(type, index, method.getMethodDeclaration());
  369. else
  370. variable= new ImmutableTypeVariable2(type);
  371. return fConstraintVariables.addExisting(variable);
  372. }
  373. return null;
  374. }
  375. /**
  376. * Creates a new return type variable.
  377. *
  378. * @param method the method binding
  379. * @return the created return type variable
  380. */
  381. public final ConstraintVariable2 createReturnTypeVariable(final IMethodBinding method) {
  382. if (!method.isConstructor()) {
  383. ITypeBinding binding= method.getReturnType();
  384. if (binding != null && binding.isArray())
  385. binding= binding.getElementType();
  386. if (binding != null && isConstrainedType(binding)) {
  387. ConstraintVariable2 variable= null;
  388. final TType type= createTType(binding);
  389. if (method.getDeclaringClass().isFromSource())
  390. variable= new ReturnTypeVariable2(type, method);
  391. else
  392. variable= new ImmutableTypeVariable2(type);
  393. return fConstraintVariables.addExisting(variable);
  394. }
  395. }
  396. return null;
  397. }
  398. /**
  399. * Creates a subtype constraint.
  400. *
  401. * @param descendant the descendant type constraint variable
  402. * @param ancestor the ancestor type constraint variable
  403. */
  404. public final void createSubtypeConstraint(final ConstraintVariable2 descendant, final ConstraintVariable2 ancestor) {
  405. final ITypeConstraint2 constraint= new SubTypeConstraint2(descendant, ancestor);
  406. if (!fTypeConstraints.contains(constraint)) {
  407. fTypeConstraints.add(constraint);
  408. setVariableUsage(descendant, constraint);
  409. setVariableUsage(ancestor, constraint);
  410. }
  411. }
  412. /**
  413. * Creates a new TType for the corresponding binding.
  414. *
  415. * @param binding The type binding
  416. * @return The corresponding TType
  417. */
  418. public final TType createTType(final ITypeBinding binding) {
  419. final String key= binding.getKey();
  420. final TType cached= fTTypeCache.get(key);
  421. if (cached != null)
  422. return cached;
  423. final TType type= fEnvironment.create(binding);
  424. fTTypeCache.put(key, type);
  425. return type;
  426. }
  427. /**
  428. * Creates a type variable.
  429. *
  430. * @param type the type binding
  431. * @param range the compilation unit range
  432. * @return the created type variable
  433. */
  434. public final ConstraintVariable2 createTypeVariable(ITypeBinding type, final CompilationUnitRange range) {
  435. if (type.isArray())
  436. type= type.getElementType();
  437. if (isConstrainedType(type))
  438. return fConstraintVariables.addExisting(new TypeVariable2(createTType(type), range));
  439. return null;
  440. }
  441. /**
  442. * Creates a type variable.
  443. *
  444. * @param type the type
  445. * @return the created type variable
  446. */
  447. public final ConstraintVariable2 createTypeVariable(final Type type) {
  448. ITypeBinding binding= type.resolveBinding();
  449. if (binding != null) {
  450. if (binding.isArray())
  451. binding= binding.getElementType();
  452. if (isConstrainedType(binding))
  453. return fConstraintVariables.addExisting(new TypeVariable2(createTType(binding), new CompilationUnitRange(RefactoringASTParser.getCompilationUnit(type), type)));
  454. }
  455. return null;
  456. }
  457. /**
  458. * Creates a variable type variable.
  459. *
  460. * @param binding the variable binding
  461. * @return the created variable variable
  462. */
  463. public final ConstraintVariable2 createVariableVariable(final IVariableBinding binding) {
  464. ITypeBinding type= binding.getType();
  465. if (type.isArray())
  466. type= type.getElementType();
  467. if (isConstrainedType(type)) {
  468. ConstraintVariable2 variable= null;
  469. final IVariableBinding declaration= binding.getVariableDeclaration();
  470. if (declaration.isField()) {
  471. final ITypeBinding declaring= declaration.getDeclaringClass();
  472. if (!declaring.isFromSource())
  473. variable= new ImmutableTypeVariable2(createTType(type));
  474. } else {
  475. final IMethodBinding declaring= declaration.getDeclaringMethod();
  476. if (declaring != null && !declaring.getDeclaringClass().isFromSource())
  477. variable= new ImmutableTypeVariable2(createTType(type));
  478. }
  479. if (variable == null)
  480. variable= new VariableVariable2(createTType(type), declaration);
  481. return fConstraintVariables.addExisting(variable);
  482. }
  483. return null;
  484. }
  485. /**
  486. * Gets called when the creation of the model ends.
  487. */
  488. public final void endCreation() {
  489. fEnvironment= null;
  490. fTTypeCache= null;
  491. }
  492. /**
  493. * Returns the cast variables of this model.
  494. *
  495. * @return the cast variables (element type: <code>CastVariable2</code>)
  496. */
  497. public final Collection<CastVariable2> getCastVariables() {
  498. return Collections.unmodifiableCollection(fCastVariables);
  499. }
  500. /**
  501. * Returns the compliance level to use.
  502. *
  503. * @return the compliance level
  504. */
  505. public final int getCompliance() {
  506. return fCompliance;
  507. }
  508. /**
  509. * Returns the constraint variables of this model.
  510. *
  511. * @return the constraint variables (element type: <code>ConstraintVariable2</code>)
  512. */
  513. public final Collection<ConstraintVariable2> getConstraintVariables() {
  514. return Collections.unmodifiableCollection(fConstraintVariables);
  515. }
  516. /**
  517. * Returns the subtype to be replaced.
  518. *
  519. * @return the subtype to be replaced
  520. */
  521. public final TType getSubType() {
  522. return fSubType;
  523. }
  524. /**
  525. * Returns the supertype as replacement.
  526. *
  527. * @return the supertype as replacement
  528. */
  529. public final TType getSuperType() {
  530. return fSuperType;
  531. }
  532. /**
  533. * Returns the type constraints of this model.
  534. *
  535. * @return the type constraints (element type: <code>ITypeConstraint2</code>)
  536. */
  537. public final Collection<ITypeConstraint2> getTypeConstraints() {
  538. return Collections.unmodifiableCollection(fTypeConstraints);
  539. }
  540. /**
  541. * Sets the compliance level to use.
  542. *
  543. * @param level the compliance level to use. The argument must be one of the <code>AST.JLSx</code> constants.
  544. */
  545. public final void setCompliance(final int level) {
  546. fCompliance= level;
  547. }
  548. }