1 11 12 package org.eclipse.jdt.internal.corext.refactoring.generics; 13 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.List ; 22 import java.util.Map ; 23 import java.util.Set ; 24 25 import org.eclipse.core.runtime.Assert; 26 import org.eclipse.core.runtime.Platform; 27 28 import org.eclipse.jdt.core.ICompilationUnit; 29 import org.eclipse.jdt.core.dom.CastExpression; 30 import org.eclipse.jdt.core.dom.Expression; 31 import org.eclipse.jdt.core.dom.IMethodBinding; 32 import org.eclipse.jdt.core.dom.ITypeBinding; 33 import org.eclipse.jdt.core.dom.IVariableBinding; 34 import org.eclipse.jdt.core.dom.Modifier; 35 import org.eclipse.jdt.core.dom.Type; 36 37 import org.eclipse.jdt.internal.corext.dom.Bindings; 38 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CompilationUnitRange; 39 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.ArrayType; 40 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.GenericType; 41 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.ParameterizedType; 42 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType; 43 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TypeEnvironment; 44 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TypeVariable; 45 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ArrayElementVariable2; 46 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ArrayTypeVariable2; 47 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.CastVariable2; 48 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.CollectionElementVariable2; 49 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ConstraintVariable2; 50 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ITypeConstraint2; 51 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ImmutableTypeVariable2; 52 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.IndependentTypeVariable2; 53 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ParameterTypeVariable2; 54 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ParameterizedTypeVariable2; 55 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ReturnTypeVariable2; 56 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.SubTypeConstraint2; 57 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeEquivalenceSet; 58 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeVariable2; 59 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.VariableVariable2; 60 import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; 61 62 63 public class InferTypeArgumentsTCModel { 64 65 protected static final boolean DEBUG= Boolean.valueOf(Platform.getDebugOption("org.eclipse.jdt.ui/debug/TypeConstraints")).booleanValue(); 67 private static final String INDEXED_COLLECTION_ELEMENTS= "IndexedCollectionElements"; private static final String ARRAY_ELEMENT= "ArrayElement"; private static final String USED_IN= "UsedIn"; private static final String METHOD_RECEIVER= "MethodReceiver"; private static final Map EMPTY_COLLECTION_ELEMENT_VARIABLES_MAP= Collections.EMPTY_MAP; 72 73 protected static boolean fStoreToString= DEBUG; 74 75 78 private HashMap fConstraintVariables; 79 82 private HashMap fTypeConstraints; 83 private Collection fCastVariables; 84 85 private HashSet fCuScopedConstraintVariables; 86 87 private TypeEnvironment fTypeEnvironment; 88 89 private static final int MAX_TTYPE_CACHE= 1024; 90 private Map fTTypeCache= new LinkedHashMap (MAX_TTYPE_CACHE, 0.75f, true) { 91 private static final long serialVersionUID= 1L; 92 protected boolean removeEldestEntry(Map.Entry eldest) { 93 return size() > MAX_TTYPE_CACHE; 94 } 95 }; 96 97 98 public InferTypeArgumentsTCModel() { 99 fTypeConstraints= new HashMap (); 100 fConstraintVariables= new LinkedHashMap (); fCastVariables= new ArrayList (); 102 103 fCuScopedConstraintVariables= new HashSet (); 104 105 fTypeEnvironment= new TypeEnvironment(true); 106 } 107 108 117 protected boolean keep(ConstraintVariable2 cv1, ConstraintVariable2 cv2) { 118 if ((cv1 == null || cv2 == null)) 119 return false; 120 121 if (cv1.equals(cv2)) { 122 if (cv1 == cv2) 123 return false; 124 else 125 Assert.isTrue(false); 126 } 127 128 if (cv1 instanceof CollectionElementVariable2 || cv2 instanceof CollectionElementVariable2) 129 return true; 130 131 if (cv1 instanceof IndependentTypeVariable2 || cv2 instanceof IndependentTypeVariable2) 132 return true; 133 134 if (isAGenericType(cv1.getType())) 135 return true; 136 137 if (isAGenericType(cv2.getType())) 138 return true; 139 140 return false; 141 } 142 143 147 public List getUsedIn(ConstraintVariable2 cv) { 148 Object usedIn= cv.getData(USED_IN); 149 if (usedIn == null) 150 return Collections.EMPTY_LIST; 151 else if (usedIn instanceof ArrayList ) 152 return Collections.unmodifiableList((ArrayList ) usedIn); 153 else 154 return Collections.singletonList(usedIn); 155 } 156 157 public void newCu() { 158 pruneUnusedCuScopedCvs(); 159 fCuScopedConstraintVariables.clear(); 160 fTTypeCache.clear(); 161 } 162 163 private void pruneUnusedCuScopedCvs() { 164 for (Iterator iter= fCuScopedConstraintVariables.iterator(); iter.hasNext();) { 165 ConstraintVariable2 cv= (ConstraintVariable2) iter.next(); 166 pruneCvIfUnused(cv); 167 } 168 } 169 170 private boolean pruneCvIfUnused(ConstraintVariable2 cv) { 171 if (getUsedIn(cv).size() != 0) 172 return false; 173 174 if (cv.getTypeEquivalenceSet() != null) { 175 if (cv.getTypeEquivalenceSet().getContributingVariables().length > 0) 176 return false; 177 } 178 179 ArrayElementVariable2 arrayElementVariable= getArrayElementVariable(cv); 180 if (arrayElementVariable != null && ! pruneCvIfUnused(arrayElementVariable)) 181 return false; 182 183 Map elementVariables= getElementVariables(cv); 184 for (Iterator iter= elementVariables.values().iterator(); iter.hasNext();) { 185 CollectionElementVariable2 elementVariable= (CollectionElementVariable2) iter.next(); 186 if (! pruneCvIfUnused(elementVariable)) 187 return false; 188 } 189 190 fConstraintVariables.remove(cv); 191 return true; 192 } 193 194 public ConstraintVariable2[] getAllConstraintVariables() { 195 ConstraintVariable2[] result= new ConstraintVariable2[fConstraintVariables.size()]; 196 int i= 0; 197 for (Iterator iter= fConstraintVariables.keySet().iterator(); iter.hasNext(); i++) 198 result[i]= (ConstraintVariable2) iter.next(); 199 return result; 200 } 201 202 public ITypeConstraint2[] getAllTypeConstraints() { 203 Set typeConstraints= fTypeConstraints.keySet(); 204 return (ITypeConstraint2[]) typeConstraints.toArray(new ITypeConstraint2[typeConstraints.size()]); 205 } 206 207 public CastVariable2[] getCastVariables() { 208 return (CastVariable2[]) fCastVariables.toArray(new CastVariable2[fCastVariables.size()]); 209 } 210 211 217 public static void setStoreToString(boolean store) { 218 fStoreToString= store; 219 } 220 221 public void createSubtypeConstraint(ConstraintVariable2 cv1, ConstraintVariable2 cv2) { 222 if (! keep(cv1, cv2)) 223 return; 224 225 ConstraintVariable2 storedCv1= storedCv(cv1); 226 ConstraintVariable2 storedCv2= storedCv(cv2); 227 ITypeConstraint2 typeConstraint= new SubTypeConstraint2(storedCv1, storedCv2); 228 229 Object storedTc= fTypeConstraints.get(typeConstraint); 230 if (storedTc == null) { 231 fTypeConstraints.put(typeConstraint, typeConstraint); 232 } else { 233 typeConstraint= (ITypeConstraint2) storedTc; 234 } 235 236 registerCvWithTc(storedCv1, typeConstraint); 237 registerCvWithTc(storedCv2, typeConstraint); 238 } 239 240 private ConstraintVariable2 storedCv(ConstraintVariable2 cv) { 241 Object stored= fConstraintVariables.get(cv); 242 if (stored == null) { 243 fConstraintVariables.put(cv, cv); 244 return cv; 245 } else { 246 return (ConstraintVariable2) stored; 247 } 248 } 249 250 private void registerCvWithTc(ConstraintVariable2 storedCv, ITypeConstraint2 typeConstraint) { 251 Object usedIn= storedCv.getData(USED_IN); 252 if (usedIn == null) { 253 storedCv.setData(USED_IN, typeConstraint); 254 } else if (usedIn instanceof ArrayList ) { 255 ArrayList usedInList= (ArrayList ) usedIn; 256 usedInList.add(typeConstraint); 257 } else { 258 ArrayList usedInList= new ArrayList (2); 259 usedInList.add(usedIn); 260 usedInList.add(typeConstraint); 261 storedCv.setData(USED_IN, usedInList); 262 } 263 } 264 265 public void createEqualsConstraint(ConstraintVariable2 leftElement, ConstraintVariable2 rightElement) { 266 if (leftElement == null || rightElement == null) 267 return; 268 269 TypeEquivalenceSet leftSet= leftElement.getTypeEquivalenceSet(); 270 TypeEquivalenceSet rightSet= rightElement.getTypeEquivalenceSet(); 271 if (leftSet == null) { 272 if (rightSet == null) { 273 TypeEquivalenceSet set= new TypeEquivalenceSet(leftElement, rightElement); 274 leftElement.setTypeEquivalenceSet(set); 275 rightElement.setTypeEquivalenceSet(set); 276 } else { 277 rightSet.add(leftElement); 278 leftElement.setTypeEquivalenceSet(rightSet); 279 } 280 } else { 281 if (rightSet == null) { 282 leftSet.add(rightElement); 283 rightElement.setTypeEquivalenceSet(leftSet); 284 } else if (leftSet == rightSet) { 285 return; 286 } else { 287 ConstraintVariable2[] cvs= rightSet.getContributingVariables(); 288 leftSet.addAll(cvs); 289 for (int i= 0; i < cvs.length; i++) 290 cvs[i].setTypeEquivalenceSet(leftSet); 291 } 292 } 293 } 294 295 public TType createTType(ITypeBinding typeBinding) { 296 String key= typeBinding.getKey(); 297 TType cached= (TType) fTTypeCache.get(key); 298 if (cached != null) 299 return cached; 300 TType type= fTypeEnvironment.create(typeBinding); 301 fTTypeCache.put(key, type); 302 return type; 303 } 304 305 private TType getBoxedType(ITypeBinding typeBinding, Expression expression) { 306 if (typeBinding == null) 307 return null; 308 309 if (! typeBinding.isPrimitive()) 310 return createTType(typeBinding); 311 312 if (expression == null || ! expression.resolveBoxing()) 313 return null; 314 315 String primitiveName= typeBinding.getName(); 316 ITypeBinding boxed= expression.getAST().resolveWellKnownType(getBoxedTypeName(primitiveName)); 317 return createTType(boxed); 318 } 319 320 private String getBoxedTypeName(String primitiveName) { 321 if ("long".equals(primitiveName)) return "java.lang.Long"; 324 else if ("int".equals(primitiveName)) return "java.lang.Integer"; 327 else if ("short".equals(primitiveName)) return "java.lang.Short"; 330 else if ("char".equals(primitiveName)) return "java.lang.Character"; 333 else if ("byte".equals(primitiveName)) return "java.lang.Byte"; 336 else if ("boolean".equals(primitiveName)) return "java.lang.Boolean"; 339 else if ("float".equals(primitiveName)) return "java.lang.Float"; 342 else if ("double".equals(primitiveName)) return "java.lang.Double"; 345 else 346 return null; 347 } 348 349 public VariableVariable2 makeVariableVariable(IVariableBinding variableBinding) { 350 if (variableBinding == null) 351 return null; 352 TType type= getBoxedType(variableBinding.getType(), null); 353 if (type == null) 354 return null; 355 VariableVariable2 cv= new VariableVariable2(type, variableBinding); 356 VariableVariable2 storedCv= (VariableVariable2) storedCv(cv); 357 if (storedCv == cv) { 358 if (! variableBinding.isField() || Modifier.isPrivate(variableBinding.getModifiers())) 359 fCuScopedConstraintVariables.add(storedCv); 360 makeElementVariables(storedCv, type); 361 makeArrayElementVariable(storedCv); 362 if (fStoreToString) 363 storedCv.setData(ConstraintVariable2.TO_STRING, '[' + variableBinding.getName() + ']'); 364 } 365 return storedCv; 366 } 367 368 public VariableVariable2 makeDeclaredVariableVariable(IVariableBinding variableBinding, ICompilationUnit cu) { 369 VariableVariable2 cv= makeVariableVariable(variableBinding); 370 if (cv == null) 371 return null; 372 cv.setCompilationUnit(cu); 373 return cv; 374 } 375 376 public TypeVariable2 makeTypeVariable(Type type) { 377 ICompilationUnit cu= RefactoringASTParser.getCompilationUnit(type); 378 TType ttype= getBoxedType(type.resolveBinding(), null); 379 if (ttype == null) 380 return null; 381 382 CompilationUnitRange range= new CompilationUnitRange(cu, type); 383 TypeVariable2 typeVariable= new TypeVariable2(ttype, range); 384 TypeVariable2 storedCv= (TypeVariable2) storedCv(typeVariable); 385 if (storedCv == typeVariable) { 386 fCuScopedConstraintVariables.add(storedCv); 387 if (isAGenericType(ttype)) 388 makeElementVariables(storedCv, ttype); 389 makeArrayElementVariable(storedCv); 390 if (fStoreToString) 391 storedCv.setData(ConstraintVariable2.TO_STRING, type.toString()); 392 } 393 return storedCv; 394 } 395 396 public IndependentTypeVariable2 makeIndependentTypeVariable(TypeVariable type) { 397 IndependentTypeVariable2 cv= new IndependentTypeVariable2(type); 398 IndependentTypeVariable2 storedCv= (IndependentTypeVariable2) storedCv(cv); 399 if (cv == storedCv) { 400 fCuScopedConstraintVariables.add(storedCv); 401 if (fStoreToString) 404 storedCv.setData(ConstraintVariable2.TO_STRING, "IndependentType(" + type.getPrettySignature() + ")"); } 406 return storedCv; 407 } 408 409 public ParameterizedTypeVariable2 makeParameterizedTypeVariable(ITypeBinding typeBinding) { 410 if (typeBinding == null) 411 return null; 412 TType type= createTType(typeBinding); 413 return makeParameterizedTypeVariable(type); 414 } 415 416 private ParameterizedTypeVariable2 makeParameterizedTypeVariable(TType type) { 417 Assert.isTrue(isAGenericType(type)); 418 419 ParameterizedTypeVariable2 cv= new ParameterizedTypeVariable2(type); 420 ParameterizedTypeVariable2 storedCv= (ParameterizedTypeVariable2) storedCv(cv); 421 if (cv == storedCv) { 422 fCuScopedConstraintVariables.add(storedCv); 423 makeElementVariables(storedCv, type); 424 if (fStoreToString) 425 storedCv.setData(ConstraintVariable2.TO_STRING, "ParameterizedType(" + type.getPrettySignature() + ")"); } 427 return storedCv; 428 } 429 430 public ArrayTypeVariable2 makeArrayTypeVariable(ITypeBinding typeBinding) { 431 if (typeBinding == null) 432 return null; 433 TType type= createTType(typeBinding); 434 return makeArrayTypeVariable((ArrayType) type); 435 } 436 437 private ArrayTypeVariable2 makeArrayTypeVariable(ArrayType type) { 438 ArrayTypeVariable2 cv= new ArrayTypeVariable2(type); 439 ArrayTypeVariable2 storedCv= (ArrayTypeVariable2) storedCv(cv); 440 if (cv == storedCv) { 441 fCuScopedConstraintVariables.add(storedCv); 442 makeArrayElementVariable(storedCv); 443 if (fStoreToString) 444 storedCv.setData(ConstraintVariable2.TO_STRING, "ArrayType(" + type.getPrettySignature() + ")"); } 446 return storedCv; 447 } 448 449 public ParameterTypeVariable2 makeParameterTypeVariable(IMethodBinding methodBinding, int parameterIndex) { 450 if (methodBinding == null) 451 return null; 452 TType type= getBoxedType(methodBinding.getParameterTypes() [parameterIndex], null); 453 if (type == null) 454 return null; 455 456 ParameterTypeVariable2 cv= new ParameterTypeVariable2(type, parameterIndex, methodBinding); 457 ParameterTypeVariable2 storedCv= (ParameterTypeVariable2) storedCv(cv); 458 if (storedCv == cv) { 459 if (methodBinding.getDeclaringClass().isLocal() || Modifier.isPrivate(methodBinding.getModifiers())) 460 fCuScopedConstraintVariables.add(cv); 461 makeElementVariables(storedCv, type); 462 makeArrayElementVariable(storedCv); 463 if (fStoreToString) 464 storedCv.setData(ConstraintVariable2.TO_STRING, "[Parameter(" + parameterIndex + "," + Bindings.asString(methodBinding) + ")]"); } 466 return storedCv; 467 } 468 469 477 public ParameterTypeVariable2 makeDeclaredParameterTypeVariable(IMethodBinding methodBinding, int parameterIndex, ICompilationUnit cu) { 478 if (methodBinding == null) 479 return null; 480 ParameterTypeVariable2 cv= makeParameterTypeVariable(methodBinding, parameterIndex); 481 if (cv == null) 482 return null; 483 cv.setCompilationUnit(cu); 484 return cv; 485 } 486 487 public ReturnTypeVariable2 makeReturnTypeVariable(IMethodBinding methodBinding) { 488 if (methodBinding == null) 489 return null; 490 TType returnType= getBoxedType(methodBinding.getReturnType(), null); 491 if (returnType == null) 492 return null; 493 494 ReturnTypeVariable2 cv= new ReturnTypeVariable2(returnType, methodBinding); 495 ReturnTypeVariable2 storedCv= (ReturnTypeVariable2) storedCv(cv); 496 if (cv == storedCv) { 497 makeElementVariables(storedCv, returnType); 498 makeArrayElementVariable(storedCv); 499 if (fStoreToString) 500 storedCv.setData(ConstraintVariable2.TO_STRING, "[ReturnType(" + Bindings.asString(methodBinding) + ")]"); } 502 return storedCv; 503 } 504 505 public ReturnTypeVariable2 makeDeclaredReturnTypeVariable(IMethodBinding methodBinding, ICompilationUnit cu) { 506 if (methodBinding == null) 507 return null; 508 ReturnTypeVariable2 cv= makeReturnTypeVariable(methodBinding); 509 if (cv == null) 510 return null; 511 512 cv.setCompilationUnit(cu); 513 if (methodBinding.getDeclaringClass().isLocal()) 514 fCuScopedConstraintVariables.add(cv); 515 return cv; 516 } 517 518 public ImmutableTypeVariable2 makeImmutableTypeVariable(ITypeBinding typeBinding, Expression expression) { 519 TType type= getBoxedType(typeBinding, expression); 521 if (type == null) 522 return null; 523 return makeImmutableTypeVariable(type); 524 } 525 526 public ImmutableTypeVariable2 makeImmutableTypeVariable(TType type) { 527 ImmutableTypeVariable2 cv= new ImmutableTypeVariable2(type); 528 ImmutableTypeVariable2 storedCv= (ImmutableTypeVariable2) storedCv(cv); 529 if (cv == storedCv) { 530 makeFixedElementVariables(storedCv, type); 531 makeArrayElementVariable(storedCv); 532 } 533 return storedCv; 534 } 535 536 public static boolean isAGenericType(TType type) { 537 return type.isGenericType() 538 || type.isParameterizedType() 539 || (type.isRawType() && type.getTypeDeclaration().isGenericType()); 540 } 541 542 public static boolean isAGenericType(ITypeBinding type) { 543 return type.isGenericType() 544 || type.isParameterizedType() 545 || (type.isRawType() && type.getTypeDeclaration().isGenericType()); 546 } 547 548 public CastVariable2 makeCastVariable(CastExpression castExpression, ConstraintVariable2 expressionCv) { 549 ITypeBinding typeBinding= castExpression.resolveTypeBinding(); 550 ICompilationUnit cu= RefactoringASTParser.getCompilationUnit(castExpression); 551 CompilationUnitRange range= new CompilationUnitRange(cu, castExpression); 552 CastVariable2 castCv= new CastVariable2(createTType(typeBinding), range, expressionCv); 553 fCastVariables.add(castCv); 554 return castCv; 555 } 556 557 public TypeEnvironment getTypeEnvironment() { 558 return fTypeEnvironment; 559 } 560 561 public CollectionElementVariable2 getElementVariable(ConstraintVariable2 constraintVariable, ITypeBinding typeVariable) { 562 Assert.isTrue(typeVariable.isTypeVariable()); HashMap typeVarToElementVars= (HashMap ) constraintVariable.getData(INDEXED_COLLECTION_ELEMENTS); 564 if (typeVarToElementVars == null) 565 return null; 566 return (CollectionElementVariable2) typeVarToElementVars.get(typeVariable.getKey()); 567 } 568 569 public Map getElementVariables(ConstraintVariable2 constraintVariable) { 570 Map elementVariables= (Map ) constraintVariable.getData(INDEXED_COLLECTION_ELEMENTS); 571 if (elementVariables == null) 572 return EMPTY_COLLECTION_ELEMENT_VARIABLES_MAP; 573 else 574 return elementVariables; 575 } 576 577 public ArrayElementVariable2 getArrayElementVariable(ConstraintVariable2 constraintVariable) { 578 return (ArrayElementVariable2) constraintVariable.getData(ARRAY_ELEMENT); 579 } 580 581 private void setArrayElementVariable(ConstraintVariable2 constraintVariable, ArrayElementVariable2 arrayElementVariable) { 582 constraintVariable.setData(ARRAY_ELEMENT, arrayElementVariable); 583 } 584 585 public void makeArrayElementVariable(ConstraintVariable2 constraintVariable2) { 586 if (constraintVariable2.getType() == null || ! constraintVariable2.getType().isArrayType()) 587 return; 588 589 ArrayElementVariable2 storedArrayElementVariable= getArrayElementVariable(constraintVariable2); 590 if (storedArrayElementVariable != null) 591 return; 592 593 ArrayElementVariable2 arrayElementCv= new ArrayElementVariable2(constraintVariable2); 594 arrayElementCv= (ArrayElementVariable2) storedCv(arrayElementCv); 595 setArrayElementVariable(constraintVariable2, arrayElementCv); 596 597 makeArrayElementVariable(arrayElementCv); } 599 600 public void makeElementVariables(ConstraintVariable2 expressionCv, TType type) { 601 if (isAGenericType(type)) { 602 GenericType genericType= (GenericType) type.getTypeDeclaration(); 603 TType[] typeParameters= genericType.getTypeParameters(); 604 for (int i= 0; i < typeParameters.length; i++) { 605 TypeVariable typeVariable= (TypeVariable) typeParameters[i]; 606 makeElementVariable(expressionCv, typeVariable, i); 607 if (typeVariable.getBounds().length != 0) { 608 } 610 } 611 } 612 makeElementVariablesFromSupertypes(expressionCv, type.getTypeDeclaration()); 613 } 614 615 private void makeElementVariablesFromSupertypes(ConstraintVariable2 expressionCv, TType type) { 616 TType superclass= type.getSuperclass(); 617 if (superclass != null) { 618 makeSupertypeElementVariables(expressionCv, superclass); 619 } 620 621 TType[] interfaces= type.getInterfaces(); 622 for (int i= 0; i < interfaces.length; i++) { 623 makeSupertypeElementVariables(expressionCv, interfaces[i]); 624 } 625 626 } 627 628 private void makeSupertypeElementVariables(ConstraintVariable2 expressionCv, TType supertype) { 629 if (supertype.isParameterizedType() || supertype.isRawType()) { 630 TType[] typeArguments= null; 631 if (supertype.isParameterizedType()) { 632 typeArguments= ((ParameterizedType) supertype).getTypeArguments(); 633 } 634 TypeVariable[] typeParameters= ((GenericType) supertype.getTypeDeclaration()).getTypeParameters(); 635 for (int i= 0; i < typeParameters.length; i++) { 636 TypeVariable typeParameter= typeParameters[i]; 637 TType referenceTypeArgument; 638 if (typeArguments == null) { referenceTypeArgument= typeParameter.getErasure(); 640 } else { 641 referenceTypeArgument= typeArguments[i]; 642 } 643 if (referenceTypeArgument.isTypeVariable()) { 644 CollectionElementVariable2 referenceTypeArgumentCv= getElementVariable(expressionCv, (TypeVariable) referenceTypeArgument); 645 setElementVariable(expressionCv, referenceTypeArgumentCv, typeParameter); 646 } else { 647 makeElementVariable(expressionCv, typeParameter, CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX); 648 } 649 } 650 } 651 makeElementVariablesFromSupertypes(expressionCv, supertype); 652 } 653 654 public void makeFixedElementVariables(ConstraintVariable2 expressionCv, TType type) { 655 if (isAGenericType(type)) { 656 GenericType genericType= (GenericType) type.getTypeDeclaration(); 657 TType[] typeParameters= genericType.getTypeParameters(); 658 TType[] typeArguments= null; 659 if (type.isParameterizedType()) 660 typeArguments= ((ParameterizedType) type).getTypeArguments(); 661 662 for (int i= 0; i < typeParameters.length; i++) { 663 TypeVariable typeVariable= (TypeVariable) typeParameters[i]; 664 CollectionElementVariable2 elementCv= makeElementVariable(expressionCv, typeVariable, i); 665 TType referenceTypeArgument; 666 if (typeArguments == null) { continue; } else { 669 referenceTypeArgument= typeArguments[i]; 670 } 671 createEqualsConstraint(elementCv, makeImmutableTypeVariable(referenceTypeArgument)); 672 } 676 } 677 makeFixedElementVariablesFromSupertypes(expressionCv, type.getTypeDeclaration()); 678 } 679 680 private void makeFixedElementVariablesFromSupertypes(ConstraintVariable2 expressionCv, TType type) { 681 TType superclass= type.getSuperclass(); 682 if (superclass != null) 683 makeFixedSupertypeElementVariables(expressionCv, superclass); 684 685 TType[] interfaces= type.getInterfaces(); 686 for (int i= 0; i < interfaces.length; i++) 687 makeFixedSupertypeElementVariables(expressionCv, interfaces[i]); 688 } 689 690 private void makeFixedSupertypeElementVariables(ConstraintVariable2 expressionCv, TType supertype) { 691 if (supertype.isParameterizedType() || supertype.isRawType()) { 692 TType[] typeArguments= null; 693 if (supertype.isParameterizedType()) 694 typeArguments= ((ParameterizedType) supertype).getTypeArguments(); 695 696 TypeVariable[] typeParameters= ((GenericType) supertype.getTypeDeclaration()).getTypeParameters(); 697 for (int i= 0; i < typeParameters.length; i++) { 698 TypeVariable typeParameter= typeParameters[i]; 699 TType referenceTypeArgument; 700 if (typeArguments == null) { continue; } else { 703 referenceTypeArgument= typeArguments[i]; 704 } 705 if (referenceTypeArgument.isTypeVariable()) { 706 CollectionElementVariable2 referenceTypeArgumentCv= getElementVariable(expressionCv, (TypeVariable) referenceTypeArgument); 707 setElementVariable(expressionCv, referenceTypeArgumentCv, typeParameter); 708 } else { 709 CollectionElementVariable2 elementCv= makeElementVariable(expressionCv, typeParameter, CollectionElementVariable2.NOT_DECLARED_TYPE_VARIABLE_INDEX); 710 createEqualsConstraint(elementCv, makeImmutableTypeVariable(referenceTypeArgument)); 711 } 712 } 713 } 714 makeFixedElementVariablesFromSupertypes(expressionCv, supertype); 715 } 716 717 734 public void createTypeVariablesEqualityConstraints(ConstraintVariable2 expressionCv, Map methodTypeVariables, ConstraintVariable2 referenceCv, TType reference) { 735 if (reference.isParameterizedType() || reference.isRawType()) { 736 TType[] referenceTypeArguments= null; 737 if (reference.isParameterizedType()) { 738 referenceTypeArguments= ((ParameterizedType) reference).getTypeArguments(); 739 } 740 TType[] referenceTypeParameters= ((GenericType) reference.getTypeDeclaration()).getTypeParameters(); 741 for (int i= 0; i < referenceTypeParameters.length; i++) { 742 TypeVariable referenceTypeParameter= (TypeVariable) referenceTypeParameters[i]; 743 TType referenceTypeArgument; 744 if (referenceTypeArguments == null) 745 referenceTypeArgument= referenceTypeParameter.getErasure(); 746 else 747 referenceTypeArgument= referenceTypeArguments[i]; 748 if (referenceTypeArgument.isTypeVariable()) { 749 ConstraintVariable2 referenceTypeArgumentCv= getElementTypeCv(referenceTypeArgument, expressionCv, methodTypeVariables); 750 CollectionElementVariable2 referenceTypeParametersCv= getElementVariable(referenceCv, referenceTypeParameter); 751 createEqualsConstraint(referenceTypeArgumentCv, referenceTypeParametersCv); 752 } else if (referenceTypeArgument.isWildcardType()) { 753 ConstraintVariable2 referenceTypeArgumentCv= makeImmutableTypeVariable(fTypeEnvironment.VOID); CollectionElementVariable2 referenceTypeParametersCv= getElementVariable(referenceCv, referenceTypeParameter); 755 createEqualsConstraint(referenceTypeArgumentCv, referenceTypeParametersCv); 756 757 770 } else { 778 } 780 } 781 782 } else if (reference.isArrayType()) { 783 TType elementType= ((ArrayType) reference).getElementType(); 784 if (elementType.isRawType()) 785 elementType= elementType.getErasure(); 786 ConstraintVariable2 elementTypeCv= getElementTypeCv(elementType, expressionCv, methodTypeVariables); 787 ArrayElementVariable2 arrayElementTypeCv= getArrayElementVariable(referenceCv); 788 createEqualsConstraint(elementTypeCv, arrayElementTypeCv); 789 } 790 } 791 792 private ConstraintVariable2 getElementTypeCv(TType elementType, ConstraintVariable2 expressionCv, Map methodTypeVariables) { 793 if (elementType.isTypeVariable()) { 794 ConstraintVariable2 elementTypeCv= (ConstraintVariable2) methodTypeVariables.get(elementType.getBindingKey()); 795 if (elementTypeCv != null) 796 return elementTypeCv; 797 if (expressionCv != null) 798 return getElementVariable(expressionCv, (TypeVariable) elementType); 799 } 800 return null; 801 } 802 803 private CollectionElementVariable2 makeElementVariable(ConstraintVariable2 expressionCv, TypeVariable typeVariable, int declarationTypeVariableIndex) { 804 if (expressionCv == null) 805 return null; 806 807 CollectionElementVariable2 storedElementVariable= getElementVariable(expressionCv, typeVariable); 808 if (storedElementVariable != null) 809 return storedElementVariable; 810 811 CollectionElementVariable2 cv= new CollectionElementVariable2(expressionCv, typeVariable, declarationTypeVariableIndex); 812 cv= (CollectionElementVariable2) storedCv(cv); 813 setElementVariable(expressionCv, cv, typeVariable); 814 return cv; 815 } 816 817 private void setElementVariable(ConstraintVariable2 typeConstraintVariable, CollectionElementVariable2 elementVariable, TypeVariable typeVariable) { 818 HashMap keyToElementVar= (HashMap ) typeConstraintVariable.getData(INDEXED_COLLECTION_ELEMENTS); 819 String key= typeVariable.getBindingKey(); 820 if (keyToElementVar == null) { 821 keyToElementVar= new HashMap (); 822 typeConstraintVariable.setData(INDEXED_COLLECTION_ELEMENTS, keyToElementVar); 823 } else { 824 Object existingElementVar= keyToElementVar.get(key); 825 if (existingElementVar != null) { 826 Assert.isTrue(existingElementVar == elementVariable); 827 } 828 } 829 keyToElementVar.put(key, elementVariable); 830 } 831 832 public CollectionElementVariable2 getElementVariable(ConstraintVariable2 constraintVariable, TypeVariable typeVariable) { 833 Assert.isTrue(typeVariable.isTypeVariable()); HashMap typeVarToElementVars= (HashMap ) constraintVariable.getData(INDEXED_COLLECTION_ELEMENTS); 835 if (typeVarToElementVars == null) 836 return null; 837 return (CollectionElementVariable2) typeVarToElementVars.get(typeVariable.getBindingKey()); 838 } 839 840 public void createElementEqualsConstraints(ConstraintVariable2 cv, ConstraintVariable2 initializerCv) { 841 internalCreateElementEqualsConstraints(cv, initializerCv, false); 842 } 843 844 public void createAssignmentElementConstraints(ConstraintVariable2 cv, ConstraintVariable2 initializerCv) { 845 internalCreateElementEqualsConstraints(cv, initializerCv, true); 846 } 847 848 private void internalCreateElementEqualsConstraints(ConstraintVariable2 cv, ConstraintVariable2 initializerCv, boolean isAssignment) { 849 if (cv == null || initializerCv == null) 850 return; 851 852 Map leftElements= getElementVariables(cv); 853 Map rightElements= getElementVariables(initializerCv); 854 for (Iterator leftIter= leftElements.entrySet().iterator(); leftIter.hasNext();) { 855 Map.Entry leftEntry= (Map.Entry ) leftIter.next(); 856 String leftTypeVariableKey= (String ) leftEntry.getKey(); 857 CollectionElementVariable2 rightElementVariable= (CollectionElementVariable2) rightElements.get(leftTypeVariableKey); 858 if (rightElementVariable != null) { 859 CollectionElementVariable2 leftElementVariable= (CollectionElementVariable2) leftEntry.getValue(); 860 createEqualsConstraint(leftElementVariable, rightElementVariable); 861 internalCreateElementEqualsConstraints(leftElementVariable, rightElementVariable, false); } 863 } 864 865 ArrayElementVariable2 leftArrayElement= getArrayElementVariable(cv); 866 ArrayElementVariable2 rightArrayElement= getArrayElementVariable(initializerCv); 867 if (leftArrayElement != null && rightArrayElement != null) { 868 if (isAssignment) 869 createSubtypeConstraint(rightArrayElement, leftArrayElement); 870 else 871 createEqualsConstraint(leftArrayElement, rightArrayElement); 872 internalCreateElementEqualsConstraints(leftArrayElement, rightArrayElement, false); } 874 } 875 876 881 public ConstraintVariable2 getMethodReceiverCv(ConstraintVariable2 expressionVariable) { 882 return (ConstraintVariable2) expressionVariable.getData(METHOD_RECEIVER); 883 } 884 885 public void setMethodReceiverCV(ConstraintVariable2 expressionVariable, ConstraintVariable2 methodReceiverCV) { 886 expressionVariable.setData(METHOD_RECEIVER, methodReceiverCV); 887 } 888 889 } 890 | Popular Tags |