1 11 12 package org.eclipse.jdt.internal.ui.text.correction; 13 14 import java.util.ArrayList ; 15 import java.util.Collection ; 16 import java.util.HashSet ; 17 import java.util.Iterator ; 18 import java.util.List ; 19 20 import org.eclipse.core.runtime.IProgressMonitor; 21 22 import org.eclipse.jdt.core.ICompilationUnit; 23 import org.eclipse.jdt.core.JavaModelException; 24 import org.eclipse.jdt.core.dom.AST; 25 import org.eclipse.jdt.core.dom.ASTNode; 26 import org.eclipse.jdt.core.dom.ASTParser; 27 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; 28 import org.eclipse.jdt.core.dom.Annotation; 29 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; 30 import org.eclipse.jdt.core.dom.ArrayAccess; 31 import org.eclipse.jdt.core.dom.ArrayCreation; 32 import org.eclipse.jdt.core.dom.ArrayInitializer; 33 import org.eclipse.jdt.core.dom.ArrayType; 34 import org.eclipse.jdt.core.dom.AssertStatement; 35 import org.eclipse.jdt.core.dom.Assignment; 36 import org.eclipse.jdt.core.dom.BodyDeclaration; 37 import org.eclipse.jdt.core.dom.CastExpression; 38 import org.eclipse.jdt.core.dom.ClassInstanceCreation; 39 import org.eclipse.jdt.core.dom.CompilationUnit; 40 import org.eclipse.jdt.core.dom.ConditionalExpression; 41 import org.eclipse.jdt.core.dom.ConstructorInvocation; 42 import org.eclipse.jdt.core.dom.Expression; 43 import org.eclipse.jdt.core.dom.FieldAccess; 44 import org.eclipse.jdt.core.dom.FieldDeclaration; 45 import org.eclipse.jdt.core.dom.IBinding; 46 import org.eclipse.jdt.core.dom.IMethodBinding; 47 import org.eclipse.jdt.core.dom.ITypeBinding; 48 import org.eclipse.jdt.core.dom.IVariableBinding; 49 import org.eclipse.jdt.core.dom.InfixExpression; 50 import org.eclipse.jdt.core.dom.Initializer; 51 import org.eclipse.jdt.core.dom.InstanceofExpression; 52 import org.eclipse.jdt.core.dom.MemberValuePair; 53 import org.eclipse.jdt.core.dom.MethodDeclaration; 54 import org.eclipse.jdt.core.dom.MethodInvocation; 55 import org.eclipse.jdt.core.dom.Modifier; 56 import org.eclipse.jdt.core.dom.Name; 57 import org.eclipse.jdt.core.dom.ParameterizedType; 58 import org.eclipse.jdt.core.dom.PrefixExpression; 59 import org.eclipse.jdt.core.dom.PrimitiveType; 60 import org.eclipse.jdt.core.dom.QualifiedName; 61 import org.eclipse.jdt.core.dom.QualifiedType; 62 import org.eclipse.jdt.core.dom.SimpleName; 63 import org.eclipse.jdt.core.dom.SimpleType; 64 import org.eclipse.jdt.core.dom.SingleVariableDeclaration; 65 import org.eclipse.jdt.core.dom.Statement; 66 import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; 67 import org.eclipse.jdt.core.dom.SuperConstructorInvocation; 68 import org.eclipse.jdt.core.dom.SuperMethodInvocation; 69 import org.eclipse.jdt.core.dom.SwitchCase; 70 import org.eclipse.jdt.core.dom.SwitchStatement; 71 import org.eclipse.jdt.core.dom.TagElement; 72 import org.eclipse.jdt.core.dom.TryStatement; 73 import org.eclipse.jdt.core.dom.Type; 74 import org.eclipse.jdt.core.dom.TypeDeclaration; 75 import org.eclipse.jdt.core.dom.TypeLiteral; 76 import org.eclipse.jdt.core.dom.TypeParameter; 77 import org.eclipse.jdt.core.dom.VariableDeclaration; 78 import org.eclipse.jdt.core.dom.VariableDeclarationExpression; 79 import org.eclipse.jdt.core.dom.VariableDeclarationFragment; 80 import org.eclipse.jdt.core.dom.VariableDeclarationStatement; 81 import org.eclipse.jdt.core.dom.WildcardType; 82 import org.eclipse.jdt.core.dom.PrimitiveType.Code; 83 84 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; 85 import org.eclipse.jdt.internal.corext.dom.ASTNodes; 86 import org.eclipse.jdt.internal.corext.dom.Bindings; 87 import org.eclipse.jdt.internal.corext.dom.GenericVisitor; 88 import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer; 89 import org.eclipse.jdt.internal.corext.dom.TypeBindingVisitor; 90 91 import org.eclipse.jdt.ui.JavaElementLabels; 92 93 import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; 94 import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider; 95 96 public class ASTResolving { 97 98 public static ITypeBinding guessBindingForReference(ASTNode node) { 99 return Bindings.normalizeTypeBinding(getPossibleReferenceBinding(node)); 100 } 101 102 private static ITypeBinding getPossibleReferenceBinding(ASTNode node) { 103 ASTNode parent= node.getParent(); 104 switch (parent.getNodeType()) { 105 case ASTNode.ASSIGNMENT: 106 Assignment assignment= (Assignment) parent; 107 if (node.equals(assignment.getLeftHandSide())) { 108 return assignment.getRightHandSide().resolveTypeBinding(); 110 } 111 return assignment.getLeftHandSide().resolveTypeBinding(); 113 case ASTNode.INFIX_EXPRESSION: 114 InfixExpression infix= (InfixExpression) parent; 115 InfixExpression.Operator op= infix.getOperator(); 116 if (op == InfixExpression.Operator.CONDITIONAL_AND || op == InfixExpression.Operator.CONDITIONAL_OR) { 117 return infix.getAST().resolveWellKnownType("boolean"); } else if (op == InfixExpression.Operator.LEFT_SHIFT || op == InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED || op == InfixExpression.Operator.RIGHT_SHIFT_SIGNED) { 120 return infix.getAST().resolveWellKnownType("int"); } 123 if (node.equals(infix.getLeftOperand())) { 124 ITypeBinding rigthHandBinding= infix.getRightOperand().resolveTypeBinding(); 126 if (rigthHandBinding != null) { 127 return rigthHandBinding; 128 } 129 } else { 130 ITypeBinding leftHandBinding= infix.getLeftOperand().resolveTypeBinding(); 132 if (leftHandBinding != null) { 133 return leftHandBinding; 134 } 135 } 136 if (op != InfixExpression.Operator.EQUALS && op != InfixExpression.Operator.NOT_EQUALS) { 137 return infix.getAST().resolveWellKnownType("int"); } 139 break; 140 case ASTNode.INSTANCEOF_EXPRESSION: 141 InstanceofExpression instanceofExpression= (InstanceofExpression) parent; 142 return instanceofExpression.getRightOperand().resolveBinding(); 143 case ASTNode.VARIABLE_DECLARATION_FRAGMENT: 144 VariableDeclarationFragment frag= (VariableDeclarationFragment) parent; 145 if (frag.getInitializer().equals(node)) { 146 return frag.getName().resolveTypeBinding(); 147 } 148 break; 149 case ASTNode.SUPER_METHOD_INVOCATION: 150 SuperMethodInvocation superMethodInvocation= (SuperMethodInvocation) parent; 151 IMethodBinding superMethodBinding= ASTNodes.getMethodBinding(superMethodInvocation.getName()); 152 if (superMethodBinding != null) { 153 return getParameterTypeBinding(node, superMethodInvocation.arguments(), superMethodBinding); 154 } 155 break; 156 case ASTNode.METHOD_INVOCATION: 157 MethodInvocation methodInvocation= (MethodInvocation) parent; 158 IMethodBinding methodBinding= methodInvocation.resolveMethodBinding(); 159 if (methodBinding != null) { 160 return getParameterTypeBinding(node, methodInvocation.arguments(), methodBinding); 161 } 162 break; 163 case ASTNode.SUPER_CONSTRUCTOR_INVOCATION: { 164 SuperConstructorInvocation superInvocation= (SuperConstructorInvocation) parent; 165 IMethodBinding superBinding= superInvocation.resolveConstructorBinding(); 166 if (superBinding != null) { 167 return getParameterTypeBinding(node, superInvocation.arguments(), superBinding); 168 } 169 break; 170 } 171 case ASTNode.CONSTRUCTOR_INVOCATION: { 172 ConstructorInvocation constrInvocation= (ConstructorInvocation) parent; 173 IMethodBinding constrBinding= constrInvocation.resolveConstructorBinding(); 174 if (constrBinding != null) { 175 return getParameterTypeBinding(node, constrInvocation.arguments(), constrBinding); 176 } 177 break; 178 } 179 case ASTNode.CLASS_INSTANCE_CREATION: { 180 ClassInstanceCreation creation= (ClassInstanceCreation) parent; 181 IMethodBinding creationBinding= creation.resolveConstructorBinding(); 182 if (creationBinding != null) { 183 return getParameterTypeBinding(node, creation.arguments(), creationBinding); 184 } 185 break; 186 } 187 case ASTNode.PARENTHESIZED_EXPRESSION: 188 return guessBindingForReference(parent); 189 case ASTNode.ARRAY_ACCESS: 190 if (((ArrayAccess) parent).getIndex().equals(node)) { 191 return parent.getAST().resolveWellKnownType("int"); } else { 193 return getPossibleReferenceBinding(parent); 194 } 195 case ASTNode.ARRAY_CREATION: 196 if (((ArrayCreation) parent).dimensions().contains(node)) { 197 return parent.getAST().resolveWellKnownType("int"); } 199 break; 200 case ASTNode.ARRAY_INITIALIZER: 201 ASTNode initializerParent= parent.getParent(); 202 int dim= 1; 203 while (initializerParent instanceof ArrayInitializer) { 204 initializerParent= initializerParent.getParent(); 205 dim++; 206 } 207 Type creationType= null; 208 if (initializerParent instanceof ArrayCreation) { 209 creationType= ((ArrayCreation) initializerParent).getType(); 210 } else if (initializerParent instanceof VariableDeclaration) { 211 VariableDeclaration varDecl= (VariableDeclaration) initializerParent; 212 creationType= ASTNodes.getType(varDecl); 213 dim-= varDecl.getExtraDimensions(); 214 } else if (initializerParent instanceof MemberValuePair) { 215 String name= ((MemberValuePair) initializerParent).getName().getIdentifier(); 216 IMethodBinding annotMember= findAnnotationMember((Annotation) initializerParent.getParent(), name); 217 if (annotMember != null) { 218 return getReducedDimensionBinding(annotMember.getReturnType(), dim); 219 } 220 } 221 if (creationType != null) { 222 while ((creationType instanceof ArrayType) && dim > 0) { 223 creationType= ((ArrayType) creationType).getComponentType(); 224 dim--; 225 } 226 return creationType.resolveBinding(); 227 } 228 break; 229 case ASTNode.CONDITIONAL_EXPRESSION: 230 ConditionalExpression expression= (ConditionalExpression) parent; 231 if (node.equals(expression.getExpression())) { 232 return parent.getAST().resolveWellKnownType("boolean"); } 234 if (node.equals(expression.getElseExpression())) { 235 return expression.getThenExpression().resolveTypeBinding(); 236 } 237 return expression.getElseExpression().resolveTypeBinding(); 238 case ASTNode.POSTFIX_EXPRESSION: 239 return parent.getAST().resolveWellKnownType("int"); case ASTNode.PREFIX_EXPRESSION: 241 if (((PrefixExpression) parent).getOperator() == PrefixExpression.Operator.NOT) { 242 return parent.getAST().resolveWellKnownType("boolean"); } 244 return parent.getAST().resolveWellKnownType("int"); case ASTNode.IF_STATEMENT: 246 case ASTNode.WHILE_STATEMENT: 247 case ASTNode.DO_STATEMENT: 248 if (node instanceof Expression) { 249 return parent.getAST().resolveWellKnownType("boolean"); } 251 break; 252 case ASTNode.SWITCH_STATEMENT: 253 if (((SwitchStatement) parent).getExpression().equals(node)) { 254 return parent.getAST().resolveWellKnownType("int"); } 256 break; 257 case ASTNode.RETURN_STATEMENT: 258 MethodDeclaration decl= ASTResolving.findParentMethodDeclaration(parent); 259 if (decl != null && !decl.isConstructor()) { 260 return decl.getReturnType2().resolveBinding(); 261 } 262 break; 263 case ASTNode.CAST_EXPRESSION: 264 return ((CastExpression) parent).getType().resolveBinding(); 265 case ASTNode.THROW_STATEMENT: 266 case ASTNode.CATCH_CLAUSE: 267 return parent.getAST().resolveWellKnownType("java.lang.Exception"); case ASTNode.FIELD_ACCESS: 269 if (node.equals(((FieldAccess) parent).getName())) { 270 return getPossibleReferenceBinding(parent); 271 } 272 break; 273 case ASTNode.SUPER_FIELD_ACCESS: 274 return getPossibleReferenceBinding(parent); 275 case ASTNode.QUALIFIED_NAME: 276 if (node.equals(((QualifiedName) parent).getName())) { 277 return getPossibleReferenceBinding(parent); 278 } 279 break; 280 case ASTNode.SWITCH_CASE: 281 if (node.equals(((SwitchCase) parent).getExpression()) && parent.getParent() instanceof SwitchStatement) { 282 return ((SwitchStatement) parent.getParent()).getExpression().resolveTypeBinding(); 283 } 284 break; 285 case ASTNode.ASSERT_STATEMENT: 286 if (node.getLocationInParent() == AssertStatement.EXPRESSION_PROPERTY) { 287 return parent.getAST().resolveWellKnownType("boolean"); } 289 return parent.getAST().resolveWellKnownType("java.lang.String"); case ASTNode.SINGLE_MEMBER_ANNOTATION: { 291 IMethodBinding annotMember= findAnnotationMember((Annotation) parent, "value"); if (annotMember != null) { 293 return annotMember.getReturnType(); 294 } 295 break; 296 } 297 case ASTNode.MEMBER_VALUE_PAIR: { 298 String name= ((MemberValuePair) parent).getName().getIdentifier(); 299 IMethodBinding annotMember= findAnnotationMember((Annotation) parent.getParent(), name); 300 if (annotMember != null) { 301 return annotMember.getReturnType(); 302 } 303 break; 304 } 305 default: 306 } 308 309 return null; 310 } 311 312 private static IMethodBinding findAnnotationMember(Annotation annotation, String name) { 313 ITypeBinding annotBinding= annotation.resolveTypeBinding(); 314 if (annotBinding != null) { 315 return Bindings.findMethodInType(annotBinding, name, (String []) null); 316 } 317 return null; 318 } 319 320 public static Type guessTypeForReference(AST ast, ASTNode node) { 321 ASTNode parent= node.getParent(); 322 while (parent != null) { 323 switch (parent.getNodeType()) { 324 case ASTNode.VARIABLE_DECLARATION_FRAGMENT: 325 if (((VariableDeclarationFragment) parent).getInitializer() == node) { 326 return ASTNodeFactory.newType(ast, (VariableDeclaration) parent); 327 } 328 return null; 329 case ASTNode.SINGLE_VARIABLE_DECLARATION: 330 if (((VariableDeclarationFragment) parent).getInitializer() == node) { 331 return ASTNodeFactory.newType(ast, (VariableDeclaration) parent); 332 } 333 return null; 334 case ASTNode.ARRAY_ACCESS: 335 if (!((ArrayAccess) parent).getIndex().equals(node)) { 336 Type type= guessTypeForReference(ast, parent); 337 if (type != null) { 338 return ast.newArrayType(type); 339 } 340 } 341 return null; 342 case ASTNode.FIELD_ACCESS: 343 if (node.equals(((FieldAccess) parent).getName())) { 344 node= parent; 345 parent= parent.getParent(); 346 } else { 347 return null; 348 } 349 break; 350 case ASTNode.SUPER_FIELD_ACCESS: 351 case ASTNode.PARENTHESIZED_EXPRESSION: 352 node= parent; 353 parent= parent.getParent(); 354 break; 355 case ASTNode.QUALIFIED_NAME: 356 if (node.equals(((QualifiedName) parent).getName())) { 357 node= parent; 358 parent= parent.getParent(); 359 } else { 360 return null; 361 } 362 break; 363 default: 364 return null; 365 } 366 } 367 return null; 368 } 369 370 private static ITypeBinding getReducedDimensionBinding(ITypeBinding arrayBinding, int dimsToReduce) { 371 while (dimsToReduce > 0) { 372 arrayBinding= arrayBinding.getComponentType(); 373 dimsToReduce--; 374 } 375 return arrayBinding; 376 } 377 378 private static ITypeBinding getParameterTypeBinding(ASTNode node, List args, IMethodBinding binding) { 379 ITypeBinding[] paramTypes= binding.getParameterTypes(); 380 int index= args.indexOf(node); 381 if (binding.isVarargs() && index >= paramTypes.length - 1) { 382 return paramTypes[paramTypes.length - 1].getComponentType(); 383 } 384 if (index >= 0 && index < paramTypes.length) { 385 return paramTypes[index]; 386 } 387 return null; 388 } 389 390 public static ITypeBinding guessBindingForTypeReference(ASTNode node) { 391 StructuralPropertyDescriptor locationInParent= node.getLocationInParent(); 392 if (locationInParent == QualifiedName.QUALIFIER_PROPERTY) { 393 return null; } 395 if (locationInParent == SimpleType.NAME_PROPERTY) { 396 node= node.getParent(); 397 } 398 ITypeBinding binding= Bindings.normalizeTypeBinding(getPossibleTypeBinding(node)); 399 if (binding != null) { 400 if (binding.isWildcardType()) { 401 return normalizeWildcardType(binding, true, node.getAST()); 402 } 403 } 404 return binding; 405 } 406 407 private static ITypeBinding getPossibleTypeBinding(ASTNode node) { 408 ASTNode parent= node.getParent(); 409 switch (parent.getNodeType()) { 410 case ASTNode.ARRAY_TYPE: { 411 int dim= 1; 412 while (parent.getParent() instanceof ArrayType) { 413 parent= parent.getParent(); 414 dim++; 415 } 416 ITypeBinding parentBinding= getPossibleTypeBinding(parent); 417 if (parentBinding != null && parentBinding.getDimensions() == dim) { 418 return parentBinding.getElementType(); 419 } 420 return null; 421 } 422 case ASTNode.PARAMETERIZED_TYPE: { 423 ITypeBinding parentBinding= getPossibleTypeBinding(parent); 424 if (parentBinding == null || !parentBinding.isParameterizedType()) { 425 return null; 426 } 427 if (node.getLocationInParent() == ParameterizedType.TYPE_PROPERTY) { 428 return parentBinding; 429 } 430 431 ITypeBinding[] typeArguments= parentBinding.getTypeArguments(); 432 List argumentNodes= ((ParameterizedType) parent).typeArguments(); 433 int index= argumentNodes.indexOf(node); 434 if (index != -1 && typeArguments.length == argumentNodes.size()) { 435 return typeArguments[index]; 436 } 437 return null; 438 } 439 case ASTNode.WILDCARD_TYPE: { 440 ITypeBinding parentBinding= getPossibleTypeBinding(parent); 441 if (parentBinding == null || !parentBinding.isWildcardType()) { 442 return null; 443 } 444 WildcardType wildcardType= (WildcardType) parent; 445 if (parentBinding.isUpperbound() == wildcardType.isUpperBound()) { 446 return parentBinding.getBound(); 447 } 448 return null; 449 } 450 case ASTNode.QUALIFIED_TYPE: { 451 ITypeBinding parentBinding= getPossibleTypeBinding(parent); 452 if (parentBinding == null || !parentBinding.isMember()) { 453 return null; 454 } 455 if (node.getLocationInParent() == QualifiedType.QUALIFIER_PROPERTY) { 456 return parentBinding.getDeclaringClass(); 457 } 458 return parentBinding; 459 } 460 case ASTNode.VARIABLE_DECLARATION_STATEMENT: 461 return guessVariableType(((VariableDeclarationStatement) parent).fragments()); 462 case ASTNode.FIELD_DECLARATION: 463 return guessVariableType(((FieldDeclaration) parent).fragments()); 464 case ASTNode.VARIABLE_DECLARATION_EXPRESSION: 465 return guessVariableType(((VariableDeclarationExpression) parent).fragments()); 466 case ASTNode.SINGLE_VARIABLE_DECLARATION: 467 SingleVariableDeclaration varDecl= (SingleVariableDeclaration) parent; 468 if (varDecl.getInitializer() != null) { 469 return Bindings.normalizeTypeBinding(varDecl.getInitializer().resolveTypeBinding()); 470 } 471 break; 472 case ASTNode.ARRAY_CREATION: 473 ArrayCreation creation= (ArrayCreation) parent; 474 if (creation.getInitializer() != null) { 475 return creation.getInitializer().resolveTypeBinding(); 476 } 477 return getPossibleReferenceBinding(parent); 478 case ASTNode.TYPE_LITERAL: 479 return ((TypeLiteral) parent).getType().resolveBinding(); 480 case ASTNode.CLASS_INSTANCE_CREATION: 481 return getPossibleReferenceBinding(parent); 482 case ASTNode.CAST_EXPRESSION: 483 return getPossibleReferenceBinding(parent); 484 case ASTNode.TAG_ELEMENT: 485 TagElement tagElement= (TagElement) parent; 486 if (TagElement.TAG_THROWS.equals(tagElement.getTagName()) || TagElement.TAG_EXCEPTION.equals(tagElement.getTagName())) { 487 ASTNode methNode= tagElement.getParent().getParent(); 488 if (methNode instanceof MethodDeclaration) { 489 List thrownExcpetions= ((MethodDeclaration) methNode).thrownExceptions(); 490 if (thrownExcpetions.size() == 1) { 491 return ((Name) thrownExcpetions.get(0)).resolveTypeBinding(); 492 } 493 } 494 } 495 break; 496 } 497 return null; 498 } 499 500 private static ITypeBinding guessVariableType(List fragments) { 501 for (Iterator iter= fragments.iterator(); iter.hasNext();) { 502 VariableDeclarationFragment frag= (VariableDeclarationFragment) iter.next(); 503 if (frag.getInitializer() != null) { 504 return Bindings.normalizeTypeBinding(frag.getInitializer().resolveTypeBinding()); 505 } 506 } 507 return null; 508 } 509 510 518 public static ITypeBinding[] getQualifierGuess(ASTNode searchRoot, final String selector, List arguments, final IBinding context) { 519 final int nArgs= arguments.size(); 520 final ArrayList result= new ArrayList (); 521 522 ITypeBinding binding= searchRoot.getAST().resolveWellKnownType("java.lang.Object"); IMethodBinding[] objectMethods= binding.getDeclaredMethods(); 525 for (int i= 0; i < objectMethods.length; i++) { 526 IMethodBinding meth= objectMethods[i]; 527 if (meth.getName().equals(selector) && meth.getParameterTypes().length == nArgs) { 528 return new ITypeBinding[] { binding }; 529 } 530 } 531 532 visitAllBindings(searchRoot, new TypeBindingVisitor() { 533 private HashSet fVisitedBindings= new HashSet (100); 534 535 public boolean visit(ITypeBinding node) { 536 node= Bindings.normalizeTypeBinding(node); 537 if (node == null) { 538 return true; 539 } 540 541 if (!fVisitedBindings.add(node.getKey())) { 542 return true; 543 } 544 if (node.isGenericType()) { 545 return true; } 547 if (context != null && !isUseableTypeInContext(node, context, false)) { 548 return true; 549 } 550 551 IMethodBinding[] methods= node.getDeclaredMethods(); 552 for (int i= 0; i < methods.length; i++) { 553 IMethodBinding meth= methods[i]; 554 if (meth.getName().equals(selector) && meth.getParameterTypes().length == nArgs) { 555 result.add(node); 556 } 557 } 558 return true; 559 } 560 }); 561 return (ITypeBinding[]) result.toArray(new ITypeBinding[result.size()]); 562 } 563 564 public static void visitAllBindings(ASTNode astRoot, TypeBindingVisitor visitor) { 565 try { 566 astRoot.accept(new AllBindingsVisitor(visitor)); 567 } catch (AllBindingsVisitor.VisitCancelledException e) { 568 } 569 } 570 571 private static class AllBindingsVisitor extends GenericVisitor { 572 private final TypeBindingVisitor fVisitor; 573 574 private static class VisitCancelledException extends RuntimeException { 575 private static final long serialVersionUID= 1L; 576 } 577 public AllBindingsVisitor(TypeBindingVisitor visitor) { 578 super(true); 579 fVisitor= visitor; 580 } 581 public boolean visit(SimpleName node) { 582 ITypeBinding binding= node.resolveTypeBinding(); 583 if (binding != null) { 584 boolean res= fVisitor.visit(binding); 585 if (res) { 586 res= Bindings.visitHierarchy(binding, fVisitor); 587 } 588 if (!res) { 589 throw new VisitCancelledException(); 590 } 591 } 592 return false; 593 } 594 } 595 596 597 public static IBinding getParentMethodOrTypeBinding(ASTNode node) { 598 do { 599 if (node instanceof MethodDeclaration) { 600 return ((MethodDeclaration) node).resolveBinding(); 601 } else if (node instanceof AbstractTypeDeclaration) { 602 return ((AbstractTypeDeclaration) node).resolveBinding(); 603 } else if (node instanceof AnonymousClassDeclaration) { 604 return ((AnonymousClassDeclaration) node).resolveBinding(); 605 } 606 node= node.getParent(); 607 } while (node != null); 608 609 return null; 610 } 611 612 public static BodyDeclaration findParentBodyDeclaration(ASTNode node) { 613 while ((node != null) && (!(node instanceof BodyDeclaration))) { 614 node= node.getParent(); 615 } 616 return (BodyDeclaration) node; 617 } 618 619 public static BodyDeclaration findParentBodyDeclaration(ASTNode node, boolean treatModifiersOutside) { 620 StructuralPropertyDescriptor lastLocation= null; 621 622 while (node != null) { 623 if (node instanceof BodyDeclaration) { 624 BodyDeclaration decl= (BodyDeclaration) node; 625 if (!treatModifiersOutside || lastLocation != decl.getModifiersProperty()) { 626 return decl; 627 } 628 treatModifiersOutside= false; 629 } 630 lastLocation= node.getLocationInParent(); 631 node= node.getParent(); 632 } 633 return (BodyDeclaration) node; 634 } 635 636 637 public static CompilationUnit findParentCompilationUnit(ASTNode node) { 638 return (CompilationUnit) findAncestor(node, ASTNode.COMPILATION_UNIT); 639 } 640 641 648 public static ASTNode findParentType(ASTNode node, boolean treatModifiersOutside) { 649 StructuralPropertyDescriptor lastLocation= null; 650 651 while (node != null) { 652 if (node instanceof AbstractTypeDeclaration) { 653 AbstractTypeDeclaration decl= (AbstractTypeDeclaration) node; 654 if (!treatModifiersOutside || lastLocation != decl.getModifiersProperty()) { 655 return decl; 656 } 657 } else if (node instanceof AnonymousClassDeclaration) { 658 return node; 659 } 660 lastLocation= node.getLocationInParent(); 661 node= node.getParent(); 662 } 663 return null; 664 } 665 666 public static ASTNode findParentType(ASTNode node) { 667 return findParentType(node, false); 668 } 669 670 676 public static MethodDeclaration findParentMethodDeclaration(ASTNode node) { 677 while (node != null) { 678 if (node.getNodeType() == ASTNode.METHOD_DECLARATION) { 679 return (MethodDeclaration) node; 680 } 681 if (node instanceof AbstractTypeDeclaration || node instanceof AnonymousClassDeclaration) { 682 return null; 683 } 684 node= node.getParent(); 685 } 686 return null; 687 } 688 689 public static ASTNode findAncestor(ASTNode node, int nodeType) { 690 while ((node != null) && (node.getNodeType() != nodeType)) { 691 node= node.getParent(); 692 } 693 return node; 694 } 695 696 public static Statement findParentStatement(ASTNode node) { 697 while ((node != null) && (!(node instanceof Statement))) { 698 node= node.getParent(); 699 if (node instanceof BodyDeclaration) { 700 return null; 701 } 702 } 703 return (Statement) node; 704 } 705 706 public static TryStatement findParentTryStatement(ASTNode node) { 707 while ((node != null) && (!(node instanceof TryStatement))) { 708 node= node.getParent(); 709 if (node instanceof BodyDeclaration) { 710 return null; 711 } 712 } 713 return (TryStatement) node; 714 } 715 716 public static boolean isInsideConstructorInvocation(MethodDeclaration methodDeclaration, ASTNode node) { 717 if (methodDeclaration.isConstructor()) { 718 Statement statement= ASTResolving.findParentStatement(node); 719 if (statement instanceof ConstructorInvocation || statement instanceof SuperConstructorInvocation) { 720 return true; } 722 } 723 return false; 724 } 725 726 public static boolean isInsideModifiers(ASTNode node) { 727 while (node != null && !(node instanceof BodyDeclaration)) { 728 if (node instanceof Annotation) { 729 return true; 730 } 731 node= node.getParent(); 732 } 733 return false; 734 } 735 736 public static boolean isInStaticContext(ASTNode selectedNode) { 737 BodyDeclaration decl= ASTResolving.findParentBodyDeclaration(selectedNode); 738 if (decl instanceof MethodDeclaration) { 739 if (isInsideConstructorInvocation((MethodDeclaration) decl, selectedNode)) { 740 return true; 741 } 742 return Modifier.isStatic(decl.getModifiers()); 743 } else if (decl instanceof Initializer) { 744 return Modifier.isStatic(((Initializer)decl).getModifiers()); 745 } else if (decl instanceof FieldDeclaration) { 746 return Modifier.isStatic(((FieldDeclaration)decl).getModifiers()); 747 } 748 return false; 749 } 750 751 public static boolean isWriteAccess(Name selectedNode) { 752 ASTNode curr= selectedNode; 753 ASTNode parent= curr.getParent(); 754 while (parent != null) { 755 switch (parent.getNodeType()) { 756 case ASTNode.QUALIFIED_NAME: 757 if (((QualifiedName) parent).getQualifier() == curr) { 758 return false; 759 } 760 break; 761 case ASTNode.FIELD_ACCESS: 762 if (((FieldAccess) parent).getExpression() == curr) { 763 return false; 764 } 765 break; 766 case ASTNode.SUPER_FIELD_ACCESS: 767 break; 768 case ASTNode.ASSIGNMENT: 769 return ((Assignment) parent).getLeftHandSide() == curr; 770 case ASTNode.VARIABLE_DECLARATION_FRAGMENT: 771 case ASTNode.SINGLE_VARIABLE_DECLARATION: 772 return ((VariableDeclaration) parent).getName() == curr; 773 case ASTNode.POSTFIX_EXPRESSION: 774 case ASTNode.PREFIX_EXPRESSION: 775 return true; 776 default: 777 return false; 778 } 779 780 curr= parent; 781 parent= curr.getParent(); 782 } 783 return false; 784 } 785 786 public static int getPossibleTypeKinds(ASTNode node, boolean is50OrHigher) { 787 int kinds= internalGetPossibleTypeKinds(node); 788 if (!is50OrHigher) { 789 kinds &= (SimilarElementsRequestor.INTERFACES | SimilarElementsRequestor.CLASSES); 790 } 791 return kinds; 792 } 793 794 795 private static int internalGetPossibleTypeKinds(ASTNode node) { 796 int kind= SimilarElementsRequestor.ALL_TYPES; 797 798 int mask= SimilarElementsRequestor.ALL_TYPES | SimilarElementsRequestor.VOIDTYPE; 799 800 ASTNode parent= node.getParent(); 801 while (parent instanceof QualifiedName) { 802 if (node.getLocationInParent() == QualifiedName.QUALIFIER_PROPERTY) { 803 return SimilarElementsRequestor.REF_TYPES; 804 } 805 node= parent; 806 parent= parent.getParent(); 807 mask= SimilarElementsRequestor.REF_TYPES; 808 } 809 while (parent instanceof Type) { 810 if (parent instanceof QualifiedType) { 811 if (node.getLocationInParent() == QualifiedType.QUALIFIER_PROPERTY) { 812 return mask & (SimilarElementsRequestor.REF_TYPES); 813 } 814 mask&= SimilarElementsRequestor.REF_TYPES; 815 } else if (parent instanceof ParameterizedType) { 816 if (node.getLocationInParent() == ParameterizedType.TYPE_ARGUMENTS_PROPERTY) { 817 return mask & SimilarElementsRequestor.REF_TYPES_AND_VAR; 818 } 819 mask&= SimilarElementsRequestor.CLASSES | SimilarElementsRequestor.INTERFACES; 820 } else if (parent instanceof WildcardType) { 821 if (node.getLocationInParent() == WildcardType.BOUND_PROPERTY) { 822 return mask & SimilarElementsRequestor.REF_TYPES_AND_VAR; 823 } 824 } 825 node= parent; 826 parent= parent.getParent(); 827 } 828 829 switch (parent.getNodeType()) { 830 case ASTNode.TYPE_DECLARATION: 831 if (node.getLocationInParent() == TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY) { 832 kind= SimilarElementsRequestor.INTERFACES; 833 } else if (node.getLocationInParent() == TypeDeclaration.SUPERCLASS_TYPE_PROPERTY) { 834 kind= SimilarElementsRequestor.CLASSES; 835 } 836 break; 837 case ASTNode.ENUM_DECLARATION: 838 kind= SimilarElementsRequestor.INTERFACES; 839 break; 840 case ASTNode.METHOD_DECLARATION: 841 if (node.getLocationInParent() == MethodDeclaration.THROWN_EXCEPTIONS_PROPERTY) { 842 kind= SimilarElementsRequestor.CLASSES; 843 } else if (node.getLocationInParent() == MethodDeclaration.RETURN_TYPE2_PROPERTY) { 844 kind= SimilarElementsRequestor.ALL_TYPES | SimilarElementsRequestor.VOIDTYPE; 845 } 846 break; 847 case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION: 848 kind= SimilarElementsRequestor.PRIMITIVETYPES | SimilarElementsRequestor.ANNOTATIONS | SimilarElementsRequestor.ENUMS; 849 break; 850 case ASTNode.INSTANCEOF_EXPRESSION: 851 kind= SimilarElementsRequestor.REF_TYPES; 852 break; 853 case ASTNode.THROW_STATEMENT: 854 kind= SimilarElementsRequestor.CLASSES; 855 break; 856 case ASTNode.CLASS_INSTANCE_CREATION: 857 if (((ClassInstanceCreation) parent).getAnonymousClassDeclaration() == null) { 858 kind= SimilarElementsRequestor.CLASSES; 859 } else { 860 kind= SimilarElementsRequestor.CLASSES | SimilarElementsRequestor.INTERFACES; 861 } 862 break; 863 case ASTNode.SINGLE_VARIABLE_DECLARATION: 864 int superParent= parent.getParent().getNodeType(); 865 if (superParent == ASTNode.CATCH_CLAUSE) { 866 kind= SimilarElementsRequestor.CLASSES; 867 } 868 break; 869 case ASTNode.TAG_ELEMENT: 870 kind= SimilarElementsRequestor.REF_TYPES; 871 break; 872 case ASTNode.MARKER_ANNOTATION: 873 case ASTNode.SINGLE_MEMBER_ANNOTATION: 874 case ASTNode.NORMAL_ANNOTATION: 875 kind= SimilarElementsRequestor.ANNOTATIONS; 876 break; 877 case ASTNode.TYPE_PARAMETER: 878 if (((TypeParameter) parent).typeBounds().indexOf(node) > 0) { 879 kind= SimilarElementsRequestor.INTERFACES; 880 } else { 881 kind= SimilarElementsRequestor.REF_TYPES_AND_VAR; 882 } 883 break; 884 case ASTNode.TYPE_LITERAL: 885 kind= SimilarElementsRequestor.REF_TYPES; 886 break; 887 default: 888 } 889 return kind & mask; 890 } 891 892 public static String getFullName(Name name) { 893 return name.getFullyQualifiedName(); 894 } 895 896 public static ICompilationUnit findCompilationUnitForBinding(ICompilationUnit cu, CompilationUnit astRoot, ITypeBinding binding) throws JavaModelException { 897 if (binding == null || !binding.isFromSource() || binding.isTypeVariable() || binding.isWildcardType()) { 898 return null; 899 } 900 ASTNode node= astRoot.findDeclaringNode(binding.getTypeDeclaration()); 901 if (node == null) { 902 ICompilationUnit targetCU= Bindings.findCompilationUnit(binding, cu.getJavaProject()); 903 if (targetCU != null) { 904 return targetCU; 905 } 906 return null; 907 } else if (node instanceof AbstractTypeDeclaration || node instanceof AnonymousClassDeclaration) { 908 return cu; 909 } 910 return null; 911 } 912 913 914 private static final Code[] CODE_ORDER= { PrimitiveType.CHAR, PrimitiveType.SHORT, PrimitiveType.INT, PrimitiveType.LONG, PrimitiveType.FLOAT, PrimitiveType.DOUBLE }; 915 916 public static ITypeBinding[] getNarrowingTypes(AST ast, ITypeBinding type) { 917 ArrayList res= new ArrayList (); 918 res.add(type); 919 if (type.isPrimitive()) { 920 Code code= PrimitiveType.toCode(type.getName()); 921 for (int i= 0; i < CODE_ORDER.length && code != CODE_ORDER[i]; i++) { 922 String typeName= CODE_ORDER[i].toString(); 923 res.add(ast.resolveWellKnownType(typeName)); 924 } 925 } 926 return (ITypeBinding[]) res.toArray(new ITypeBinding[res.size()]); 927 } 928 929 public static ITypeBinding[] getRelaxingTypes(AST ast, ITypeBinding type) { 930 ArrayList res= new ArrayList (); 931 res.add(type); 932 if (type.isArray()) { 933 res.add(ast.resolveWellKnownType("java.lang.Object")); res.add(ast.resolveWellKnownType("java.io.Serializable")); res.add(ast.resolveWellKnownType("java.lang.Cloneable")); } else if (type.isPrimitive()) { 937 Code code= PrimitiveType.toCode(type.getName()); 938 boolean found= false; 939 for (int i= 0; i < CODE_ORDER.length; i++) { 940 if (found) { 941 String typeName= CODE_ORDER[i].toString(); 942 res.add(ast.resolveWellKnownType(typeName)); 943 } 944 if (code == CODE_ORDER[i]) { 945 found= true; 946 } 947 } 948 } else { 949 collectRelaxingTypes(res, type); 950 } 951 return (ITypeBinding[]) res.toArray(new ITypeBinding[res.size()]); 952 } 953 954 private static void collectRelaxingTypes(Collection res, ITypeBinding type) { 955 ITypeBinding[] interfaces= type.getInterfaces(); 956 for (int i= 0; i < interfaces.length; i++) { 957 ITypeBinding curr= interfaces[i]; 958 if (!res.contains(curr)) { 959 res.add(curr); 960 } 961 collectRelaxingTypes(res, curr); 962 } 963 ITypeBinding binding= type.getSuperclass(); 964 if (binding != null) { 965 if (!res.contains(binding)) { 966 res.add(binding); 967 } 968 collectRelaxingTypes(res, binding); 969 } 970 } 971 972 public static String [] getUsedVariableNames(ASTNode node) { 973 CompilationUnit root= (CompilationUnit) node.getRoot(); 974 Collection res= (new ScopeAnalyzer(root)).getUsedVariableNames(node.getStartPosition(), node.getLength()); 975 return (String []) res.toArray(new String [res.size()]); 976 } 977 978 private static boolean isVariableDefinedInContext(IBinding binding, ITypeBinding typeVariable) { 979 if (binding.getKind() == IBinding.VARIABLE) { 980 IVariableBinding var= (IVariableBinding) binding; 981 binding= var.getDeclaringMethod(); 982 if (binding == null) { 983 binding= var.getDeclaringClass(); 984 } 985 } 986 if (binding instanceof IMethodBinding) { 987 if (binding == typeVariable.getDeclaringMethod()) { 988 return true; 989 } 990 binding= ((IMethodBinding) binding).getDeclaringClass(); 991 } 992 993 while (binding instanceof ITypeBinding) { 994 if (binding == typeVariable.getDeclaringClass()) { 995 return true; 996 } 997 if (Modifier.isStatic(binding.getModifiers())) { 998 break; 999 } 1000 binding= ((ITypeBinding) binding).getDeclaringClass(); 1001 } 1002 return false; 1003 } 1004 1005 public static boolean isUseableTypeInContext(ITypeBinding[] binding, IBinding context, boolean noWildcards) { 1006 for (int i= 0; i < binding.length; i++) { 1007 if (!isUseableTypeInContext(binding[i], context, noWildcards)) { 1008 return false; 1009 } 1010 } 1011 return true; 1012 } 1013 1014 1015 public static boolean isUseableTypeInContext(ITypeBinding type, IBinding context, boolean noWildcards) { 1016 if (type.isArray()) { 1017 type= type.getElementType(); 1018 } 1019 if (type.isAnonymous()) { 1020 return false; 1021 } 1022 if (type.isRawType() || type.isPrimitive()) { 1023 return true; 1024 } 1025 if (type.isTypeVariable()) { 1026 return isVariableDefinedInContext(context, type); 1027 } 1028 if (type.isGenericType()) { 1029 ITypeBinding[] typeParameters= type.getTypeParameters(); 1030 for (int i= 0; i < typeParameters.length; i++) { 1031 if (!isUseableTypeInContext(typeParameters[i], context, noWildcards)) { 1032 return false; 1033 } 1034 } 1035 return true; 1036 } 1037 if (type.isParameterizedType()) { 1038 ITypeBinding[] typeArguments= type.getTypeArguments(); 1039 for (int i= 0; i < typeArguments.length; i++) { 1040 if (!isUseableTypeInContext(typeArguments[i], context, noWildcards)) { 1041 return false; 1042 } 1043 } 1044 return true; 1045 } 1046 if (type.isCapture()) { 1047 type= type.getWildcard(); 1048 } 1049 1050 if (type.isWildcardType()) { 1051 if (noWildcards) { 1052 return false; 1053 } 1054 if (type.getBound() != null) { 1055 return isUseableTypeInContext(type.getBound(), context, noWildcards); 1056 } 1057 } 1058 return true; 1059 } 1060 1061 1069 public static ITypeBinding normalizeWildcardType(ITypeBinding wildcardType, boolean isBindingToAssign, AST ast) { 1070 ITypeBinding bound= wildcardType.getBound(); 1071 if (isBindingToAssign) { 1072 if (bound == null || !wildcardType.isUpperbound()) { 1073 return ast.resolveWellKnownType("java.lang.Object"); } 1075 } else { 1076 if (bound == null || wildcardType.isUpperbound()) { 1077 return null; 1078 } 1079 } 1080 return bound; 1081 } 1082 1083 1085 public static String getTypeSignature(ITypeBinding type) { 1086 return BindingLabelProvider.getBindingLabel(type, BindingLabelProvider.DEFAULT_TEXTFLAGS); 1087 } 1088 1089 public static String getMethodSignature(IMethodBinding binding, boolean inOtherCU) { 1090 StringBuffer buf= new StringBuffer (); 1091 if (inOtherCU && !binding.isConstructor()) { 1092 buf.append(binding.getDeclaringClass().getTypeDeclaration().getName()).append('.'); } 1094 return BindingLabelProvider.getBindingLabel(binding, BindingLabelProvider.DEFAULT_TEXTFLAGS); 1095 } 1096 1097 public static String getMethodSignature(String name, ITypeBinding[] params, boolean isVarArgs) { 1098 StringBuffer buf= new StringBuffer (); 1099 buf.append(name).append('('); 1100 for (int i= 0; i < params.length; i++) { 1101 if (i > 0) { 1102 buf.append(JavaElementLabels.COMMA_STRING); 1103 } 1104 if (isVarArgs && i == params.length - 1) { 1105 buf.append(getTypeSignature(params[i].getElementType())); 1106 buf.append("..."); } else { 1108 buf.append(getTypeSignature(params[i])); 1109 } 1110 } 1111 buf.append(')'); 1112 return buf.toString(); 1113 } 1114 1115 public static CompilationUnit createQuickFixAST(ICompilationUnit compilationUnit, IProgressMonitor monitor) { 1116 ASTParser astParser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL); 1117 astParser.setSource(compilationUnit); 1118 astParser.setResolveBindings(true); 1119 astParser.setStatementsRecovery(ASTProvider.SHARED_AST_STATEMENT_RECOVERY); 1120 astParser.setBindingsRecovery(ASTProvider.SHARED_BINDING_RECOVERY); 1121 return (CompilationUnit) astParser.createAST(monitor); 1122 } 1123 1124} 1125 | Popular Tags |