1 11 package org.eclipse.jdt.internal.corext.refactoring.structure.constraints; 12 13 import java.util.AbstractSet ; 14 import java.util.ArrayList ; 15 import java.util.Collection ; 16 import java.util.Collections ; 17 import java.util.HashMap ; 18 import java.util.HashSet ; 19 import java.util.Iterator ; 20 import java.util.LinkedHashMap ; 21 import java.util.Map ; 22 import java.util.Set ; 23 24 import org.eclipse.jdt.core.dom.CastExpression; 25 import org.eclipse.jdt.core.dom.IMethodBinding; 26 import org.eclipse.jdt.core.dom.ITypeBinding; 27 import org.eclipse.jdt.core.dom.IVariableBinding; 28 import org.eclipse.jdt.core.dom.Name; 29 import org.eclipse.jdt.core.dom.Type; 30 31 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange; 32 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType; 33 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TypeEnvironment; 34 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.CastVariable2; 35 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ConstraintVariable2; 36 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraint2; 37 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ImmutableTypeVariable2; 38 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.IndependentTypeVariable2; 39 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ParameterTypeVariable2; 40 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ReturnTypeVariable2; 41 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.SubTypeConstraint2; 42 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeEquivalenceSet; 43 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeVariable2; 44 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.VariableVariable2; 45 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 46 47 52 public final class SuperTypeConstraintsModel { 53 54 55 private static class HashedSet extends AbstractSet implements Set { 56 57 58 private final Map fImplementation= new HashMap (); 59 60 63 public final boolean add(final Object object) { 64 return fImplementation.put(object, object) == null; 65 } 66 67 73 public final Object addExisting(final Object object) { 74 final Object result= fImplementation.get(object); 75 if (result != null) 76 return result; 77 fImplementation.put(object, object); 78 return object; 79 } 80 81 84 public final void clear() { 85 fImplementation.clear(); 86 } 87 88 91 public final boolean contains(final Object object) { 92 return fImplementation.containsKey(object); 93 } 94 95 98 public final boolean isEmpty() { 99 return fImplementation.isEmpty(); 100 } 101 102 105 public final Iterator iterator() { 106 return fImplementation.keySet().iterator(); 107 } 108 109 112 public final boolean remove(final Object object) { 113 return fImplementation.remove(object) == object; 114 } 115 116 119 public final int size() { 120 return fImplementation.size(); 121 } 122 } 123 124 125 private static final String DATA_USAGE= "us"; 127 128 private static final int MAX_CACHE= 64; 129 130 136 public static Collection getVariableUsage(final ConstraintVariable2 variable) { 137 final Object data= variable.getData(DATA_USAGE); 138 if (data == null) 139 return Collections.EMPTY_LIST; 140 else if (data instanceof Collection ) 141 return Collections.unmodifiableCollection((Collection ) data); 142 else 143 return Collections.singletonList(data); 144 } 145 146 152 public static boolean isConstrainedType(final ITypeBinding binding) { 153 return binding != null && !binding.isSynthetic() && !binding.isPrimitive(); 154 } 155 156 162 public static void setVariableUsage(final ConstraintVariable2 variable, ITypeConstraint2 constraint) { 163 final Object data= variable.getData(DATA_USAGE); 164 if (data == null) 165 variable.setData(DATA_USAGE, constraint); 166 else if (data instanceof Collection ) 167 ((Collection ) data).add(constraint); 168 else { 169 final Collection usage= new ArrayList (2); 170 usage.add(data); 171 usage.add(constraint); 172 variable.setData(DATA_USAGE, usage); 173 } 174 } 175 176 177 private final Collection fCastVariables= new ArrayList (); 178 179 180 private int fCompliance= 3; 181 182 183 private final HashedSet fConstraintVariables= new HashedSet(); 184 185 186 private final Collection fCovariantTypeConstraints= new ArrayList (); 187 188 189 private TypeEnvironment fEnvironment; 190 191 192 private final TType fSubType; 193 194 195 private final TType fSuperType; 196 197 198 private Map fTTypeCache= new LinkedHashMap (MAX_CACHE, 0.75f, true) { 199 200 private static final long serialVersionUID= 1L; 201 202 protected final boolean removeEldestEntry(Map.Entry entry) { 203 return size() > MAX_CACHE; 204 } 205 }; 206 207 208 private final Set fTypeConstraints= new HashSet (); 209 210 216 public SuperTypeConstraintsModel(final TypeEnvironment environment, TType subType, TType superType) { 217 fEnvironment= environment; 218 fSubType= subType; 219 fSuperType= superType; 220 } 221 222 225 public final void beginCreation() { 226 } 228 229 236 public final ConstraintVariable2 createCastVariable(final CastExpression expression, final ConstraintVariable2 variable) { 237 ITypeBinding binding= expression.resolveTypeBinding(); 238 if (binding.isArray()) 239 binding= binding.getElementType(); 240 if (isConstrainedType(binding)) { 241 final CastVariable2 result= new CastVariable2(createTType(binding), new CompilationUnitRange(RefactoringASTParser.getCompilationUnit(expression), expression), variable); 242 fCastVariables.add(result); 243 return result; 244 } 245 return null; 246 } 247 248 255 public final void createConditionalTypeConstraint(final ConstraintVariable2 expressionVariable, final ConstraintVariable2 thenVariable, final ConstraintVariable2 elseVariable) { 256 final ITypeConstraint2 constraint= new ConditionalTypeConstraint(expressionVariable, thenVariable, elseVariable); 257 if (!fTypeConstraints.contains(constraint)) { 258 fTypeConstraints.add(constraint); 259 setVariableUsage(expressionVariable, constraint); 260 setVariableUsage(thenVariable, constraint); 261 setVariableUsage(elseVariable, constraint); 262 } 263 } 264 265 271 public final void createCovariantTypeConstraint(final ConstraintVariable2 descendant, final ConstraintVariable2 ancestor) { 272 final ITypeConstraint2 constraint= new CovariantTypeConstraint(descendant, ancestor); 273 if (!fTypeConstraints.contains(constraint)) { 274 fTypeConstraints.add(constraint); 275 fCovariantTypeConstraints.add(constraint); 276 setVariableUsage(descendant, constraint); 277 setVariableUsage(ancestor, constraint); 278 } 279 } 280 281 290 public final ConstraintVariable2 createDeclaringTypeVariable(ITypeBinding type) { 291 if (type.isArray()) 292 type= type.getElementType(); 293 type= type.getTypeDeclaration(); 294 return (ConstraintVariable2) fConstraintVariables.addExisting(new ImmutableTypeVariable2(createTType(type))); 295 } 296 297 303 public final void createEqualityConstraint(final ConstraintVariable2 left, final ConstraintVariable2 right) { 304 if (left != null && right != null) { 305 final TypeEquivalenceSet first= left.getTypeEquivalenceSet(); 306 final TypeEquivalenceSet second= right.getTypeEquivalenceSet(); 307 if (first == null) { 308 if (second == null) { 309 final TypeEquivalenceSet set= new TypeEquivalenceSet(left, right); 310 left.setTypeEquivalenceSet(set); 311 right.setTypeEquivalenceSet(set); 312 } else { 313 second.add(left); 314 left.setTypeEquivalenceSet(second); 315 } 316 } else { 317 if (second == null) { 318 first.add(right); 319 right.setTypeEquivalenceSet(first); 320 } else if (first == second) 321 return; 322 else { 323 final ConstraintVariable2[] variables= second.getContributingVariables(); 324 first.addAll(variables); 325 for (int index= 0; index < variables.length; index++) 326 variables[index].setTypeEquivalenceSet(first); 327 } 328 } 329 } 330 } 331 332 338 public final ConstraintVariable2 createExceptionVariable(final Name name) { 339 final ITypeBinding binding= name.resolveTypeBinding(); 340 if (isConstrainedType(binding)) 341 return (ConstraintVariable2) fConstraintVariables.addExisting(new TypeVariable2(createTType(binding), new CompilationUnitRange(RefactoringASTParser.getCompilationUnit(name), name))); 342 return null; 343 } 344 345 351 public final ConstraintVariable2 createImmutableTypeVariable(ITypeBinding type) { 352 if (type.isArray()) 353 type= type.getElementType(); 354 if (isConstrainedType(type)) 355 return (ConstraintVariable2) fConstraintVariables.addExisting(new ImmutableTypeVariable2(createTType(type))); 356 return null; 357 } 358 359 368 public final ConstraintVariable2 createIndependentTypeVariable(ITypeBinding type) { 369 if (type.isArray()) 370 type= type.getElementType(); 371 if (isConstrainedType(type)) 372 return (ConstraintVariable2) fConstraintVariables.addExisting(new IndependentTypeVariable2(createTType(type))); 373 return null; 374 } 375 376 383 public final ConstraintVariable2 createMethodParameterVariable(final IMethodBinding method, final int index) { 384 final ITypeBinding[] parameters= method.getParameterTypes(); 385 ITypeBinding binding= parameters[Math.min(index, parameters.length - 1)]; 386 if (binding.isArray()) 387 binding= binding.getElementType(); 388 if (isConstrainedType(binding)) { 389 ConstraintVariable2 variable= null; 390 final TType type= createTType(binding); 391 if (method.getDeclaringClass().isFromSource()) 392 variable= new ParameterTypeVariable2(type, index, method.getMethodDeclaration()); 393 else 394 variable= new ImmutableTypeVariable2(type); 395 return (ConstraintVariable2) fConstraintVariables.addExisting(variable); 396 } 397 return null; 398 } 399 400 406 public final ConstraintVariable2 createReturnTypeVariable(final IMethodBinding method) { 407 if (!method.isConstructor()) { 408 ITypeBinding binding= method.getReturnType(); 409 if (binding != null && binding.isArray()) 410 binding= binding.getElementType(); 411 if (binding != null && isConstrainedType(binding)) { 412 ConstraintVariable2 variable= null; 413 final TType type= createTType(binding); 414 if (method.getDeclaringClass().isFromSource()) 415 variable= new ReturnTypeVariable2(type, method); 416 else 417 variable= new ImmutableTypeVariable2(type); 418 return (ConstraintVariable2) fConstraintVariables.addExisting(variable); 419 } 420 } 421 return null; 422 } 423 424 430 public final void createSubtypeConstraint(final ConstraintVariable2 descendant, final ConstraintVariable2 ancestor) { 431 final ITypeConstraint2 constraint= new SubTypeConstraint2(descendant, ancestor); 432 if (!fTypeConstraints.contains(constraint)) { 433 fTypeConstraints.add(constraint); 434 setVariableUsage(descendant, constraint); 435 setVariableUsage(ancestor, constraint); 436 } 437 } 438 439 445 public final TType createTType(final ITypeBinding binding) { 446 final String key= binding.getKey(); 447 final TType cached= (TType) fTTypeCache.get(key); 448 if (cached != null) 449 return cached; 450 final TType type= fEnvironment.create(binding); 451 fTTypeCache.put(key, type); 452 return type; 453 } 454 455 462 public final ConstraintVariable2 createTypeVariable(ITypeBinding type, final CompilationUnitRange range) { 463 if (type.isArray()) 464 type= type.getElementType(); 465 if (isConstrainedType(type)) 466 return (ConstraintVariable2) fConstraintVariables.addExisting(new TypeVariable2(createTType(type), range)); 467 return null; 468 } 469 470 476 public final ConstraintVariable2 createTypeVariable(final Type type) { 477 ITypeBinding binding= type.resolveBinding(); 478 if (binding != null) { 479 if (binding.isArray()) 480 binding= binding.getElementType(); 481 if (isConstrainedType(binding)) 482 return (ConstraintVariable2) fConstraintVariables.addExisting(new TypeVariable2(createTType(binding), new CompilationUnitRange(RefactoringASTParser.getCompilationUnit(type), type))); 483 } 484 return null; 485 } 486 487 493 public final ConstraintVariable2 createVariableVariable(final IVariableBinding binding) { 494 ITypeBinding type= binding.getType(); 495 if (type.isArray()) 496 type= type.getElementType(); 497 if (isConstrainedType(type)) { 498 ConstraintVariable2 variable= null; 499 final IVariableBinding declaration= binding.getVariableDeclaration(); 500 if (declaration.isField()) { 501 final ITypeBinding declaring= declaration.getDeclaringClass(); 502 if (!declaring.isFromSource()) 503 variable= new ImmutableTypeVariable2(createTType(type)); 504 } else { 505 final IMethodBinding declaring= declaration.getDeclaringMethod(); 506 if (declaring != null && !declaring.getDeclaringClass().isFromSource()) 507 variable= new ImmutableTypeVariable2(createTType(type)); 508 } 509 if (variable == null) 510 variable= new VariableVariable2(createTType(type), declaration); 511 return (ConstraintVariable2) fConstraintVariables.addExisting(variable); 512 } 513 return null; 514 } 515 516 519 public final void endCreation() { 520 fEnvironment= null; 521 fTTypeCache= null; 522 } 523 524 529 public final Collection getCastVariables() { 530 return Collections.unmodifiableCollection(fCastVariables); 531 } 532 533 538 public final int getCompliance() { 539 return fCompliance; 540 } 541 542 547 public final Collection getConstraintVariables() { 548 return Collections.unmodifiableCollection(fConstraintVariables); 549 } 550 551 556 public final TType getSubType() { 557 return fSubType; 558 } 559 560 565 public final TType getSuperType() { 566 return fSuperType; 567 } 568 569 574 public final Collection getTypeConstraints() { 575 return Collections.unmodifiableCollection(fTypeConstraints); 576 } 577 578 583 public final void setCompliance(final int level) { 584 fCompliance= level; 585 } 586 } | Popular Tags |