1 11 package org.eclipse.jdt.internal.core.search.matching; 12 13 import java.util.HashMap ; 14 15 import org.eclipse.core.resources.IResource; 16 import org.eclipse.core.runtime.*; 17 import org.eclipse.jdt.core.*; 18 import org.eclipse.jdt.core.compiler.CharOperation; 19 import org.eclipse.jdt.core.search.*; 20 import org.eclipse.jdt.internal.compiler.ast.*; 21 import org.eclipse.jdt.internal.compiler.env.IBinaryType; 22 import org.eclipse.jdt.internal.compiler.lookup.*; 23 import org.eclipse.jdt.internal.compiler.util.SimpleSet; 24 import org.eclipse.jdt.internal.core.JavaElement; 25 import org.eclipse.jdt.internal.core.search.BasicSearchEngine; 26 27 public class MethodLocator extends PatternLocator { 28 29 protected MethodPattern pattern; 30 protected boolean isDeclarationOfReferencedMethodsPattern; 31 32 public char[][][] allSuperDeclaringTypeNames; 34 35 private HashMap methodDeclarationsWithInvalidParam = new HashMap (); 37 38 public MethodLocator(MethodPattern pattern) { 39 super(pattern); 40 41 this.pattern = pattern; 42 this.isDeclarationOfReferencedMethodsPattern = this.pattern instanceof DeclarationOfReferencedMethodsPattern; 43 } 44 47 protected void clear() { 48 this.methodDeclarationsWithInvalidParam = new HashMap (); 49 } 50 public void initializePolymorphicSearch(MatchLocator locator) { 51 long start = 0; 52 if (BasicSearchEngine.VERBOSE) { 53 start = System.currentTimeMillis(); 54 } 55 try { 56 this.allSuperDeclaringTypeNames = 57 new SuperTypeNamesCollector( 58 this.pattern, 59 this.pattern.declaringSimpleName, 60 this.pattern.declaringQualification, 61 locator, 62 this.pattern.declaringType, 63 locator.progressMonitor).collect(); 64 } catch (JavaModelException e) { 65 } 67 if (BasicSearchEngine.VERBOSE) { 68 System.out.println("Time to initialize polymorphic search: "+(System.currentTimeMillis()-start)); } 70 } 71 74 private boolean isTypeInSuperDeclaringTypeNames(char[][] typeName) { 75 if (allSuperDeclaringTypeNames == null) return false; 76 int length = allSuperDeclaringTypeNames.length; 77 for (int i= 0; i<length; i++) { 78 if (CharOperation.equals(allSuperDeclaringTypeNames[i], typeName)) { 79 return true; 80 } 81 } 82 return false; 83 } 84 88 protected boolean isVirtualInvoke(MethodBinding method, MessageSend messageSend) { 89 return !method.isStatic() && !method.isPrivate() && !messageSend.isSuperAccess(); 90 } 91 public int match(ASTNode node, MatchingNodeSet nodeSet) { 92 int declarationsLevel = IMPOSSIBLE_MATCH; 93 if (this.pattern.findReferences) { 94 if (node instanceof ImportReference) { 95 ImportReference importRef = (ImportReference) node; 97 int length = importRef.tokens.length-1; 98 if (importRef.isStatic() && ((importRef.bits & ASTNode.OnDemand) == 0) && matchesName(this.pattern.selector, importRef.tokens[length])) { 99 char[][] compoundName = new char[length][]; 100 System.arraycopy(importRef.tokens, 0, compoundName, 0, length); 101 char[] declaringType = CharOperation.concat(pattern.declaringQualification, pattern.declaringSimpleName, '.'); 102 if (matchesName(declaringType, CharOperation.concatWith(compoundName, '.'))) { 103 declarationsLevel = ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH; 104 } 105 } 106 } 107 } 108 return nodeSet.addMatch(node, declarationsLevel); 109 } 110 public int match(MethodDeclaration node, MatchingNodeSet nodeSet) { 114 if (!this.pattern.findDeclarations) return IMPOSSIBLE_MATCH; 115 116 if (!matchesName(this.pattern.selector, node.selector)) return IMPOSSIBLE_MATCH; 118 119 boolean resolve = ((InternalSearchPattern)this.pattern).mustResolve; 121 if (this.pattern.parameterSimpleNames != null) { 122 int length = this.pattern.parameterSimpleNames.length; 123 ASTNode[] args = node.arguments; 124 int argsLength = args == null ? 0 : args.length; 125 if (length != argsLength) return IMPOSSIBLE_MATCH; 126 for (int i = 0; i < argsLength; i++) { 127 if (args != null && !matchesTypeReference(this.pattern.parameterSimpleNames[i], ((Argument) args[i]).type)) { 128 if (this.mayBeGeneric) { 130 if (!((InternalSearchPattern)this.pattern).mustResolve) { 131 nodeSet.mustResolve = true; 134 resolve = true; 135 } 136 this.methodDeclarationsWithInvalidParam.put(node, null); 137 } else { 138 return IMPOSSIBLE_MATCH; 139 } 140 } 141 } 142 } 143 144 if (this.pattern.hasMethodArguments()) { 146 if (node.typeParameters == null || node.typeParameters.length != this.pattern.methodArguments.length) return IMPOSSIBLE_MATCH; 147 } 148 149 return nodeSet.addMatch(node, resolve ? POSSIBLE_MATCH : ACCURATE_MATCH); 151 } 152 public int match(MemberValuePair node, MatchingNodeSet nodeSet) { 153 if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH; 154 155 if (!matchesName(this.pattern.selector, node.name)) return IMPOSSIBLE_MATCH; 156 157 return nodeSet.addMatch(node, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH); 158 } 159 public int match(MessageSend node, MatchingNodeSet nodeSet) { 160 if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH; 161 162 if (!matchesName(this.pattern.selector, node.selector)) return IMPOSSIBLE_MATCH; 163 if (this.pattern.parameterSimpleNames != null && (!this.pattern.varargs || ((node.bits & ASTNode.InsideJavadoc) != 0))) { 164 int length = this.pattern.parameterSimpleNames.length; 165 ASTNode[] args = node.arguments; 166 int argsLength = args == null ? 0 : args.length; 167 if (length != argsLength) return IMPOSSIBLE_MATCH; 168 } 169 170 return nodeSet.addMatch(node, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH); 171 } 172 public int match(Annotation node, MatchingNodeSet nodeSet) { 174 if (!this.pattern.findReferences) return IMPOSSIBLE_MATCH; 175 MemberValuePair[] pairs = node.memberValuePairs(); 176 if (pairs == null || pairs.length == 0) return IMPOSSIBLE_MATCH; 177 178 int length = pairs.length; 179 MemberValuePair pair = null; 180 for (int i=0; i<length; i++) { 181 pair = node.memberValuePairs()[i]; 182 if (matchesName(this.pattern.selector, pair.name)) { 183 ASTNode possibleNode = (node instanceof SingleMemberAnnotation) ? (ASTNode) node : pair; 184 return nodeSet.addMatch(possibleNode, ((InternalSearchPattern)this.pattern).mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH); 185 } 186 } 187 return IMPOSSIBLE_MATCH; 188 } 189 192 protected int matchContainer() { 193 if (this.pattern.findReferences) { 194 return ALL_CONTAINER; 196 } 197 return CLASS_CONTAINER; 198 } 199 203 protected void matchLevelAndReportImportRef(ImportReference importRef, Binding binding, MatchLocator locator) throws CoreException { 204 if (importRef.isStatic() && binding instanceof MethodBinding) { 205 super.matchLevelAndReportImportRef(importRef, binding, locator); 206 } 207 } 208 protected int matchMethod(MethodBinding method, boolean skipImpossibleArg) { 209 if (!matchesName(this.pattern.selector, method.selector)) return IMPOSSIBLE_MATCH; 210 211 int level = ACCURATE_MATCH; 212 if (this.pattern.declaringSimpleName == null) { 214 int newLevel = resolveLevelForType(this.pattern.returnSimpleName, this.pattern.returnQualification, method.returnType); 217 if (level > newLevel) { 218 if (newLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH; 219 level = newLevel; } 221 } 222 223 int parameterCount = this.pattern.parameterSimpleNames == null ? -1 : this.pattern.parameterSimpleNames.length; 225 if (parameterCount > -1) { 226 if (method.parameters == null) return INACCURATE_MATCH; 228 if (parameterCount != method.parameters.length) return IMPOSSIBLE_MATCH; 229 if (!method.isValidBinding() && ((ProblemMethodBinding)method).problemId() == ProblemReasons.Ambiguous) { 230 return INACCURATE_MATCH; 232 } 233 234 for (int i = 0; i < parameterCount; i++) { 236 TypeBinding argType = method.parameters[i]; 237 int newLevel = IMPOSSIBLE_MATCH; 238 if (argType.isMemberType()) { 239 newLevel = CharOperation.match(this.pattern.parameterSimpleNames[i], argType.sourceName(), this.isCaseSensitive) 241 ? ACCURATE_MATCH 242 : IMPOSSIBLE_MATCH; 243 } else { 244 newLevel = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], argType); 247 } 248 if (level > newLevel) { 249 if (newLevel == IMPOSSIBLE_MATCH) { 250 if (skipImpossibleArg) { 251 newLevel = level; 254 } else { 255 return IMPOSSIBLE_MATCH; 256 } 257 } 258 level = newLevel; } 260 } 261 } 262 263 return level; 264 } 265 private boolean matchOverriddenMethod(ReferenceBinding type, MethodBinding method, MethodBinding matchMethod) { 266 if (type == null || this.pattern.selector == null) return false; 267 268 if (!type.isInterface() && !CharOperation.equals(type.compoundName, TypeConstants.JAVA_LANG_OBJECT)) { 270 ReferenceBinding superClass = type.superclass(); 271 if (superClass.isParameterizedType()) { 272 MethodBinding[] methods = superClass.getMethods(this.pattern.selector); 273 int length = methods.length; 274 for (int i = 0; i<length; i++) { 275 if (methods[i].areParametersEqual(method)) { 276 if (matchMethod == null) { 277 if (methodParametersEqualsPattern(methods[i].original())) return true; 278 } else { 279 if (methods[i].original().areParametersEqual(matchMethod)) return true; 280 } 281 } 282 } 283 } 284 if (matchOverriddenMethod(superClass, method, matchMethod)) { 285 return true; 286 } 287 } 288 289 ReferenceBinding[] interfaces = type.superInterfaces(); 291 if (interfaces == null) return false; 292 int iLength = interfaces.length; 293 for (int i = 0; i<iLength; i++) { 294 if (interfaces[i].isParameterizedType()) { 295 MethodBinding[] methods = interfaces[i].getMethods(this.pattern.selector); 296 int length = methods.length; 297 for (int j = 0; j<length; j++) { 298 if (methods[j].areParametersEqual(method)) { 299 if (matchMethod == null) { 300 if (methodParametersEqualsPattern(methods[j].original())) return true; 301 } else { 302 if (methods[j].original().areParametersEqual(matchMethod)) return true; 303 } 304 } 305 } 306 } 307 if (matchOverriddenMethod(interfaces[i], method, matchMethod)) { 308 return true; 309 } 310 } 311 return false; 312 } 313 316 protected void matchReportReference(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException { 317 MethodBinding methodBinding = (reference instanceof MessageSend) ? ((MessageSend)reference).binding: ((elementBinding instanceof MethodBinding) ? (MethodBinding) elementBinding : null); 318 if (this.isDeclarationOfReferencedMethodsPattern) { 319 if (methodBinding == null) return; 320 if (accuracy != SearchMatch.A_ACCURATE) return; 322 323 DeclarationOfReferencedMethodsPattern declPattern = (DeclarationOfReferencedMethodsPattern) this.pattern; 325 while (element != null && !declPattern.enclosingElement.equals(element)) 326 element = element.getParent(); 327 if (element != null) { 328 reportDeclaration(methodBinding, locator, declPattern.knownMethods); 329 } 330 } else { 331 match = locator.newMethodReferenceMatch(element, elementBinding, accuracy, -1, -1, false , false, reference); 332 if (this.pattern.findReferences && reference instanceof MessageSend) { 333 IJavaElement focus = ((InternalSearchPattern) this.pattern).focus; 334 if (focus != null && focus.getElementType() == IJavaElement.METHOD) { 337 if (methodBinding != null && methodBinding.declaringClass != null) { 338 boolean isPrivate = Flags.isPrivate(((IMethod) focus).getFlags()); 339 if (isPrivate && !CharOperation.equals(methodBinding.declaringClass.sourceName, focus.getParent().getElementName().toCharArray())) { 340 return; } 342 } 343 } 344 matchReportReference((MessageSend)reference, locator, ((MessageSend)reference).binding); 345 } else { 346 if (reference instanceof SingleMemberAnnotation) { 347 reference = ((SingleMemberAnnotation)reference).memberValuePairs()[0]; 348 match.setImplicit(true); 349 } 350 int offset = reference.sourceStart; 351 int length = reference.sourceEnd - offset + 1; 352 match.setOffset(offset); 353 match.setLength(length); 354 locator.report(match); 355 } 356 } 357 } 358 void matchReportReference(MessageSend messageSend, MatchLocator locator, MethodBinding methodBinding) throws CoreException { 359 360 boolean isParameterized = false; 362 if (methodBinding instanceof ParameterizedGenericMethodBinding) { isParameterized = true; 364 365 ParameterizedGenericMethodBinding parameterizedMethodBinding = (ParameterizedGenericMethodBinding) methodBinding; 367 match.setRaw(parameterizedMethodBinding.isRaw); 368 TypeBinding[] typeArguments = parameterizedMethodBinding.typeArguments; 369 updateMatch(typeArguments, locator, this.pattern.methodArguments, this.pattern.hasMethodParameters()); 370 371 if (methodBinding.declaringClass.isParameterizedType() || methodBinding.declaringClass.isRawType()) { 373 ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding)methodBinding.declaringClass; 374 if (!this.pattern.hasTypeArguments() && this.pattern.hasMethodArguments() || parameterizedBinding.isParameterizedWithOwnVariables()) { 375 } else { 378 updateMatch(parameterizedBinding, this.pattern.getTypeArguments(), this.pattern.hasTypeParameters(), 0, locator); 379 } 380 } else if (this.pattern.hasTypeArguments()) { 381 match.setRule(SearchPattern.R_ERASURE_MATCH); 382 } 383 384 387 390 if (match.getRule() != 0 && messageSend.resolvedType == null) { 392 match.setRule(SearchPattern.R_ERASURE_MATCH); 393 } 394 } else if (methodBinding instanceof ParameterizedMethodBinding) { 395 isParameterized = true; 396 if (methodBinding.declaringClass.isParameterizedType() || methodBinding.declaringClass.isRawType()) { 397 ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding)methodBinding.declaringClass; 398 if (!parameterizedBinding.isParameterizedWithOwnVariables()) { 399 updateMatch(parameterizedBinding, this.pattern.getTypeArguments(), this.pattern.hasTypeParameters(), 0, locator); 400 } 401 } else if (this.pattern.hasTypeArguments()) { 402 match.setRule(SearchPattern.R_ERASURE_MATCH); 403 } 404 405 408 411 if (match.getRule() != 0 && messageSend.resolvedType == null) { 413 match.setRule(SearchPattern.R_ERASURE_MATCH); 414 } 415 } else if (this.pattern.hasMethodArguments()) { match.setRule(SearchPattern.R_ERASURE_MATCH); 417 } 418 419 if (match.getRule() == 0) return; boolean report = (this.isErasureMatch && match.isErasure()) || (this.isEquivalentMatch && match.isEquivalent()) || match.isExact(); 422 if (!report) return; 423 424 int offset = (int) (messageSend.nameSourcePosition >>> 32); 426 match.setOffset(offset); 427 match.setLength(messageSend.sourceEnd - offset + 1); 428 if (isParameterized && this.pattern.hasMethodArguments()) { 429 locator.reportAccurateParameterizedMethodReference(match, messageSend, messageSend.typeArguments); 430 } else { 431 locator.report(match); 432 } 433 } 434 437 private boolean methodParametersEqualsPattern(MethodBinding method) { 438 TypeBinding[] methodParameters = method.parameters; 439 440 int length = methodParameters.length; 441 if (length != this.pattern.parameterSimpleNames.length) return false; 442 443 for (int i = 0; i < length; i++) { 444 char[] paramQualifiedName = qualifiedPattern(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i]); 445 if (!CharOperation.match(paramQualifiedName, methodParameters[i].readableName(), this.isCaseSensitive)) { 446 return false; 447 } 448 } 449 return true; 450 } 451 public SearchMatch newDeclarationMatch(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, int length, MatchLocator locator) { 452 if (elementBinding != null) { 453 MethodBinding methodBinding = (MethodBinding) elementBinding; 454 if (this.methodDeclarationsWithInvalidParam.containsKey(reference)) { 456 Boolean report = (Boolean ) this.methodDeclarationsWithInvalidParam.get(reference); 458 if (report != null) { 459 if (report.booleanValue()) { 460 return super.newDeclarationMatch(reference, element, elementBinding, accuracy, length, locator); 461 } 462 return null; 463 } 464 if (matchOverriddenMethod(methodBinding.declaringClass, methodBinding, null)) { 465 this.methodDeclarationsWithInvalidParam.put(reference, Boolean.TRUE); 466 return super.newDeclarationMatch(reference, element, elementBinding, accuracy, length, locator); 467 } 468 if (isTypeInSuperDeclaringTypeNames(methodBinding.declaringClass.compoundName)) { 469 MethodBinding patternBinding = locator.getMethodBinding(this.pattern); 470 if (patternBinding != null) { 471 if (!matchOverriddenMethod(patternBinding.declaringClass, patternBinding, methodBinding)) { 472 this.methodDeclarationsWithInvalidParam.put(reference, Boolean.FALSE); 473 return null; 474 } 475 } 476 this.methodDeclarationsWithInvalidParam.put(reference, Boolean.TRUE); 477 return super.newDeclarationMatch(reference, element, elementBinding, accuracy, length, locator); 478 } 479 this.methodDeclarationsWithInvalidParam.put(reference, Boolean.FALSE); 480 return null; 481 } 482 } 483 return super.newDeclarationMatch(reference, element, elementBinding, accuracy, length, locator); 484 } 485 protected int referenceType() { 486 return IJavaElement.METHOD; 487 } 488 protected void reportDeclaration(MethodBinding methodBinding, MatchLocator locator, SimpleSet knownMethods) throws CoreException { 489 ReferenceBinding declaringClass = methodBinding.declaringClass; 490 IType type = locator.lookupType(declaringClass); 491 if (type == null) return; 493 char[] bindingSelector = methodBinding.selector; 494 boolean isBinary = type.isBinary(); 495 IMethod method = null; 496 TypeBinding[] parameters = methodBinding.original().parameters; 497 int parameterLength = parameters.length; 498 if (isBinary) { 499 char[][] parameterTypes = new char[parameterLength][]; 500 for (int i = 0; i<parameterLength; i++) { 501 char[] typeName = parameters[i].qualifiedSourceName(); 502 for (int j=0, dim=parameters[i].dimensions(); j<dim; j++) { 503 typeName = CharOperation.concat(typeName, new char[] {'[', ']'}); 504 } 505 parameterTypes[i] = typeName; 506 } 507 method = locator.createBinaryMethodHandle(type, methodBinding.selector, parameterTypes); 508 } else { 509 String [] parameterTypes = new String [parameterLength]; 510 for (int i = 0; i < parameterLength; i++) { 511 char[] typeName = parameters[i].shortReadableName(); 512 if (parameters[i].isMemberType()) { 513 typeName = CharOperation.subarray(typeName, CharOperation.indexOf('.', typeName)+1, typeName.length); 514 } 515 parameterTypes[i] = Signature.createTypeSignature(typeName, false); 516 } 517 method = type.getMethod(new String (bindingSelector), parameterTypes); 518 } 519 if (method == null || knownMethods.addIfNotIncluded(method) == null) return; 520 521 IResource resource = type.getResource(); 522 IBinaryType info = null; 523 if (isBinary) { 524 if (resource == null) 525 resource = type.getJavaProject().getProject(); 526 info = locator.getBinaryInfo((org.eclipse.jdt.internal.core.ClassFile)type.getClassFile(), resource); 527 locator.reportBinaryMemberDeclaration(resource, method, methodBinding, info, SearchMatch.A_ACCURATE); 528 } else { 529 if (declaringClass instanceof ParameterizedTypeBinding) 530 declaringClass = ((ParameterizedTypeBinding) declaringClass).genericType(); 531 ClassScope scope = ((SourceTypeBinding) declaringClass).scope; 532 if (scope != null) { 533 TypeDeclaration typeDecl = scope.referenceContext; 534 AbstractMethodDeclaration methodDecl = null; 535 AbstractMethodDeclaration[] methodDecls = typeDecl.methods; 536 for (int i = 0, length = methodDecls.length; i < length; i++) { 537 if (CharOperation.equals(bindingSelector, methodDecls[i].selector)) { 538 methodDecl = methodDecls[i]; 539 break; 540 } 541 } 542 if (methodDecl != null) { 543 int offset = methodDecl.sourceStart; 544 Binding binding = methodDecl.binding; 545 if (binding != null) 546 method = (IMethod) ((JavaElement) method).resolved(binding); 547 match = new MethodDeclarationMatch(method, SearchMatch.A_ACCURATE, offset, methodDecl.sourceEnd-offset+1, locator.getParticipant(), resource); 548 locator.report(match); 549 } 550 } 551 } 552 } 553 public int resolveLevel(ASTNode possibleMatchingNode) { 554 if (this.pattern.findReferences) { 555 if (possibleMatchingNode instanceof MessageSend) { 556 return resolveLevel((MessageSend) possibleMatchingNode); 557 } 558 if (possibleMatchingNode instanceof SingleMemberAnnotation) { 559 SingleMemberAnnotation annotation = (SingleMemberAnnotation) possibleMatchingNode; 560 return resolveLevel(annotation.memberValuePairs()[0].binding); 561 } 562 if (possibleMatchingNode instanceof MemberValuePair) { 563 MemberValuePair memberValuePair = (MemberValuePair) possibleMatchingNode; 564 return resolveLevel(memberValuePair.binding); 565 } 566 } 567 if (this.pattern.findDeclarations) { 568 if (possibleMatchingNode instanceof MethodDeclaration) { 569 return resolveLevel(((MethodDeclaration) possibleMatchingNode).binding); 570 } 571 } 572 return IMPOSSIBLE_MATCH; 573 } 574 public int resolveLevel(Binding binding) { 575 if (binding == null) return INACCURATE_MATCH; 576 if (!(binding instanceof MethodBinding)) return IMPOSSIBLE_MATCH; 577 578 MethodBinding method = (MethodBinding) binding; 579 boolean skipVerif = this.pattern.findDeclarations && this.mayBeGeneric; 580 int methodLevel = matchMethod(method, skipVerif); 581 if (methodLevel == IMPOSSIBLE_MATCH) { 582 if (method != method.original()) methodLevel = matchMethod(method.original(), skipVerif); 583 if (methodLevel == IMPOSSIBLE_MATCH) { 584 return IMPOSSIBLE_MATCH; 585 } else { 586 method = method.original(); 587 } 588 } 589 590 char[] qualifiedPattern = qualifiedPattern(this.pattern.declaringSimpleName, this.pattern.declaringQualification); 592 if (qualifiedPattern == null) return methodLevel; 594 boolean subType = !method.isStatic() && !method.isPrivate(); 595 if (subType && this.pattern.declaringQualification != null && method.declaringClass != null && method.declaringClass.fPackage != null) { 596 subType = CharOperation.compareWith(this.pattern.declaringQualification, method.declaringClass.fPackage.shortReadableName()) == 0; 597 } 598 int declaringLevel = subType 599 ? resolveLevelAsSubtype(qualifiedPattern, method.declaringClass, null) 600 : resolveLevelForType(qualifiedPattern, method.declaringClass); 601 return methodLevel > declaringLevel ? declaringLevel : methodLevel; } 603 protected int resolveLevel(MessageSend messageSend) { 604 MethodBinding method = messageSend.binding; 605 if (method == null) { 606 return INACCURATE_MATCH; 607 } 608 if (messageSend.resolvedType == null) { 609 int argLength = messageSend.arguments == null ? 0 : messageSend.arguments.length; 613 if (pattern.parameterSimpleNames == null || argLength == pattern.parameterSimpleNames.length) { 614 return INACCURATE_MATCH; 615 } 616 return IMPOSSIBLE_MATCH; 617 } 618 619 int methodLevel = matchMethod(method, false); 620 if (methodLevel == IMPOSSIBLE_MATCH) { 621 if (method != method.original()) methodLevel = matchMethod(method.original(), false); 622 if (methodLevel == IMPOSSIBLE_MATCH) return IMPOSSIBLE_MATCH; 623 method = method.original(); 624 } 625 626 char[] qualifiedPattern = qualifiedPattern(this.pattern.declaringSimpleName, this.pattern.declaringQualification); 628 if (qualifiedPattern == null) return methodLevel; 630 int declaringLevel; 631 if (isVirtualInvoke(method, messageSend) && (messageSend.actualReceiverType instanceof ReferenceBinding)) { 632 ReferenceBinding methodReceiverType = (ReferenceBinding) messageSend.actualReceiverType; 633 declaringLevel = resolveLevelAsSubtype(qualifiedPattern, methodReceiverType, method.parameters); 634 if (declaringLevel == IMPOSSIBLE_MATCH) { 635 if (method.declaringClass == null || this.allSuperDeclaringTypeNames == null) { 636 declaringLevel = INACCURATE_MATCH; 637 } else { 638 char[][] compoundName = methodReceiverType.compoundName; 639 for (int i = 0, max = this.allSuperDeclaringTypeNames.length; i < max; i++) { 640 if (CharOperation.equals(this.allSuperDeclaringTypeNames[i], compoundName)) { 641 return methodLevel | SUPER_INVOCATION_FLAVOR; } 644 } 645 653 } 654 } 655 if ((declaringLevel & FLAVORS_MASK) != 0) { 656 return declaringLevel; 658 } 659 } else { 660 declaringLevel = resolveLevelForType(qualifiedPattern, method.declaringClass); 661 } 662 return methodLevel > declaringLevel ? declaringLevel : methodLevel; } 664 671 protected int resolveLevelAsSubtype(char[] qualifiedPattern, ReferenceBinding type, TypeBinding[] argumentTypes) { 672 if (type == null) return INACCURATE_MATCH; 673 674 int level = resolveLevelForType(qualifiedPattern, type); 675 if (level != IMPOSSIBLE_MATCH) { 676 if (!type.isAbstract() && !type.isInterface()) { level |= OVERRIDDEN_METHOD_FLAVOR; 678 } 679 return level; 680 } 681 682 if (!type.isInterface() && !CharOperation.equals(type.compoundName, TypeConstants.JAVA_LANG_OBJECT)) { 684 level = resolveLevelAsSubtype(qualifiedPattern, type.superclass(), argumentTypes); 685 if (level != IMPOSSIBLE_MATCH) { 686 if (argumentTypes != null) { 687 MethodBinding[] methods = type.getMethods(this.pattern.selector); 689 for (int i=0, length=methods.length; i<length; i++) { 690 MethodBinding method = methods[i]; 691 TypeBinding[] parameters = method.parameters; 692 if (argumentTypes.length == parameters.length) { 693 boolean found = true; 694 for (int j=0,l=parameters.length; j<l; j++) { 695 if (parameters[j].erasure() != argumentTypes[j].erasure()) { 696 found = false; 697 break; 698 } 699 } 700 if (found) { if ((level & OVERRIDDEN_METHOD_FLAVOR) != 0) { 702 return IMPOSSIBLE_MATCH; 704 } 705 if (!method.isAbstract() && !type.isInterface()) { 706 level |= OVERRIDDEN_METHOD_FLAVOR; 708 } 709 } 710 } 711 } 712 } 713 return level | SUB_INVOCATION_FLAVOR; } 715 } 716 717 ReferenceBinding[] interfaces = type.superInterfaces(); 719 if (interfaces == null) return INACCURATE_MATCH; 720 for (int i = 0; i < interfaces.length; i++) { 721 level = resolveLevelAsSubtype(qualifiedPattern, interfaces[i], null); 722 if (level != IMPOSSIBLE_MATCH) { 723 if (!type.isAbstract() && !type.isInterface()) { level |= OVERRIDDEN_METHOD_FLAVOR; 725 } 726 return level | SUB_INVOCATION_FLAVOR; } 728 } 729 return IMPOSSIBLE_MATCH; 730 } 731 public String toString() { 732 return "Locator for " + this.pattern.toString(); } 734 } 735 | Popular Tags |