1 11 12 package org.eclipse.jdt.internal.corext.refactoring.generics; 13 14 import java.util.Collections ; 15 import java.util.HashMap ; 16 import java.util.Iterator ; 17 import java.util.List ; 18 import java.util.Map ; 19 20 import org.eclipse.core.runtime.Assert; 21 22 import org.eclipse.jdt.core.ICompilationUnit; 23 import org.eclipse.jdt.core.dom.ASTNode; 24 import org.eclipse.jdt.core.dom.ArrayAccess; 25 import org.eclipse.jdt.core.dom.ArrayCreation; 26 import org.eclipse.jdt.core.dom.ArrayType; 27 import org.eclipse.jdt.core.dom.Assignment; 28 import org.eclipse.jdt.core.dom.BooleanLiteral; 29 import org.eclipse.jdt.core.dom.CastExpression; 30 import org.eclipse.jdt.core.dom.CatchClause; 31 import org.eclipse.jdt.core.dom.CharacterLiteral; 32 import org.eclipse.jdt.core.dom.ClassInstanceCreation; 33 import org.eclipse.jdt.core.dom.CompilationUnit; 34 import org.eclipse.jdt.core.dom.ConditionalExpression; 35 import org.eclipse.jdt.core.dom.Expression; 36 import org.eclipse.jdt.core.dom.FieldAccess; 37 import org.eclipse.jdt.core.dom.FieldDeclaration; 38 import org.eclipse.jdt.core.dom.IBinding; 39 import org.eclipse.jdt.core.dom.IMethodBinding; 40 import org.eclipse.jdt.core.dom.ITypeBinding; 41 import org.eclipse.jdt.core.dom.IVariableBinding; 42 import org.eclipse.jdt.core.dom.Javadoc; 43 import org.eclipse.jdt.core.dom.MethodDeclaration; 44 import org.eclipse.jdt.core.dom.MethodInvocation; 45 import org.eclipse.jdt.core.dom.NumberLiteral; 46 import org.eclipse.jdt.core.dom.ParenthesizedExpression; 47 import org.eclipse.jdt.core.dom.QualifiedName; 48 import org.eclipse.jdt.core.dom.ReturnStatement; 49 import org.eclipse.jdt.core.dom.SimpleName; 50 import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 51 import org.eclipse.jdt.core.dom.StringLiteral; 52 import org.eclipse.jdt.core.dom.ThisExpression; 53 import org.eclipse.jdt.core.dom.Type; 54 import org.eclipse.jdt.core.dom.TypeLiteral; 55 import org.eclipse.jdt.core.dom.VariableDeclarationExpression; 56 import org.eclipse.jdt.core.dom.VariableDeclarationFragment; 57 import org.eclipse.jdt.core.dom.VariableDeclarationStatement; 58 59 import org.eclipse.jdt.internal.corext.dom.ASTNodes; 60 import org.eclipse.jdt.internal.corext.dom.Bindings; 61 import org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor; 62 import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks; 63 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.GenericType; 64 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.ParameterizedType; 65 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TType; 66 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.TypeVariable; 67 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.WildcardType; 68 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ArrayElementVariable2; 69 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.CollectionElementVariable2; 70 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ConstraintVariable2; 71 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ImmutableTypeVariable2; 72 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.IndependentTypeVariable2; 73 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ParameterTypeVariable2; 74 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ParameterizedTypeVariable2; 75 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.ReturnTypeVariable2; 76 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TTypes; 77 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.TypeVariable2; 78 import org.eclipse.jdt.internal.corext.refactoring.typeconstraints2.VariableVariable2; 79 import org.eclipse.jdt.internal.corext.util.JdtFlags; 80 81 public class InferTypeArgumentsConstraintCreator extends HierarchicalASTVisitor { 82 83 86 private static final String CV_PROP= "org.eclipse.jdt.internal.corext.refactoring.typeconstraints.CONSTRAINT_VARIABLE"; 88 private InferTypeArgumentsTCModel fTCModel; 89 private ICompilationUnit fCU; 90 91 private final boolean fAssumeCloneReturnsSameType; 92 93 94 public InferTypeArgumentsConstraintCreator(InferTypeArgumentsTCModel model, boolean assumeCloneReturnsSameType) { 95 fTCModel= model; 96 fAssumeCloneReturnsSameType= assumeCloneReturnsSameType; 97 } 98 99 public boolean visit(CompilationUnit node) { 100 fTCModel.newCu(); fCU= (ICompilationUnit) node.getJavaElement(); 102 return super.visit(node); 103 } 104 105 public boolean visit(Javadoc node) { 106 return false; 107 } 108 109 public boolean visit(Type node) { 110 return false; } 112 113 116 public void endVisit(Type node) { 117 if (node.isParameterizedType()) { 118 ImmutableTypeVariable2 typeVariable= fTCModel.makeImmutableTypeVariable(node.resolveBinding(), null); 120 setConstraintVariable(node, typeVariable); 121 } else { 122 TypeVariable2 typeVariable= fTCModel.makeTypeVariable(node); 123 setConstraintVariable(node, typeVariable); 124 } 125 } 126 127 public void endVisit(SimpleName node) { 128 if (node.resolveBoxing()) { 129 ImmutableTypeVariable2 boxed= fTCModel.makeImmutableTypeVariable(node.resolveTypeBinding(), node); 130 setConstraintVariable(node, boxed); 131 return; 132 } 133 IBinding binding= node.resolveBinding(); 134 if (binding instanceof IVariableBinding) { 135 IVariableBinding variableBinding= (IVariableBinding) binding; 137 ITypeBinding declaredVariableType= variableBinding.getVariableDeclaration().getType(); 138 if (declaredVariableType.isTypeVariable()) { 139 Expression receiver= getSimpleNameReceiver(node); 140 if (receiver != null) { 141 ConstraintVariable2 receiverCv= getConstraintVariable(receiver); 142 Assert.isNotNull(receiverCv); 144 ConstraintVariable2 elementCv= fTCModel.getElementVariable(receiverCv, declaredVariableType); 145 setConstraintVariable(node, elementCv); 147 return; 148 } 149 150 } else if (declaredVariableType.isParameterizedType()){ 151 Expression receiver= getSimpleNameReceiver(node); 152 if (receiver != null) { 153 ConstraintVariable2 receiverCv= getConstraintVariable(receiver); 154 if (receiverCv != null) { 155 ConstraintVariable2 returnTypeCv= fTCModel.makeParameterizedTypeVariable(declaredVariableType); 157 setConstraintVariable(node, returnTypeCv); 158 TType declaredVariableTType= fTCModel.createTType(declaredVariableType); 160 fTCModel.createTypeVariablesEqualityConstraints(receiverCv, Collections.EMPTY_MAP, returnTypeCv, declaredVariableTType); 161 return; 162 } 163 } 164 165 } else { 166 } 169 170 VariableVariable2 cv= fTCModel.makeVariableVariable(variableBinding); 172 setConstraintVariable(node, cv); 173 } 174 } 176 177 private Expression getSimpleNameReceiver(SimpleName node) { 178 Expression receiver; 179 if (node.getParent() instanceof QualifiedName && node.getLocationInParent() == QualifiedName.NAME_PROPERTY) { 180 receiver= ((QualifiedName) node.getParent()).getQualifier(); 181 } else if (node.getParent() instanceof FieldAccess && node.getLocationInParent() == FieldAccess.NAME_PROPERTY) { 182 receiver= ((FieldAccess) node.getParent()).getExpression(); 183 } else { 184 receiver= null; 186 } 187 if (receiver instanceof ThisExpression) 188 return null; 189 else 190 return receiver; 191 } 192 193 public void endVisit(FieldAccess node) { 194 if (node.resolveBoxing()) { 195 ImmutableTypeVariable2 boxed= fTCModel.makeImmutableTypeVariable(node.resolveTypeBinding(), node); 196 setConstraintVariable(node, boxed); 197 return; 198 } 199 ConstraintVariable2 nameCv= getConstraintVariable(node.getName()); 200 setConstraintVariable(node, nameCv); 201 } 202 203 public void endVisit(QualifiedName node) { 204 if (node.resolveBoxing()) { 205 ImmutableTypeVariable2 boxed= fTCModel.makeImmutableTypeVariable(node.resolveTypeBinding(), node); 206 setConstraintVariable(node, boxed); 207 return; 208 } 209 ConstraintVariable2 cv= getConstraintVariable(node.getName()); 210 setConstraintVariable(node, cv); 211 } 212 213 public void endVisit(ArrayAccess node) { 214 if (node.resolveBoxing()) { 215 ImmutableTypeVariable2 boxed= fTCModel.makeImmutableTypeVariable(node.resolveTypeBinding(), node); 216 setConstraintVariable(node, boxed); 217 return; 218 } 219 220 ConstraintVariable2 arrayCv= getConstraintVariable(node.getArray()); 221 if (arrayCv == null) 222 return; 223 224 ArrayElementVariable2 arrayElementCv= fTCModel.getArrayElementVariable(arrayCv); 225 setConstraintVariable(node, arrayElementCv); 226 } 227 228 public void endVisit(Assignment node) { 229 Expression lhs= node.getLeftHandSide(); 230 Expression rhs= node.getRightHandSide(); 231 232 ConstraintVariable2 left= getConstraintVariable(lhs); 233 ConstraintVariable2 right= getConstraintVariable(rhs); 234 if (node.resolveBoxing()) { 235 ImmutableTypeVariable2 boxed= fTCModel.makeImmutableTypeVariable(node.resolveTypeBinding(), node); 236 setConstraintVariable(node, boxed); 237 } else { 238 setConstraintVariable(node, left); } 240 if (left == null || right == null) 241 return; 242 243 Assignment.Operator op= node.getOperator(); 244 if (op == Assignment.Operator.PLUS_ASSIGN && (lhs.resolveTypeBinding() == node.getAST().resolveWellKnownType("java.lang.String"))) { } else { 247 fTCModel.createElementEqualsConstraints(left, right); 248 fTCModel.createSubtypeConstraint(right, left); } 250 } 252 253 public void endVisit(CastExpression node) { 254 257 Type type= node.getType(); 258 ITypeBinding typeBinding= type.resolveBinding(); 259 if (typeBinding.isPrimitive()) { 260 ImmutableTypeVariable2 boxed= fTCModel.makeImmutableTypeVariable(typeBinding, node); 261 setConstraintVariable(node, boxed); 262 return; } 264 265 ConstraintVariable2 typeCv= getConstraintVariable(type); 266 if (typeCv == null) 267 return; 268 269 setConstraintVariable(node, typeCv); 271 272 Expression expression= node.getExpression(); 273 ConstraintVariable2 expressionCv= getConstraintVariable(expression); 274 275 if (expressionCv == null) 277 return; 278 if (expressionCv instanceof ImmutableTypeVariable2) 279 return; 280 if (! (expressionCv instanceof TypeVariable2 || expressionCv instanceof IndependentTypeVariable2 || expressionCv instanceof CollectionElementVariable2) 281 && fTCModel.getElementVariables(expressionCv).size() == 0 && fTCModel.getArrayElementVariable(expressionCv) == null) 282 return; 283 284 fTCModel.createAssignmentElementConstraints(typeCv, expressionCv); 285 286 if (expression instanceof MethodInvocation) { 287 MethodInvocation invoc= (MethodInvocation) expression; 288 if (! isSpecialCloneInvocation(invoc.resolveMethodBinding(), invoc.getExpression())) { 289 fTCModel.makeCastVariable(node, expressionCv); 290 } 291 } else { 292 fTCModel.makeCastVariable(node, expressionCv); 293 } 294 295 boolean eitherIsIntf= typeBinding.isInterface() || expression.resolveTypeBinding().isInterface(); 296 if (eitherIsIntf) 297 return; 298 299 301 } 302 303 public void endVisit(ParenthesizedExpression node) { 304 if (node.resolveBoxing()) { 305 ImmutableTypeVariable2 boxed= fTCModel.makeImmutableTypeVariable(node.resolveTypeBinding(), node); 306 setConstraintVariable(node, boxed); 307 return; 308 } 309 ConstraintVariable2 expressionCv= getConstraintVariable(node.getExpression()); 310 setConstraintVariable(node, expressionCv); 311 } 312 313 public void endVisit(ConditionalExpression node) { 314 ImmutableTypeVariable2 boxed= fTCModel.makeImmutableTypeVariable(node.resolveTypeBinding(), node); 316 setConstraintVariable(node, boxed); 317 } 318 319 public boolean visit(CatchClause node) { 320 SingleVariableDeclaration exception= node.getException(); 321 IVariableBinding variableBinding= exception.resolveBinding(); 322 VariableVariable2 cv= fTCModel.makeDeclaredVariableVariable(variableBinding, fCU); 323 setConstraintVariable(exception, cv); 324 return true; 325 } 326 327 public void endVisit(StringLiteral node) { 328 ITypeBinding typeBinding= node.resolveTypeBinding(); 329 ImmutableTypeVariable2 cv= fTCModel.makeImmutableTypeVariable(typeBinding, null); 330 setConstraintVariable(node, cv); 331 } 332 333 public void endVisit(NumberLiteral node) { 334 ITypeBinding typeBinding= node.resolveTypeBinding(); 335 ImmutableTypeVariable2 cv= fTCModel.makeImmutableTypeVariable(typeBinding, node); 336 setConstraintVariable(node, cv); 337 } 338 339 public void endVisit(BooleanLiteral node) { 340 ITypeBinding typeBinding= node.resolveTypeBinding(); 341 ImmutableTypeVariable2 cv= fTCModel.makeImmutableTypeVariable(typeBinding, node); 342 setConstraintVariable(node, cv); 343 } 344 345 public void endVisit(CharacterLiteral node) { 346 ITypeBinding typeBinding= node.resolveTypeBinding(); 347 ImmutableTypeVariable2 cv= fTCModel.makeImmutableTypeVariable(typeBinding, node); 348 setConstraintVariable(node, cv); 349 } 350 351 public void endVisit(ThisExpression node) { 352 ITypeBinding typeBinding= node.resolveTypeBinding(); 353 ImmutableTypeVariable2 cv= fTCModel.makeImmutableTypeVariable(typeBinding, null); 354 setConstraintVariable(node, cv); 355 } 356 357 public void endVisit(TypeLiteral node) { 358 ITypeBinding typeBinding= node.resolveTypeBinding(); 359 ImmutableTypeVariable2 cv= fTCModel.makeImmutableTypeVariable(typeBinding, null); 360 setConstraintVariable(node, cv); 361 } 362 363 public void endVisit(MethodDeclaration node) { 364 IMethodBinding methodBinding= node.resolveBinding(); 365 366 if (methodBinding == null) 367 return; 369 int parameterCount= node.parameters().size(); 370 ConstraintVariable2[] parameterTypeCvs= new ConstraintVariable2[parameterCount]; 371 for (int i= 0; i < parameterCount; i++) { 372 SingleVariableDeclaration paramDecl= (SingleVariableDeclaration) node.parameters().get(i); 373 ConstraintVariable2 parameterTypeCv= fTCModel.makeDeclaredParameterTypeVariable(methodBinding, i, fCU); 375 parameterTypeCvs[i]= parameterTypeCv; 376 if (parameterTypeCv == null) 377 continue; 378 379 ConstraintVariable2 typeCv= getConstraintVariable(paramDecl.getType()); 381 fTCModel.createElementEqualsConstraints(parameterTypeCv, typeCv); 382 383 ConstraintVariable2 nameCv= getConstraintVariable(paramDecl.getName()); 385 fTCModel.createElementEqualsConstraints(parameterTypeCv, nameCv); 386 } 387 388 ConstraintVariable2 returnTypeCv= null; 389 if (! methodBinding.isConstructor()) { 390 ConstraintVariable2 returnTypeBindingCv= fTCModel.makeDeclaredReturnTypeVariable(methodBinding, fCU); 392 if (returnTypeBindingCv != null) { 393 returnTypeCv= getConstraintVariable(node.getReturnType2()); 394 fTCModel.createElementEqualsConstraints(returnTypeBindingCv, returnTypeCv); 395 } 396 } 397 if (MethodChecks.isVirtual(methodBinding)) { 398 addConstraintsForOverriding(methodBinding, returnTypeCv, parameterTypeCvs); 400 } 401 } 402 403 private void addConstraintsForOverriding(IMethodBinding methodBinding, ConstraintVariable2 returnTypeCv, ConstraintVariable2[] parameterTypeCvs) { 404 boolean hasParameterElementCvs= false; 405 for (int i= 0; i < parameterTypeCvs.length; i++) 406 if (parameterTypeCvs[i] != null) 407 hasParameterElementCvs= true; 408 409 if (returnTypeCv == null && ! hasParameterElementCvs) 410 return; 411 412 ITypeBinding[] allSuperTypes= Bindings.getAllSuperTypes(methodBinding.getDeclaringClass()); 413 for (int i= 0; i < allSuperTypes.length; i++) { 414 ITypeBinding superType= allSuperTypes[i]; 415 IMethodBinding superMethod= Bindings.findOverriddenMethodInType(superType, methodBinding); 416 if (superMethod == null) 417 continue; 418 419 for (int p= 0; p < parameterTypeCvs.length; p++) { 420 if (parameterTypeCvs[p] == null) 421 continue; 422 ParameterTypeVariable2 parameterTypeCv= fTCModel.makeParameterTypeVariable(superMethod, p); 423 fTCModel.createElementEqualsConstraints(parameterTypeCv, parameterTypeCvs[p]); 424 } 425 426 if (returnTypeCv != null) { 427 ReturnTypeVariable2 superMethodReturnTypeCv= fTCModel.makeReturnTypeVariable(superMethod); 428 fTCModel.createElementEqualsConstraints(superMethodReturnTypeCv, returnTypeCv); 429 } 430 } 431 } 432 433 public void endVisit(MethodInvocation node) { 434 IMethodBinding methodBinding= node.resolveMethodBinding(); 435 if (methodBinding == null) 436 return; 437 438 Expression receiver; 439 if (JdtFlags.isStatic(methodBinding)) 440 receiver= null; 441 else 442 receiver= node.getExpression(); 443 444 446 if (isSpecialCloneInvocation(methodBinding, receiver)) { 447 ConstraintVariable2 expressionCv= getConstraintVariable(receiver); 448 setConstraintVariable(node, expressionCv); 450 451 } else if ("getClass".equals(methodBinding.getName()) && methodBinding.getParameterTypes().length == 0) { ITypeBinding returnType= node.resolveTypeBinding(); 454 ITypeBinding returnTypeDeclaration= returnType.getTypeDeclaration(); 455 ParameterizedTypeVariable2 expressionCv= fTCModel.makeParameterizedTypeVariable(returnTypeDeclaration); 456 setConstraintVariable(node, expressionCv); 457 ConstraintVariable2 classTypeVariable= fTCModel.getElementVariable(expressionCv, returnTypeDeclaration.getTypeParameters()[0]); 458 459 ITypeBinding capture= returnType.getTypeArguments()[0]; 461 ITypeBinding wildcard= capture.getWildcard(); 462 ImmutableTypeVariable2 wildcardType= fTCModel.makeImmutableTypeVariable(wildcard, null); 463 fTCModel.createSubtypeConstraint(classTypeVariable, wildcardType); 464 465 469 } else { 470 Map methodTypeVariables= createMethodTypeArguments(methodBinding); 471 472 doVisitMethodInvocationReturnType(node, methodBinding, receiver, methodTypeVariables); 473 doVisitMethodInvocationArguments(methodBinding, node.arguments(), receiver, methodTypeVariables, null); 474 } 475 476 } 477 478 481 private Map createMethodTypeArguments(IMethodBinding methodBinding) { 482 ITypeBinding[] methodTypeParameters= methodBinding.getMethodDeclaration().getTypeParameters(); 483 Map methodTypeVariables; 484 if (methodTypeParameters.length == 0) { 485 methodTypeVariables= Collections.EMPTY_MAP; 486 } else { 487 methodTypeVariables= new HashMap (); 488 for (int i= 0; i < methodTypeParameters.length; i++) { 489 ITypeBinding methodTypeParameter= methodTypeParameters[i]; 490 TypeVariable typeVariable= (TypeVariable) fTCModel.createTType(methodTypeParameter); 492 IndependentTypeVariable2 typeVariableCv= fTCModel.makeIndependentTypeVariable(typeVariable); 493 methodTypeVariables.put(methodTypeParameter.getKey(), typeVariableCv); 494 } 495 } 496 return methodTypeVariables; 497 } 498 499 private void doVisitMethodInvocationReturnType(MethodInvocation node, IMethodBinding methodBinding, Expression receiver, Map methodTypeVariables) { 500 ITypeBinding declaredReturnType= methodBinding.getMethodDeclaration().getReturnType(); 501 502 if (declaredReturnType.isPrimitive()) { 503 ImmutableTypeVariable2 boxed= fTCModel.makeImmutableTypeVariable(declaredReturnType, node); 504 setConstraintVariable(node, boxed); 505 506 } else if (declaredReturnType.isTypeVariable()) { 507 ConstraintVariable2 methodTypeVariableCv= (ConstraintVariable2) methodTypeVariables.get(declaredReturnType.getKey()); 508 if (methodTypeVariableCv != null) { 509 setConstraintVariable(node, methodTypeVariableCv); 512 523 } else { 524 526 if (receiver == null) return; 528 ConstraintVariable2 expressionCv= getConstraintVariable(receiver); 530 ConstraintVariable2 elementCv= fTCModel.getElementVariable(expressionCv, declaredReturnType); 531 setConstraintVariable(node, elementCv); 533 } 534 535 } else if (declaredReturnType.isParameterizedType()) { 536 ConstraintVariable2 returnTypeCv= fTCModel.makeParameterizedTypeVariable(declaredReturnType.getTypeDeclaration()); 537 setConstraintVariable(node, returnTypeCv); 538 ConstraintVariable2 receiverCv= null; 540 if (receiver != null) receiverCv= getConstraintVariable(receiver); 542 TType declaredReturnTType= fTCModel.createTType(declaredReturnType); 544 fTCModel.createTypeVariablesEqualityConstraints(receiverCv, methodTypeVariables, returnTypeCv, declaredReturnTType); 545 546 } else if (declaredReturnType.isArray()) { 547 ConstraintVariable2 returnTypeCv= fTCModel.makeArrayTypeVariable(declaredReturnType); 548 setConstraintVariable(node, returnTypeCv); 549 ConstraintVariable2 receiverCv= null; 551 if (receiver != null) { receiverCv= getConstraintVariable(receiver); 553 554 fTCModel.setMethodReceiverCV(returnTypeCv, receiverCv); 556 } 557 TType declaredReturnTType= fTCModel.createTType(declaredReturnType); 559 fTCModel.createTypeVariablesEqualityConstraints(receiverCv, methodTypeVariables, returnTypeCv, declaredReturnTType); 560 561 } else { 562 ReturnTypeVariable2 returnTypeCv= fTCModel.makeReturnTypeVariable(methodBinding); 563 setConstraintVariable(node, returnTypeCv); 564 } 565 } 566 567 private boolean isSpecialCloneInvocation(IMethodBinding methodBinding, Expression receiver) { 568 return fAssumeCloneReturnsSameType 569 && "clone".equals(methodBinding.getName()) && methodBinding.getParameterTypes().length == 0 571 && receiver != null 572 && receiver.resolveTypeBinding() != methodBinding.getMethodDeclaration().getReturnType(); 573 } 574 575 private void doVisitMethodInvocationArguments(IMethodBinding methodBinding, List arguments, Expression receiver, Map methodTypeVariables, Type createdType) { 576 ITypeBinding[] declaredParameterTypes= methodBinding.getMethodDeclaration().getParameterTypes(); 578 int lastParamIdx= declaredParameterTypes.length - 1; 579 for (int i= 0; i < arguments.size(); i++) { 580 Expression arg= (Expression) arguments.get(i); 581 ConstraintVariable2 argCv= getConstraintVariable(arg); 582 if (argCv == null) 583 continue; 584 585 TType declaredParameterType; 586 int iParam; 587 if (! methodBinding.isVarargs() || i < lastParamIdx) { 588 iParam= i; 589 declaredParameterType= fTCModel.createTType(declaredParameterTypes[iParam]); 590 } else { iParam= lastParamIdx; 592 declaredParameterType= fTCModel.createTType(declaredParameterTypes[iParam]); 593 if (i == lastParamIdx && canAssignToVararg( 594 fTCModel.createTType(arg.resolveTypeBinding()), 595 (org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.ArrayType) declaredParameterType)) { 596 } else { 598 declaredParameterType= ((org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.ArrayType) declaredParameterType).getComponentType(); 599 } 600 } 601 602 if (declaredParameterType.isTypeVariable()) { 603 604 ConstraintVariable2 methodTypeVariableCv= (ConstraintVariable2) methodTypeVariables.get(declaredParameterType.getBindingKey()); 605 if (methodTypeVariableCv != null) { 606 fTCModel.createSubtypeConstraint(argCv, methodTypeVariableCv); 608 609 } else { 610 if (createdType != null) { 611 ConstraintVariable2 createdTypeCv= getConstraintVariable(createdType); 613 ConstraintVariable2 elementCv= fTCModel.getElementVariable(createdTypeCv, (TypeVariable) declaredParameterType); 614 fTCModel.createSubtypeConstraint(argCv, elementCv); 616 } 617 if (receiver != null) { 618 ConstraintVariable2 expressionCv= getConstraintVariable(receiver); 620 ConstraintVariable2 elementCv= fTCModel.getElementVariable(expressionCv, (TypeVariable) declaredParameterType); 621 622 630 fTCModel.createSubtypeConstraint(argCv, elementCv); 632 } else { 633 } 635 } 636 } else if (declaredParameterType.isParameterizedType()) { 637 TType[] typeArguments= ((ParameterizedType) declaredParameterType).getTypeArguments(); 638 TypeVariable[] typeParameters= ((GenericType) declaredParameterType.getTypeDeclaration()).getTypeParameters(); 639 for (int ta= 0; ta < typeArguments.length; ta++) { 640 TType typeArgument= typeArguments[ta]; 641 CollectionElementVariable2 argElementCv= fTCModel.getElementVariable(argCv, typeParameters[ta]); 642 if (typeArgument.isWildcardType()) { 643 WildcardType wildcardTypeArgument= (WildcardType) typeArgument; 645 TType bound= wildcardTypeArgument.getBound(); 646 if (bound != null && bound.isTypeVariable()) { 647 ConstraintVariable2 methodTypeVariableCv= (ConstraintVariable2) methodTypeVariables.get(bound.getBindingKey()); 648 if (methodTypeVariableCv != null) { 649 createWildcardConstraint(wildcardTypeArgument, argElementCv, methodTypeVariableCv); 651 } else { 652 if (createdType != null) { 653 ConstraintVariable2 createdTypeCv= getConstraintVariable(createdType); 654 CollectionElementVariable2 elementCv= fTCModel.getElementVariable(createdTypeCv, typeParameters[ta]); 655 createWildcardConstraint(wildcardTypeArgument, argElementCv, elementCv); 656 } 657 if (receiver != null) { 658 ConstraintVariable2 expressionCv= getConstraintVariable(receiver); 660 CollectionElementVariable2 elementCv= fTCModel.getElementVariable(expressionCv, typeParameters[ta]); 661 createWildcardConstraint(wildcardTypeArgument, argElementCv, elementCv); 662 } else { 663 } 665 } 666 667 } else { 668 } 670 671 } else if (typeArgument.isTypeVariable()) { 672 ConstraintVariable2 methodTypeVariableCv= (ConstraintVariable2) methodTypeVariables.get(typeArgument.getBindingKey()); 673 if (methodTypeVariableCv != null) { 674 fTCModel.createEqualsConstraint(argElementCv, methodTypeVariableCv); 676 } else { 677 if (createdType != null) { 678 ConstraintVariable2 createdTypeCv= getConstraintVariable(createdType); 679 ConstraintVariable2 elementCv= fTCModel.getElementVariable(createdTypeCv, (TypeVariable) typeArgument); 680 fTCModel.createEqualsConstraint(argElementCv, elementCv); 681 } 682 if (receiver != null) { 683 ConstraintVariable2 expressionCv= getConstraintVariable(receiver); 684 ConstraintVariable2 elementCv= fTCModel.getElementVariable(expressionCv, (TypeVariable) typeArgument); 685 fTCModel.createEqualsConstraint(argElementCv, elementCv); 686 } else { 687 } 689 } 690 691 } else { 692 ImmutableTypeVariable2 typeArgumentCv= fTCModel.makeImmutableTypeVariable(typeArgument); 693 fTCModel.createEqualsConstraint(argElementCv, typeArgumentCv); 694 } 695 } 696 697 } else if (declaredParameterType.isArrayType()) { 698 TType declaredElementType= ((org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.ArrayType) declaredParameterType).getElementType(); 700 if (declaredElementType.isTypeVariable()) { 701 ConstraintVariable2 methodTypeVariableCv= (ConstraintVariable2) methodTypeVariables.get(declaredElementType.getBindingKey()); 702 if (methodTypeVariableCv != null) { 703 ArrayElementVariable2 argElementCv= fTCModel.getArrayElementVariable(argCv); 704 fTCModel.createEqualsConstraint(argElementCv, methodTypeVariableCv); 706 } else { 707 } 709 } else { 710 } 712 713 } else { if (! InferTypeArgumentsTCModel.isAGenericType(declaredParameterType)) 715 continue; 716 ParameterTypeVariable2 parameterTypeCv= fTCModel.makeParameterTypeVariable(methodBinding, iParam); 717 fTCModel.createElementEqualsConstraints(parameterTypeCv, argCv); 719 } 720 } 721 } 722 723 private boolean canAssignToVararg(TType rhs, org.eclipse.jdt.internal.corext.refactoring.typeconstraints.types.ArrayType lhs) { 724 return TTypes.canAssignTo(rhs.getErasure(), lhs.getErasure()); 725 } 726 727 private void createWildcardConstraint(WildcardType typeArgument, CollectionElementVariable2 argElementCv, ConstraintVariable2 paramElementCv) { 728 if (typeArgument.isExtendsWildcardType()) 729 fTCModel.createSubtypeConstraint(argElementCv, paramElementCv); 730 else 731 fTCModel.createSubtypeConstraint(paramElementCv, argElementCv); 732 } 733 734 public void endVisit(ClassInstanceCreation node) { 735 Expression receiver= node.getExpression(); 736 Type createdType= node.getType(); 737 738 ConstraintVariable2 typeCv; 739 if (node.getAnonymousClassDeclaration() == null) { 740 typeCv= getConstraintVariable(createdType); 741 } else { 742 typeCv= fTCModel.makeImmutableTypeVariable(createdType.resolveBinding(), null); 743 setConstraintVariable(createdType, typeCv); 744 } 745 setConstraintVariable(node, typeCv); 746 747 IMethodBinding methodBinding= node.resolveConstructorBinding(); 748 Map methodTypeVariables= createMethodTypeArguments(methodBinding); 749 List arguments= node.arguments(); 750 doVisitMethodInvocationArguments(methodBinding, arguments, receiver, methodTypeVariables, createdType); 751 } 752 753 public void endVisit(ArrayCreation node) { 754 ArrayType arrayType= node.getType(); 755 TypeVariable2 arrayTypeCv= (TypeVariable2) getConstraintVariable(arrayType); 756 if (arrayTypeCv == null) 757 return; 758 setConstraintVariable(node, arrayTypeCv); 759 } 761 762 public void endVisit(ReturnStatement node) { 763 Expression expression= node.getExpression(); 764 if (expression == null) 765 return; 766 ConstraintVariable2 expressionCv= getConstraintVariable(expression); 767 if (expressionCv == null) 768 return; 769 770 MethodDeclaration methodDeclaration= (MethodDeclaration) ASTNodes.getParent(node, ASTNode.METHOD_DECLARATION); 771 if (methodDeclaration == null) 772 return; 773 IMethodBinding methodBinding= methodDeclaration.resolveBinding(); 774 if (methodBinding == null) 775 return; 776 ReturnTypeVariable2 returnTypeCv= fTCModel.makeReturnTypeVariable(methodBinding); 777 if (returnTypeCv == null) 778 return; 779 780 fTCModel.createElementEqualsConstraints(returnTypeCv, expressionCv); 781 } 782 783 public void endVisit(VariableDeclarationExpression node) { 784 Type type= node.getType(); 788 ConstraintVariable2 typeCv= getConstraintVariable(type); 789 if (typeCv == null) 790 return; 791 792 setConstraintVariable(node, typeCv); 793 794 List fragments= node.fragments(); 795 for (Iterator iter= fragments.iterator(); iter.hasNext();) { 796 VariableDeclarationFragment fragment= (VariableDeclarationFragment) iter.next(); 797 ConstraintVariable2 fragmentCv= getConstraintVariable(fragment); 798 fTCModel.createElementEqualsConstraints(typeCv, fragmentCv); 799 } 800 } 801 802 public void endVisit(VariableDeclarationStatement node) { 803 endVisitFieldVariableDeclaration(node.getType(), node.fragments()); 807 } 808 809 public void endVisit(FieldDeclaration node) { 810 endVisitFieldVariableDeclaration(node.getType(), node.fragments()); 814 } 815 816 private void endVisitFieldVariableDeclaration(Type type, List variableDeclarationFragments) { 817 ConstraintVariable2 typeCv= getConstraintVariable(type); 818 if (typeCv == null) 819 return; 820 821 for (Iterator iter= variableDeclarationFragments.iterator(); iter.hasNext();) { 822 VariableDeclarationFragment fragment= (VariableDeclarationFragment) iter.next(); 823 ConstraintVariable2 fragmentCv= getConstraintVariable(fragment); 824 fTCModel.createElementEqualsConstraints(typeCv, fragmentCv); 825 } 826 } 827 828 public void endVisit(SingleVariableDeclaration node) { 829 832 834 851 857 Expression initializer= node.getInitializer(); 859 if (initializer == null) 860 return; 861 862 } 867 868 public void endVisit(VariableDeclarationFragment node) { 869 VariableVariable2 cv= fTCModel.makeDeclaredVariableVariable(node.resolveBinding(), fCU); 870 if (cv == null) 871 return; 872 873 setConstraintVariable(node, cv); 874 875 877 Expression initializer= node.getInitializer(); 878 if (initializer == null) 879 return; 880 881 ConstraintVariable2 initializerCv= getConstraintVariable(initializer); 882 if (initializerCv == null) 883 return; 884 885 fTCModel.createElementEqualsConstraints(cv, initializerCv); 886 887 } 891 892 894 public InferTypeArgumentsTCModel getTCModel() { 895 return fTCModel; 896 } 897 898 902 protected static ConstraintVariable2 getConstraintVariable(ASTNode node) { 903 return (ConstraintVariable2) node.getProperty(CV_PROP); 904 } 905 906 910 protected static void setConstraintVariable(ASTNode node, ConstraintVariable2 constraintVariable) { 911 node.setProperty(CV_PROP, constraintVariable); 912 } 913 914 924 } 925 | Popular Tags |