1 14 package org.eclipse.jdt.internal.corext.dom; 15 16 import java.util.ArrayList ; 17 import java.util.HashSet ; 18 import java.util.List ; 19 import java.util.Set ; 20 21 import org.eclipse.core.runtime.IPath; 22 import org.eclipse.core.runtime.Path; 23 import org.eclipse.core.runtime.Platform; 24 25 import org.eclipse.jdt.core.IClassFile; 26 import org.eclipse.jdt.core.ICompilationUnit; 27 import org.eclipse.jdt.core.IField; 28 import org.eclipse.jdt.core.IJavaElement; 29 import org.eclipse.jdt.core.IJavaProject; 30 import org.eclipse.jdt.core.IMethod; 31 import org.eclipse.jdt.core.IType; 32 import org.eclipse.jdt.core.JavaModelException; 33 import org.eclipse.jdt.core.Signature; 34 import org.eclipse.jdt.core.dom.AST; 35 import org.eclipse.jdt.core.dom.ASTNode; 36 import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; 37 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; 38 import org.eclipse.jdt.core.dom.Assignment; 39 import org.eclipse.jdt.core.dom.Expression; 40 import org.eclipse.jdt.core.dom.FieldAccess; 41 import org.eclipse.jdt.core.dom.IBinding; 42 import org.eclipse.jdt.core.dom.IMethodBinding; 43 import org.eclipse.jdt.core.dom.IPackageBinding; 44 import org.eclipse.jdt.core.dom.ITypeBinding; 45 import org.eclipse.jdt.core.dom.IVariableBinding; 46 import org.eclipse.jdt.core.dom.Modifier; 47 import org.eclipse.jdt.core.dom.QualifiedName; 48 import org.eclipse.jdt.core.dom.SimpleName; 49 import org.eclipse.jdt.core.dom.SuperFieldAccess; 50 51 import org.eclipse.jdt.internal.corext.Assert; 52 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 53 54 import org.eclipse.jdt.internal.ui.JavaPlugin; 55 56 public class Bindings { 57 58 public static final String ARRAY_LENGTH_FIELD_BINDING_STRING= "(array type):length"; private Bindings() { 60 } 62 63 private static final boolean CHECK_CORE_BINDING_IS_EQUAL_TO; 64 static { 65 String value= Platform.getDebugOption("org.eclipse.jdt.ui/debug/checkCoreBindingIsEqualTo"); CHECK_CORE_BINDING_IS_EQUAL_TO= value != null && value.equalsIgnoreCase("true"); } 68 private static final boolean CHECK_CORE_BINDING_GET_JAVA_ELEMENT; 69 static { 70 String value= Platform.getDebugOption("org.eclipse.jdt.ui/debug/checkCoreBindingGetJavaElement"); CHECK_CORE_BINDING_GET_JAVA_ELEMENT= value != null && value.equalsIgnoreCase("true"); } 73 private static final boolean USE_UI_BINDING_GET_JAVA_ELEMENT; 74 static { 75 String value= Platform.getDebugOption("org.eclipse.jdt.ui/debug/useUIBindingGetJavaElement"); USE_UI_BINDING_GET_JAVA_ELEMENT= value != null && value.equalsIgnoreCase("true"); } 78 79 87 public static boolean equals(IBinding b1, IBinding b2) { 88 boolean isEqualTo= b1.isEqualTo(b2); 89 if (CHECK_CORE_BINDING_IS_EQUAL_TO) { 90 boolean originalEquals= originalEquals(b1, b2); 91 if (originalEquals != isEqualTo) { 92 String message= "Unexpected difference between Bindings.equals(..) and IBinding#isEqualTo(..)"; String detail= "\nb1 == " + b1.getKey() + ",\nb2 == " + (b2 == null ? "null binding" : b2.getKey()); try { 95 detail+= "\nb1.getJavaElement() == " + b1.getJavaElement() + ",\nb2.getJavaElement() == " + (b2 == null ? "null binding" : b2.getJavaElement().toString()); } catch (Exception e) { 97 detail += "\nException in getJavaElement():\n" + e; } 99 JavaPlugin.logRepeatedMessage(message, detail); 100 } 101 } 102 return isEqualTo; 103 } 104 105 private static boolean originalEquals(IBinding b1, IBinding b2) { 106 Assert.isNotNull(b1); 107 if (b1 == b2) 108 return true; 109 if (b2 == null) 110 return false; 111 String k1= b1.getKey(); 112 String k2= b2.getKey(); 113 if (k1 == null || k2 == null) 114 return false; 115 return k1.equals(k2); 116 } 117 118 126 public static boolean equals(IBinding[] b1, IBinding[] b2) { 127 Assert.isNotNull(b1); 128 if (b1 == b2) 129 return true; 130 if (b2 == null) 131 return false; 132 if (b1.length != b2.length) 133 return false; 134 for (int i= 0; i < b1.length; i++) { 135 if (! Bindings.equals(b1[i], b2[i])) 136 return false; 137 } 138 return true; 139 } 140 141 public static int hashCode(IBinding binding){ 142 Assert.isNotNull(binding); 143 String key= binding.getKey(); 144 if (key == null) 145 return binding.hashCode(); 146 return key.hashCode(); 147 } 148 149 154 public static String asString(IBinding binding) { 155 if (binding instanceof IMethodBinding) 156 return asString((IMethodBinding)binding); 157 else if (binding instanceof ITypeBinding) 158 return asString((ITypeBinding)binding); 159 else if (binding instanceof IVariableBinding) 160 return asString((IVariableBinding)binding); 161 return binding.toString(); 162 } 163 164 private static String asString(IVariableBinding variableBinding) { 165 if (! variableBinding.isField()) 166 return variableBinding.toString(); 167 if (variableBinding.getDeclaringClass() == null) { 168 Assert.isTrue(variableBinding.getName().equals("length")); return ARRAY_LENGTH_FIELD_BINDING_STRING; 170 } 171 StringBuffer result= new StringBuffer (); 172 result.append(variableBinding.getDeclaringClass().getName()); 173 result.append(':'); 174 result.append(variableBinding.getName()); 175 return result.toString(); 176 } 177 178 private static String asString(ITypeBinding type) { 179 return type.getQualifiedName(); 180 } 181 182 private static String asString(IMethodBinding method) { 183 StringBuffer result= new StringBuffer (); 184 result.append(method.getDeclaringClass().getName()); 185 result.append(':'); 186 result.append(method.getName()); 187 result.append('('); 188 ITypeBinding[] parameters= method.getParameterTypes(); 189 int lastComma= parameters.length - 1; 190 for (int i= 0; i < parameters.length; i++) { 191 ITypeBinding parameter= parameters[i]; 192 result.append(parameter.getName()); 193 if (i < lastComma) 194 result.append(", "); } 196 result.append(')'); 197 return result.toString(); 198 } 199 200 public static String getTypeQualifiedName(ITypeBinding type) { 201 List result= new ArrayList (5); 202 createName(type, false, result); 203 204 StringBuffer buffer= new StringBuffer (); 205 for (int i= 0; i < result.size(); i++) { 206 if (i > 0) { 207 buffer.append('.'); 208 } 209 buffer.append(((String ) result.get(i))); 210 } 211 return buffer.toString(); 212 } 213 214 222 public static String getFullyQualifiedName(ITypeBinding type) { 223 224 226 String name= type.getQualifiedName(); 227 final int index= name.indexOf('<'); 228 if (index > 0) 229 name= name.substring(0, index); 230 return name; 231 } 232 233 public static String getImportName(IBinding binding) { 234 ITypeBinding declaring= null; 235 switch (binding.getKind()) { 236 case IBinding.TYPE: 237 return getRawQualifiedName((ITypeBinding) binding); 238 case IBinding.PACKAGE: 239 return binding.getName() + ".*"; case IBinding.METHOD: 241 declaring= ((IMethodBinding) binding).getDeclaringClass(); 242 break; 243 case IBinding.VARIABLE: 244 declaring= ((IVariableBinding) binding).getDeclaringClass(); 245 break; 246 default: 247 return binding.getName(); 248 } 249 return JavaModelUtil.concatenateName(getRawQualifiedName(declaring), binding.getName()); 250 } 251 252 253 private static void createName(ITypeBinding type, boolean includePackage, List list) { 254 ITypeBinding baseType= type; 255 if (type.isArray()) { 256 baseType= type.getElementType(); 257 } 258 if (!baseType.isPrimitive() && !baseType.isNullType()) { 259 ITypeBinding declaringType= baseType.getDeclaringClass(); 260 if (declaringType != null) { 261 createName(declaringType, includePackage, list); 262 } else if (includePackage && !baseType.getPackage().isUnnamed()) { 263 String [] components= baseType.getPackage().getNameComponents(); 264 for (int i= 0; i < components.length; i++) { 265 list.add(components[i]); 266 } 267 } 268 } 269 if (!baseType.isAnonymous()) { 270 list.add(type.getName()); 271 } else { 272 list.add("$local$"); } 274 } 275 276 277 public static String [] getNameComponents(ITypeBinding type) { 278 List result= new ArrayList (5); 279 createName(type, false, result); 280 return (String []) result.toArray(new String [result.size()]); 281 } 282 283 public static String [] getAllNameComponents(ITypeBinding type) { 284 List result= new ArrayList (5); 285 createName(type, true, result); 286 return (String []) result.toArray(new String [result.size()]); 287 } 288 289 public static ITypeBinding getTopLevelType(ITypeBinding type) { 290 ITypeBinding parent= type.getDeclaringClass(); 291 while (parent != null) { 292 type= parent; 293 parent= type.getDeclaringClass(); 294 } 295 return type; 296 } 297 298 306 public static boolean isRuntimeException(ITypeBinding thrownException) { 307 if (thrownException == null || thrownException.isPrimitive() || thrownException.isArray()) 308 return false; 309 return findTypeInHierarchy(thrownException, "java.lang.RuntimeException") != null; } 311 312 319 public static IVariableBinding findFieldInType(ITypeBinding type, String fieldName) { 320 if (type.isPrimitive()) 321 return null; 322 IVariableBinding[] fields= type.getDeclaredFields(); 323 for (int i= 0; i < fields.length; i++) { 324 IVariableBinding field= fields[i]; 325 if (field.getName().equals(fieldName)) 326 return field; 327 } 328 return null; 329 } 330 331 340 public static IMethodBinding findMethodInType(ITypeBinding type, String methodName, ITypeBinding[] parameters) { 341 if (type.isPrimitive()) 342 return null; 343 IMethodBinding[] methods= type.getDeclaredMethods(); 344 for (int i= 0; i < methods.length; i++) { 345 if (parameters == null) { 346 if (methodName.equals(methods[i].getName())) 347 return methods[i]; 348 } else { 349 if (isEqualMethod(methods[i], methodName, parameters)) 350 return methods[i]; 351 } 352 } 353 return null; 354 } 355 356 364 public static IMethodBinding findMethodInType(ITypeBinding type, String methodName, String [] parameters) { 365 if (type.isPrimitive()) 366 return null; 367 IMethodBinding[] methods= type.getDeclaredMethods(); 368 for (int i= 0; i < methods.length; i++) { 369 if (parameters == null) { 370 if (methodName.equals(methods[i].getName())) 371 return methods[i]; 372 } else { 373 if (isEqualMethod(methods[i], methodName, parameters)) 374 return methods[i]; 375 } 376 } 377 return null; 378 } 379 380 386 public static IMethodBinding findOverriddenMethodInType(ITypeBinding type, IMethodBinding method) { 387 return findMethodInType(type, method.getName(), method.getParameterTypes()); 388 } 398 399 408 public static IVariableBinding findFieldInHierarchy(ITypeBinding type, String fieldName) { 409 IVariableBinding field= findFieldInType(type, fieldName); 410 if (field != null) 411 return field; 412 ITypeBinding superClass= type.getSuperclass(); 413 if (superClass != null) { 414 field= findFieldInType(type, fieldName); 415 if (field != null) 416 return field; 417 } 418 ITypeBinding[] interfaces= type.getInterfaces(); 419 for (int i= 0; i < interfaces.length; i++) { 420 field= findFieldInType(type, fieldName); 421 if (field != null) return field; 423 } 424 return null; 425 } 426 427 428 438 public static IMethodBinding findMethodInHierarchy(ITypeBinding type, String methodName, ITypeBinding parameters[]) { 439 IMethodBinding method= findMethodInType(type, methodName, parameters); 440 if (method != null) 441 return method; 442 ITypeBinding superClass= type.getSuperclass(); 443 if (superClass != null) { 444 method= findMethodInHierarchy(superClass, methodName, parameters); 445 if (method != null) 446 return method; 447 } 448 ITypeBinding[] interfaces= type.getInterfaces(); 449 for (int i= 0; i < interfaces.length; i++) { 450 method= findMethodInHierarchy(interfaces[i], methodName, parameters); 451 if (method != null) 452 return method; 453 } 454 return null; 455 } 456 457 458 469 public static IMethodBinding findMethodInHierarchy(ITypeBinding typeObject, ITypeBinding type, String methodName, String parameters[]) { 470 IMethodBinding method= findMethodInType(type, methodName, parameters); 471 if (method != null) 472 return method; 473 ITypeBinding superClass= type.getSuperclass(); 474 if (superClass == null && type.isInterface()) 475 superClass= typeObject; 476 if (superClass != null) { 477 method= findMethodInHierarchy(typeObject, superClass, methodName, parameters); 478 if (method != null) 479 return method; 480 } 481 ITypeBinding[] interfaces= type.getInterfaces(); 482 for (int i= 0; i < interfaces.length; i++) { 483 method= findMethodInHierarchy(typeObject, interfaces[i], methodName, parameters); 484 if (method != null) 485 return method; 486 } 487 return null; 488 } 489 490 498 public static IMethodBinding findOverriddenMethodInHierarchy(ITypeBinding type, IMethodBinding binding) { 499 IMethodBinding method= findOverriddenMethodInType(type, binding); 500 if (method != null) 501 return method; 502 ITypeBinding superClass= type.getSuperclass(); 503 if (superClass != null) { 504 method= findOverriddenMethodInHierarchy(superClass, binding); 505 if (method != null) 506 return method; 507 } 508 ITypeBinding[] interfaces= type.getInterfaces(); 509 for (int i= 0; i < interfaces.length; i++) { 510 method= findOverriddenMethodInHierarchy(interfaces[i], binding); 511 if (method != null) 512 return method; 513 } 514 return null; 515 } 516 517 518 524 public static IMethodBinding findMethodDefininition(IMethodBinding method, boolean testVisibility) { 525 int modifiers= method.getModifiers(); 526 if (Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || method.isConstructor()) { 527 return null; 528 } 529 530 ITypeBinding type= method.getDeclaringClass(); 531 if (type.isInterface()) { 532 return null; 533 } 534 535 if (type.getSuperclass() != null) { 536 IMethodBinding res= findOverriddenMethodInHierarchy(type.getSuperclass(), method); 537 if (res != null && !Modifier.isPrivate(res.getModifiers())) { 538 if (!testVisibility || isVisibleInHierarchy(res, method.getDeclaringClass().getPackage())) { 539 return res; 540 } 541 } 542 } 543 ITypeBinding[] interfaces= type.getInterfaces(); 544 for (int i= 0; i < interfaces.length; i++) { 545 IMethodBinding res= findOverriddenMethodInHierarchy(interfaces[i], method); 546 if (res != null) { 547 return res; } 549 } 550 return null; 551 } 552 553 559 public static IMethodBinding findMethodImplementation(IMethodBinding method, boolean testVisibility) { 560 ITypeBinding superClass= method.getDeclaringClass().getSuperclass(); 561 562 String methodName= method.getName(); 563 ITypeBinding[] parameters= method.getParameterTypes(); 564 while (superClass != null) { 565 IMethodBinding res= findMethodInType(superClass, methodName, parameters); 566 if (res != null) { 567 if (isVisibleInHierarchy(res, method.getDeclaringClass().getPackage())) { 568 return res; 569 } 570 return null; 571 } 572 superClass= superClass.getSuperclass(); 573 } 574 return null; 575 } 576 577 public static boolean isVisibleInHierarchy(IMethodBinding member, IPackageBinding pack) { 578 int otherflags= member.getModifiers(); 579 ITypeBinding declaringType= member.getDeclaringClass(); 580 if (Modifier.isPublic(otherflags) || Modifier.isProtected(otherflags) || (declaringType != null && declaringType.isInterface())) { 581 return true; 582 } else if (Modifier.isPrivate(otherflags)) { 583 return false; 584 } 585 return pack == declaringType.getPackage(); 586 } 587 588 598 public static IMethodBinding findDeclarationInHierarchy(ITypeBinding type, String methodName, ITypeBinding[] parameters) { 599 ITypeBinding[] interfaces= type.getInterfaces(); 600 for (int i= 0; i < interfaces.length; i++) { 601 ITypeBinding curr= interfaces[i]; 602 IMethodBinding method= findMethodInType(curr, methodName, parameters); 603 if (method != null) 604 return method; 605 method= findDeclarationInHierarchy(interfaces[i], methodName, parameters); 606 if (method != null) 607 return method; 608 } 609 ITypeBinding superClass= type.getSuperclass(); 610 if (superClass != null) { 611 IMethodBinding method= findMethodInType(superClass, methodName, parameters); 612 if (method != null) 613 return method; 614 615 method= findDeclarationInHierarchy(superClass, methodName, parameters); 616 if (method != null) 617 return method; 618 } 619 return null; 620 } 621 622 627 public static ITypeBinding[] getAllSuperTypes(ITypeBinding type) { 628 Set result= new HashSet (); 629 collectSuperTypes(type, result); 630 result.remove(type); 631 return (ITypeBinding[]) result.toArray(new ITypeBinding[result.size()]); 632 } 633 634 private static void collectSuperTypes(ITypeBinding curr, Set collection) { 635 if (collection.add(curr)) { 636 ITypeBinding[] interfaces= curr.getInterfaces(); 637 for (int i= 0; i < interfaces.length; i++) { 638 collectSuperTypes(interfaces[i], collection); 639 } 640 ITypeBinding superClass= curr.getSuperclass(); 641 if (superClass != null) { 642 collectSuperTypes(superClass, collection); 643 } 644 } 645 } 646 647 654 public static boolean visitHierarchy(ITypeBinding type, TypeBindingVisitor visitor) { 655 boolean result= visitSuperclasses(type, visitor); 656 if(result) { 657 result= visitInterfaces(type, visitor); 658 } 659 return result; 660 } 661 662 669 public static boolean visitInterfaces(ITypeBinding type, TypeBindingVisitor visitor) { 670 ITypeBinding[] interfaces= type.getInterfaces(); 671 for (int i= 0; i < interfaces.length; i++) { 672 if (!visitor.visit(interfaces[i])) { 673 return false; 674 } 675 } 676 return true; 677 } 678 679 686 public static boolean visitSuperclasses(ITypeBinding type, TypeBindingVisitor visitor) { 687 while ((type= type.getSuperclass()) != null) { 688 if (!visitor.visit(type)) { 689 return false; 690 } 691 } 692 return true; 693 } 694 695 public static boolean isEqualMethod(IMethodBinding method, String methodName, ITypeBinding[] parameters) { 696 if (!method.getName().equals(methodName)) 697 return false; 698 699 ITypeBinding[] methodParameters= method.getParameterTypes(); 700 if (methodParameters.length != parameters.length) 701 return false; 702 for (int i= 0; i < parameters.length; i++) { 703 if (!equals(methodParameters[i].getErasure(), parameters[i].getErasure())) 704 return false; 705 } 706 return true; 707 } 708 709 public static boolean isEqualMethod(IMethodBinding method, String methodName, String [] parameters) { 710 if (!method.getName().equals(methodName)) 711 return false; 712 713 ITypeBinding[] methodParameters= method.getParameterTypes(); 714 if (methodParameters.length != parameters.length) 715 return false; 716 String first, second; 717 int index; 718 for (int i= 0; i < parameters.length; i++) { 719 first= parameters[i]; 720 index= first.indexOf('<'); 721 if (index > 0) 722 first= first.substring(0, index); 723 second= methodParameters[i].getErasure().getQualifiedName(); 724 index= second.indexOf('<'); 725 if (index > 0) 726 second= second.substring(0, index); 727 if (!first.equals(second)) 728 return false; 729 } 730 return true; 731 } 732 733 740 public static ITypeBinding findTypeInHierarchy(ITypeBinding hierarchyType, String fullyQualifiedTypeName) { 741 if (hierarchyType.isArray() || hierarchyType.isPrimitive()) { 742 return null; 743 } 744 if (fullyQualifiedTypeName.equals(hierarchyType.getQualifiedName())) { 745 return hierarchyType; 746 } 747 ITypeBinding superClass= hierarchyType.getSuperclass(); 748 if (superClass != null) { 749 ITypeBinding res= findTypeInHierarchy(superClass, fullyQualifiedTypeName); 750 if (res != null) { 751 return res; 752 } 753 } 754 ITypeBinding[] superInterfaces= hierarchyType.getInterfaces(); 755 for (int i= 0; i < superInterfaces.length; i++) { 756 ITypeBinding res= findTypeInHierarchy(superInterfaces[i], fullyQualifiedTypeName); 757 if (res != null) { 758 return res; 759 } 760 } 761 return null; 762 } 763 764 769 public static IVariableBinding getAssignedVariable(Assignment assignment) { 770 Expression leftHand = assignment.getLeftHandSide(); 771 switch (leftHand.getNodeType()) { 772 case ASTNode.SIMPLE_NAME: 773 return (IVariableBinding) ((SimpleName) leftHand).resolveBinding(); 774 case ASTNode.QUALIFIED_NAME: 775 return (IVariableBinding) ((QualifiedName) leftHand).getName().resolveBinding(); 776 case ASTNode.FIELD_ACCESS: 777 return ((FieldAccess) leftHand).resolveFieldBinding(); 778 case ASTNode.SUPER_FIELD_ACCESS: 779 return ((SuperFieldAccess) leftHand).resolveFieldBinding(); 780 default: 781 return null; 782 } 783 } 784 785 793 public static boolean isSuperType(ITypeBinding type, ITypeBinding candidate) { 794 if (candidate.isArray() || candidate.isPrimitive()) { 795 return false; 796 } 797 if (Bindings.equals(candidate, type)) { 798 return true; 799 } 800 ITypeBinding superClass= candidate.getSuperclass(); 801 if (superClass != null) { 802 if (isSuperType(type, superClass)) { 803 return true; 804 } 805 } 806 807 if (type.isInterface()) { 808 ITypeBinding[] superInterfaces= candidate.getInterfaces(); 809 for (int i= 0; i < superInterfaces.length; i++) { 810 if (isSuperType(type, superInterfaces[i])) { 811 return true; 812 } 813 } 814 } 815 return false; 816 } 817 818 819 821 830 public static ICompilationUnit findCompilationUnit(ITypeBinding typeBinding, IJavaProject project) throws JavaModelException { 831 ICompilationUnit coreFindCompilationUnit= coreFindCompilationUnit(typeBinding); 832 if (CHECK_CORE_BINDING_GET_JAVA_ELEMENT) { 833 ICompilationUnit originalFindCompilationUnit= originalFindCompilationUnit(typeBinding, project); 834 if (coreFindCompilationUnit == null) { 835 if (originalFindCompilationUnit != null) { 836 JavaPlugin.logRepeatedMessage("ITypeBinding#getJavaElement() is not supposed to be null: ", "typeBinding == " + typeBinding.getKey() + ", project == " + project.getElementName() + ", coreFindCompilationUnit == " + coreFindCompilationUnit + ", originalFindCompilationUnit == " + originalFindCompilationUnit); } 840 } else { 841 if (! coreFindCompilationUnit.equals(originalFindCompilationUnit)) { 842 JavaPlugin.logRepeatedMessage("ITypeBinding#getJavaElement() is not correct element: ", "typeBinding == " + typeBinding.getKey() + ", project == " + project.getElementName() + ", coreFindCompilationUnit == " + coreFindCompilationUnit + ", originalFindCompilationUnit == " + originalFindCompilationUnit); } 846 } 847 } 848 return coreFindCompilationUnit; 849 } 850 851 private static ICompilationUnit coreFindCompilationUnit(ITypeBinding typeBinding) { 852 IJavaElement type= typeBinding.getJavaElement(); 853 if (type instanceof IType) 854 return ((IType) type).getCompilationUnit(); 855 else 856 return null; 857 } 858 859 private static ICompilationUnit originalFindCompilationUnit(ITypeBinding typeBinding, IJavaProject project) throws JavaModelException { 860 if (!typeBinding.isFromSource()) { 861 return null; 862 } 863 while (typeBinding != null && !typeBinding.isTopLevel()) { 864 typeBinding= typeBinding.getDeclaringClass(); 865 } 866 if (typeBinding != null) { 867 typeBinding= typeBinding.getTypeDeclaration(); 868 IPackageBinding pack= typeBinding.getPackage(); 869 String packageName= pack.isUnnamed() ? "" : pack.getName(); IType type= project.findType(packageName, typeBinding.getName()); 871 if (type != null) { 872 return type.getCompilationUnit(); 873 } 874 } 875 return null; 876 } 877 878 887 public static IField findField(IVariableBinding field, IJavaProject in) throws JavaModelException { 888 Assert.isTrue(field.isField()); 889 IField iField= (IField) field.getJavaElement(); 890 if (CHECK_CORE_BINDING_GET_JAVA_ELEMENT) { 891 IField originalFindField= originalFindField(field, in); 892 if (iField != null && ! iField.equals(originalFindField) 893 || iField == null && originalFindField != null) { 894 JavaPlugin.logRepeatedMessage("IVariableBinding#getJavaElement() is not correct element: ", "field == " + field.getKey() + ", project == " + in.getElementName() + ", iField == " + iField + ", originalFindField == " + originalFindField); } 898 } 899 return iField; 900 } 901 902 private static IField originalFindField(IVariableBinding field, IJavaProject in) throws JavaModelException { 903 ITypeBinding declaringClassBinding = field.getDeclaringClass(); 904 if (declaringClassBinding == null) 905 return null; 906 IType declaringClass = findType(declaringClassBinding, in); 907 if (declaringClass == null) 908 return null; 909 IField foundField= declaringClass.getField(field.getName()); 910 if (! foundField.exists()) 911 return null; 912 return foundField; 913 } 914 915 924 public static IType findType(ITypeBinding type, IJavaProject scope) throws JavaModelException { 925 IType iType= (IType) type.getJavaElement(); 926 if (CHECK_CORE_BINDING_GET_JAVA_ELEMENT) { 927 IType originalFindType= originalFindType(type, scope); 928 if (iType != null && ! iType.equals(originalFindType) 929 || iType == null && originalFindType != null) { 930 JavaPlugin.logRepeatedMessage("ITypeBinding#getJavaElement() is not correct element: ", "type == " + type.getKey() + ", project == " + scope.getElementName() + ", iType == " + iType + ", originalFindType == " + originalFindType); } 934 } 935 return iType; 936 } 937 938 private static IType originalFindType(ITypeBinding type, IJavaProject scope) throws JavaModelException { 939 if (type.isPrimitive() || type.isAnonymous() || type.isNullType()) 940 return null; 941 if (type.isArray()) 942 return findType(type.getElementType(), scope); 943 944 946 String [] typeElements= Bindings.getNameComponents(type); 947 IJavaElement element= scope.findElement(getPathToCompilationUnit(type.getPackage(), typeElements[0])); 948 IType candidate= null; 949 if (element instanceof ICompilationUnit) { 950 candidate= ((ICompilationUnit)element).getType(typeElements[0]); 951 } else if (element instanceof IClassFile) { 952 candidate= ((IClassFile)element).getType(); 953 } else if (element == null) { 954 if (type.isMember()) 955 candidate= JavaModelUtil.findType(scope, Bindings.getFullyQualifiedName(type.getDeclaringClass())); 956 else 957 candidate= JavaModelUtil.findType(scope, Bindings.getFullyQualifiedName(type)); 958 } 959 960 if (candidate == null || typeElements.length == 1) 961 return candidate; 962 963 return findTypeInType(typeElements, candidate); 964 } 965 966 974 public static IMethod findMethod(IMethodBinding method, IJavaProject scope) throws JavaModelException { 975 if (! USE_UI_BINDING_GET_JAVA_ELEMENT) { 976 IMethod iMethod= (IMethod) method.getJavaElement(); 977 if (CHECK_CORE_BINDING_GET_JAVA_ELEMENT) { 978 IMethod originalFindMethod= originalFindMethod(method, scope); 979 if (iMethod != null && ! iMethod.equals(originalFindMethod) 980 || iMethod == null && originalFindMethod != null) { 981 JavaPlugin.logRepeatedMessage("IMethodBinding#getJavaElement() is not correct element: ", "method == " + method.getKey() + ", project == " + scope.getElementName() + ", iMethod == " + iMethod + ", originalFindMethod == " + originalFindMethod); } 985 } 986 return iMethod; 987 } 988 989 IMethod originalFindMethod= originalFindMethod(method, scope); 990 if (CHECK_CORE_BINDING_GET_JAVA_ELEMENT) { 991 IMethod iMethod= (IMethod) method.getJavaElement(); 992 if (iMethod != null && ! iMethod.equals(originalFindMethod) 993 || iMethod == null && originalFindMethod != null) { 994 JavaPlugin.logRepeatedMessage("IMethodBinding#getJavaElement() is not correct element: ", "method == " + method.getKey() + ", project == " + scope.getElementName() + ", iMethod == " + iMethod + ", originalFindMethod == " + originalFindMethod); } 998 } 999 return originalFindMethod; 1000 } 1001 1002 private static IMethod originalFindMethod(IMethodBinding method, IJavaProject scope) throws JavaModelException { 1003 IType type= findType(method.getDeclaringClass(), scope); 1004 if (type == null) 1005 return null; 1006 return findMethod(method, type); 1007 } 1008 1009 1017 public static IMethod findMethod(IMethodBinding method, IType type) throws JavaModelException { 1018 method= method.getMethodDeclaration(); 1019 1020 IMethod[] candidates= type.getMethods(); 1021 for (int i= 0; i < candidates.length; i++) { 1022 IMethod candidate= candidates[i]; 1023 if (candidate.getElementName().equals(method.getName()) && sameParameters(method, candidate)) { 1024 return candidate; 1025 } 1026 } 1027 return null; 1028 } 1029 1030 1032 private static IPath getPathToCompilationUnit(IPackageBinding packageBinding, String topLevelTypeName) { 1033 IPath result= Path.EMPTY; 1034 String [] packageNames= packageBinding.getNameComponents(); 1035 for (int i= 0; i < packageNames.length; i++) { 1036 result= result.append(packageNames[i]); 1037 } 1038 return result.append(topLevelTypeName + ".java"); } 1040 1041 private static IType findTypeInType(String [] typeElements, IType jmType) { 1042 IType result= jmType; 1043 for (int i= 1; i < typeElements.length; i++) { 1044 result= result.getType(typeElements[i]); 1045 if (!result.exists()) 1046 return null; 1047 } 1048 return result == jmType ? null : result; 1049 } 1050 1051 1053 private static boolean sameParameters(IMethodBinding method, IMethod candidate) throws JavaModelException { 1054 ITypeBinding[] methodParamters= method.getParameterTypes(); 1055 String [] candidateParameters= candidate.getParameterTypes(); 1056 if (methodParamters.length != candidateParameters.length) 1057 return false; 1058 IType scope= candidate.getDeclaringType(); 1059 for (int i= 0; i < methodParamters.length; i++) { 1060 ITypeBinding methodParameter= methodParamters[i]; 1061 String candidateParameter= candidateParameters[i]; 1062 if (!sameParameter(methodParameter, candidateParameter, scope)) 1063 return false; 1064 } 1065 return true; 1066 } 1067 1068 private static boolean sameParameter(ITypeBinding type, String candidate, IType scope) throws JavaModelException { 1069 if (type.getDimensions() != Signature.getArrayCount(candidate)) 1070 return false; 1071 1072 if (type.isArray()) 1074 type= type.getElementType(); 1075 candidate= Signature.getElementType(candidate); 1076 1077 if (isPrimitiveType(candidate) != type.isPrimitive()) { 1078 return false; 1079 } 1080 1081 if (type.isPrimitive() || type.isTypeVariable()) { 1082 return type.getName().equals(Signature.toString(candidate)); 1083 } else { 1084 candidate= Signature.getTypeErasure(candidate); 1086 type= type.getErasure(); 1087 1088 if (isResolvedType(candidate)) { 1089 return Signature.toString(candidate).equals(Bindings.getFullyQualifiedName(type)); 1090 } else { 1091 String [][] qualifiedCandidates= scope.resolveType(Signature.toString(candidate)); 1092 if (qualifiedCandidates == null || qualifiedCandidates.length == 0) 1093 return false; 1094 String packageName= type.getPackage().isUnnamed() ? "" : type.getPackage().getName(); String typeName= getTypeQualifiedName(type); 1096 for (int i= 0; i < qualifiedCandidates.length; i++) { 1097 String [] qualifiedCandidate= qualifiedCandidates[i]; 1098 if ( qualifiedCandidate[0].equals(packageName) && 1099 qualifiedCandidate[1].equals(typeName)) 1100 return true; 1101 } 1102 } 1103 } 1104 return false; 1105 } 1106 1107 private static boolean isPrimitiveType(String s) { 1108 return Signature.getTypeSignatureKind(s) == Signature.BASE_TYPE_SIGNATURE; 1109 } 1110 1111 private static boolean isResolvedType(String s) { 1112 int arrayCount= Signature.getArrayCount(s); 1113 return s.charAt(arrayCount) == Signature.C_RESOLVED; 1114 } 1115 1116 1123 public static ITypeBinding normalizeTypeBinding(ITypeBinding binding) { 1124 if (binding != null && !binding.isNullType() && !isVoidType(binding)) { 1125 if (binding.isAnonymous()) { 1126 ITypeBinding[] baseBindings= binding.getInterfaces(); 1127 if (baseBindings.length > 0) { 1128 return baseBindings[0]; 1129 } 1130 return binding.getSuperclass(); 1131 } 1132 if (binding.isCapture()) { 1133 return binding.getWildcard(); 1134 } 1135 return binding; 1136 } 1137 return null; 1138 } 1139 1140 public static boolean isVoidType(ITypeBinding binding) { 1141 return "void".equals(binding.getName()); } 1143 1144 1145 1152 public static ITypeBinding normalizeForDeclarationUse(ITypeBinding binding, AST ast) { 1153 if (binding.isNullType()) 1154 return ast.resolveWellKnownType("java.lang.Object"); if (binding.isPrimitive()) 1156 return binding; 1157 binding= normalizeTypeBinding(binding); 1158 if (binding == null || !binding.isWildcardType()) 1159 return binding; 1160 if (binding.isUpperbound()) { 1161 return binding.getBound(); 1162 } else { 1163 return ast.resolveWellKnownType("java.lang.Object"); } 1165 } 1166 1167 1172 public static ITypeBinding getBindingOfParentType(ASTNode node) { 1173 while (node != null) { 1174 if (node instanceof AbstractTypeDeclaration) { 1175 return ((AbstractTypeDeclaration) node).resolveBinding(); 1176 } else if (node instanceof AnonymousClassDeclaration) { 1177 return ((AnonymousClassDeclaration) node).resolveBinding(); 1178 } 1179 node= node.getParent(); 1180 } 1181 return null; 1182 } 1183 1184 1185 public static String getRawName(ITypeBinding binding) { 1186 String name= binding.getName(); 1187 if (binding.isParameterizedType() || binding.isGenericType()) { 1188 int idx= name.indexOf('<'); 1189 if (idx != -1) { 1190 return name.substring(0, idx); 1191 } 1192 } 1193 return name; 1194 } 1195 1196 1197 public static String getRawQualifiedName(ITypeBinding binding) { 1198 final String EMPTY= ""; 1200 if (binding.isAnonymous() || binding.isLocal()) { 1201 return EMPTY; } 1203 1204 if (binding.isPrimitive() || binding.isNullType() || binding.isTypeVariable()) { 1205 return binding.getName(); 1206 } 1207 1208 if (binding.isArray()) { 1209 String elementTypeQualifiedName = getRawQualifiedName(binding.getElementType()); 1210 if (elementTypeQualifiedName.length() != 0) { 1211 StringBuffer stringBuffer= new StringBuffer (elementTypeQualifiedName); 1212 stringBuffer.append('[').append(']'); 1213 return stringBuffer.toString(); 1214 } else { 1215 return EMPTY; 1216 } 1217 } 1218 if (binding.isMember()) { 1219 String outerName= getRawQualifiedName(binding.getDeclaringClass()); 1220 if (outerName.length() > 0) { 1221 StringBuffer buffer= new StringBuffer (); 1222 buffer.append(outerName); 1223 buffer.append('.'); 1224 buffer.append(getRawName(binding)); 1225 return buffer.toString(); 1226 } else { 1227 return EMPTY; 1228 } 1229 1230 } else if (binding.isTopLevel()) { 1231 IPackageBinding packageBinding= binding.getPackage(); 1232 StringBuffer buffer= new StringBuffer (); 1233 if (packageBinding != null && packageBinding.getName().length() > 0) { 1234 buffer.append(packageBinding.getName()).append('.'); 1235 } 1236 buffer.append(getRawName(binding)); 1237 return buffer.toString(); 1238 } 1239 return EMPTY; 1240 } 1241 1242 1243 1246 public static IVariableBinding getVariableDeclaration(IVariableBinding var) { 1247 ITypeBinding declaringClass= var.getDeclaringClass(); 1248 if (declaringClass == null) { 1249 return var; 1250 } 1251 if (declaringClass.getTypeDeclaration() == declaringClass) { return var; 1253 } 1254 IVariableBinding[] genericFields= declaringClass.getTypeDeclaration().getDeclaredFields(); 1255 String name= var.getName(); 1256 for (int i= 0; i < genericFields.length; i++) { 1257 if (name.equals(genericFields[i].getName())) { 1258 return genericFields[i]; 1259 } 1260 } 1261 Assert.isTrue(false, "field does not exist in generic type"); return var; 1263 } 1264 1265 1269 public static boolean isDeclarationBinding(IBinding binding) { 1270 switch (binding.getKind()) { 1271 case IBinding.TYPE: 1272 return ((ITypeBinding) binding).getTypeDeclaration() == binding; 1273 case IBinding.VARIABLE: 1274 IVariableBinding var= (IVariableBinding) binding; 1275 return !var.isField() || isDeclarationBinding(var.getDeclaringClass()); 1276 case IBinding.METHOD: 1277 return ((IMethodBinding) binding).getMethodDeclaration() == binding; 1278 } 1279 return true; 1280 } 1281 1282 public static boolean containsOverridingMethod(IMethodBinding[] candidates, IMethodBinding overridable) { 1283 for (int index= 0; index < candidates.length; index++) { 1284 if (areOverriddenMethods(candidates[index], overridable)) 1285 return true; 1286 } 1287 return false; 1288 } 1289 1290 public static boolean containsSignatureEquivalentConstructor(IMethodBinding[] candidates, IMethodBinding overridable) { 1291 for (int index= 0; index < candidates.length; index++) { 1292 if (isSignatureEquivalentConstructor(candidates[index], overridable)) 1293 return true; 1294 } 1295 return false; 1296 } 1297 1298 public static boolean isSignatureEquivalentConstructor(IMethodBinding overridden, IMethodBinding overridable) { 1299 1300 if (!overridden.isConstructor() || !overridable.isConstructor()) 1301 return false; 1302 1303 if (overridden.isDefaultConstructor()) 1304 return false; 1305 1306 return areSubTypeCompatible(overridden, overridable); 1307 } 1308 1309 public static boolean areOverriddenMethods(IMethodBinding overridden, IMethodBinding overridable) { 1310 1311 if (!overridden.getName().equals(overridable.getName())) 1312 return false; 1313 1314 return areSubTypeCompatible(overridden, overridable); 1315 } 1316 1317 private static boolean areSubTypeCompatible(IMethodBinding overridden, IMethodBinding overridable) { 1318 1319 if (overridden.getParameterTypes().length != overridable.getParameterTypes().length) 1320 return false; 1321 1322 ITypeBinding overriddenReturn= overridden.getReturnType(); 1323 ITypeBinding overridableReturn= overridable.getReturnType(); 1324 if (overriddenReturn == null || overridableReturn == null) 1325 return false; 1326 1327 if (!overriddenReturn.getErasure().isSubTypeCompatible(overridableReturn.getErasure())) 1328 return false; 1329 1330 ITypeBinding[] overriddenTypes= overridden.getParameterTypes(); 1331 ITypeBinding[] overridableTypes= overridable.getParameterTypes(); 1332 Assert.isTrue(overriddenTypes.length == overridableTypes.length); 1333 for (int index= 0; index < overriddenTypes.length; index++) { 1334 final ITypeBinding overridableErasure= overridableTypes[index].getErasure(); 1335 final ITypeBinding overriddenErasure= overriddenTypes[index].getErasure(); 1336 if (!overridableErasure.isSubTypeCompatible(overriddenErasure) || !overridableErasure.getKey().equals(overriddenErasure.getKey())) 1337 return false; 1338 } 1339 ITypeBinding[] overriddenExceptions= overridden.getExceptionTypes(); 1340 ITypeBinding[] overridableExceptions= overridable.getExceptionTypes(); 1341 boolean checked= false; 1342 for (int index= 0; index < overriddenExceptions.length; index++) { 1343 checked= false; 1344 for (int offset= 0; offset < overridableExceptions.length; offset++) { 1345 if (overriddenExceptions[index].isSubTypeCompatible(overridableExceptions[offset])) 1346 checked= true; 1347 } 1348 if (!checked) 1349 return false; 1350 } 1351 return true; 1352 } 1353 1354} 1355 | Popular Tags |