<s> package org . eclipse . jdt . internal . core . search . matching ; import java . util . HashMap ; import org . eclipse . core . resources . IResource ; import org . eclipse . core . runtime . * ; import org . eclipse . jdt . core . * ; import org . eclipse . jdt . core . compiler . CharOperation ; import org . eclipse . jdt . core . search . * ; import org . eclipse . jdt . internal . compiler . ast . * ; import org . eclipse . jdt . internal . compiler . env . IBinaryType ; import org . eclipse . jdt . internal . compiler . lookup . * ; import org . eclipse . jdt . internal . compiler . util . SimpleSet ; import org . eclipse . jdt . internal . core . search . BasicSearchEngine ; public class MethodLocator extends PatternLocator { protected MethodPattern pattern ; protected boolean isDeclarationOfReferencedMethodsPattern ; public char [ ] [ ] [ ] allSuperDeclaringTypeNames ; private HashMap methodDeclarationsWithInvalidParam = new HashMap ( ) ; public MethodLocator ( MethodPattern pattern ) { super ( pattern ) ; this . pattern = pattern ; this . isDeclarationOfReferencedMethodsPattern = this . pattern instanceof DeclarationOfReferencedMethodsPattern ; } protected void clear ( ) { this . methodDeclarationsWithInvalidParam = new HashMap ( ) ; } protected int fineGrain ( ) { return this . pattern . fineGrain ; } private MethodBinding getMethodBinding ( ReferenceBinding type , char [ ] methodName , TypeBinding [ ] argumentTypes ) { MethodBinding [ ] methods = type . getMethods ( methodName ) ; MethodBinding method = null ; methodsLoop : for ( int i = 0 , length = methods . length ; i < length ; i ++ ) { method = methods [ i ] ; TypeBinding [ ] parameters = method . parameters ; if ( argumentTypes . length == parameters . length ) { for ( int j = 0 , l = parameters . length ; j < l ; j ++ ) { if ( parameters [ j ] . erasure ( ) != argumentTypes [ j ] . erasure ( ) ) { continue methodsLoop ; } } return method ; } } return null ; } public void initializePolymorphicSearch ( MatchLocator locator ) { long start = 0 ; if ( BasicSearchEngine . VERBOSE ) { start = System . currentTimeMillis ( ) ; } try { this . allSuperDeclaringTypeNames = new SuperTypeNamesCollector ( this . pattern , this . pattern . declaringSimpleName , this . pattern . declaringQualification , locator , this . pattern . declaringType , locator . progressMonitor ) . collect ( ) ; } catch ( JavaModelException e ) { } if ( BasicSearchEngine . VERBOSE ) { System . out . println ( "" + ( System . currentTimeMillis ( ) - start ) ) ; } } private boolean isTypeInSuperDeclaringTypeNames ( char [ ] [ ] typeName ) { if ( this . allSuperDeclaringTypeNames == null ) return false ; int length = this . allSuperDeclaringTypeNames . length ; for ( int i = 0 ; i < length ; i ++ ) { if ( CharOperation . equals ( this . allSuperDeclaringTypeNames [ i ] , typeName ) ) { return true ; } } return false ; } protected boolean isVirtualInvoke ( MethodBinding method , MessageSend messageSend ) { return ! method . isStatic ( ) && ! method . isPrivate ( ) && ! messageSend . isSuperAccess ( ) ; } public int match ( ASTNode node , MatchingNodeSet nodeSet ) { int declarationsLevel = IMPOSSIBLE_MATCH ; if ( this . pattern . findReferences ) { if ( node instanceof ImportReference ) { ImportReference importRef = ( ImportReference ) node ; int length = importRef . tokens . length - 1 ; if ( importRef . isStatic ( ) && ( ( importRef . bits & ASTNode . OnDemand ) == 0 ) && matchesName ( this . pattern . selector , importRef . tokens [ length ] ) ) { char [ ] [ ] compoundName = new char [ length ] [ ] ; System . arraycopy ( importRef . tokens , 0 , compoundName , 0 , length ) ; char [ ] declaringType = CharOperation . concat ( this . pattern . declaringQualification , this . pattern . declaringSimpleName , '.' ) ; if ( matchesName ( declaringType , CharOperation . concatWith ( compoundName , '.' ) ) ) { declarationsLevel = this . pattern . mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH ; } } } } return nodeSet . addMatch ( node , declarationsLevel ) ; } public int match ( MethodDeclaration node , MatchingNodeSet nodeSet ) { if ( ! this . pattern . findDeclarations ) return IMPOSSIBLE_MATCH ; if ( ! matchesName ( this . pattern . selector , node . selector ) ) return IMPOSSIBLE_MATCH ; boolean resolve = this . pattern . mustResolve ; if ( this . pattern . parameterSimpleNames != null ) { int length = this . pattern . parameterSimpleNames . length ; ASTNode [ ] args = node . arguments ; int argsLength = args == null ? 0 : args . length ; if ( length != argsLength ) return IMPOSSIBLE_MATCH ; for ( int i = 0 ; i < argsLength ; i ++ ) { if ( args != null && ! matchesTypeReference ( this . pattern . parameterSimpleNames [ i ] , ( ( Argument ) args [ i ] ) . type ) ) { if ( this . mayBeGeneric ) { if ( ! this . pattern . mustResolve ) { nodeSet . mustResolve = true ; resolve = true ; } this . methodDeclarationsWithInvalidParam . put ( node , null ) ; } else { return IMPOSSIBLE_MATCH ; } } } } if ( this . pattern . hasMethodArguments ( ) ) { if ( node . typeParameters == null || node . typeParameters . length != this . pattern . methodArguments . length ) return IMPOSSIBLE_MATCH ; } return nodeSet . addMatch ( node , resolve ? POSSIBLE_MATCH : ACCURATE_MATCH ) ; } public int match ( MemberValuePair node , MatchingNodeSet nodeSet ) { if ( ! this . pattern . findReferences ) return IMPOSSIBLE_MATCH ; if ( ! matchesName ( this . pattern . selector , node . name ) ) return IMPOSSIBLE_MATCH ; return nodeSet . addMatch ( node , this . pattern . mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH ) ; } public int match ( MessageSend node , MatchingNodeSet nodeSet ) { if ( ! this . pattern . findReferences ) return IMPOSSIBLE_MATCH ; if ( ! matchesName ( this . pattern . selector , node . selector ) ) return IMPOSSIBLE_MATCH ; if ( this . pattern . parameterSimpleNames != null && ( ! this . pattern . varargs || ( ( node . bits & ASTNode . InsideJavadoc ) != 0 ) ) ) { int length = this . pattern . parameterSimpleNames . length ; ASTNode [ ] args = node . arguments ; int argsLength = args == null ? 0 : args . length ; if ( length != argsLength ) return IMPOSSIBLE_MATCH ; } return nodeSet . addMatch ( node , this . pattern . mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH ) ; } public int match ( Annotation node , MatchingNodeSet nodeSet ) { if ( ! this . pattern . findReferences ) return IMPOSSIBLE_MATCH ; MemberValuePair [ ] pairs = node . memberValuePairs ( ) ; if ( pairs == null || pairs . length == 0 ) return IMPOSSIBLE_MATCH ; int length = pairs . length ; MemberValuePair pair = null ; for ( int i = 0 ; i < length ; i ++ ) { pair = node . memberValuePairs ( ) [ i ] ; if ( matchesName ( this . pattern . selector , pair . name ) ) { ASTNode possibleNode = ( node instanceof SingleMemberAnnotation ) ? ( ASTNode ) node : pair ; return nodeSet . addMatch ( possibleNode , this . pattern . mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH ) ; } } return IMPOSSIBLE_MATCH ; } protected int matchContainer ( ) { if ( this . pattern . findReferences ) { return ALL_CONTAINER ; } return CLASS_CONTAINER ; } protected void matchLevelAndReportImportRef ( ImportReference importRef , Binding binding , MatchLocator locator ) throws CoreException { if ( importRef . isStatic ( ) && binding instanceof MethodBinding ) { super . matchLevelAndReportImportRef ( importRef , binding , locator ) ; } } protected int matchMethod ( MethodBinding method , boolean skipImpossibleArg ) { if ( ! matchesName ( this . pattern . selector , method . selector ) ) return IMPOSSIBLE_MATCH ; int level = ACCURATE_MATCH ; if ( this . pattern . declaringSimpleName == null ) { int newLevel = resolveLevelForType ( this . pattern . returnSimpleName , this . pattern . returnQualification , method . returnType ) ; if ( level > newLevel ) { if ( newLevel == IMPOSSIBLE_MATCH ) return IMPOSSIBLE_MATCH ; level = newLevel ; } } int parameterCount = this . pattern . parameterSimpleNames == null ? - 1 : this . pattern . parameterSimpleNames . length ; if ( parameterCount > - 1 ) { if ( method . parameters == null ) return INACCURATE_MATCH ; if ( parameterCount != method . parameters . length ) return IMPOSSIBLE_MATCH ; if ( ! method . isValidBinding ( ) && ( ( ProblemMethodBinding ) method ) . problemId ( ) == ProblemReasons . Ambiguous ) { return INACCURATE_MATCH ; } for ( int i = 0 ; i < parameterCount ; i ++ ) { TypeBinding argType = method . parameters [ i ] ; int newLevel = IMPOSSIBLE_MATCH ; if ( argType . isMemberType ( ) ) { newLevel = CharOperation . match ( this . pattern . parameterSimpleNames [ i ] , argType . sourceName ( ) , this . isCaseSensitive ) ? ACCURATE_MATCH : IMPOSSIBLE_MATCH ; } else { newLevel = resolveLevelForType ( this . pattern . parameterSimpleNames [ i ] , this . pattern . parameterQualifications [ i ] , argType ) ; } if ( level > newLevel ) { if ( newLevel == IMPOSSIBLE_MATCH ) { if ( skipImpossibleArg ) { newLevel = level ; } else { return IMPOSSIBLE_MATCH ; } } level = newLevel ; } } } return level ; } private boolean matchOverriddenMethod ( ReferenceBinding type , MethodBinding method , MethodBinding matchMethod ) { if ( type == null || this . pattern . selector == null ) return false ; if ( ! type . isInterface ( ) && ! CharOperation . equals ( type . compoundName , TypeConstants . JAVA_LANG_OBJECT ) ) { ReferenceBinding superClass = type . superclass ( ) ; if ( superClass . isParameterizedType ( ) ) { MethodBinding [ ] methods = superClass . getMethods ( this . pattern . selector ) ; int length = methods . length ; for ( int i = 0 ; i < length ; i ++ ) { if ( methods [ i ] . areParametersEqual ( method ) ) { if ( matchMethod == null ) { if ( methodParametersEqualsPattern ( methods [ i ] . original ( ) ) ) return true ; } else { if ( methods [ i ] . original ( ) . areParametersEqual ( matchMethod ) ) return true ; } } } } if ( matchOverriddenMethod ( superClass , method , matchMethod ) ) { return true ; } } ReferenceBinding [ ] interfaces = type . superInterfaces ( ) ; if ( interfaces == null ) return false ; int iLength = interfaces . length ; for ( int i = 0 ; i < iLength ; i ++ ) { if ( interfaces [ i ] . isParameterizedType ( ) ) { MethodBinding [ ] methods = interfaces [ i ] . getMethods ( this . pattern . selector ) ; int length = methods . length ; for ( int j = 0 ; j < length ; j ++ ) { if ( methods [ j ] . areParametersEqual ( method ) ) { if ( matchMethod == null ) { if ( methodParametersEqualsPattern ( methods [ j ] . original ( ) ) ) return true ; } else { if ( methods [ j ] . original ( ) . areParametersEqual ( matchMethod ) ) return true ; } } } } if ( matchOverriddenMethod ( interfaces [ i ] , method , matchMethod ) ) { return true ; } } return false ; } protected void matchReportReference ( ASTNode reference , IJavaElement element , Binding elementBinding , int accuracy , MatchLocator locator ) throws CoreException { matchReportReference ( reference , element , null , null , elementBinding , accuracy , locator ) ; } protected void matchReportReference ( ASTNode reference , IJavaElement element , IJavaElement localElement , IJavaElement [ ] otherElements , Binding elementBinding , int accuracy , MatchLocator locator ) throws CoreException { MethodBinding methodBinding = ( reference instanceof MessageSend ) ? ( ( MessageSend ) reference ) . binding : ( ( elementBinding instanceof MethodBinding ) ? ( MethodBinding ) elementBinding : null ) ; if ( this . isDeclarationOfReferencedMethodsPattern ) { if ( methodBinding == null ) return ; if ( accuracy != SearchMatch . A_ACCURATE ) return ; DeclarationOfReferencedMethodsPattern declPattern = ( DeclarationOfReferencedMethodsPattern ) this . pattern ; while ( element != null && ! declPattern . enclosingElement . equals ( element ) ) element = element . getParent ( ) ; if ( element != null ) { reportDeclaration ( methodBinding , locator , declPattern . knownMethods ) ; } } else { MethodReferenceMatch methodReferenceMatch = locator . newMethodReferenceMatch ( element , elementBinding , accuracy , - 1 , - 1 , false , false , reference ) ; methodReferenceMatch . setLocalElement ( localElement ) ; this . match = methodReferenceMatch ; if ( this . pattern . findReferences && reference instanceof MessageSend ) { IJavaElement focus = this . pattern . focus ; if ( focus != null && focus . getElementType ( ) == IJavaElement . METHOD ) { if ( methodBinding != null && methodBinding . declaringClass != null ) { boolean isPrivate = Flags . isPrivate ( ( ( IMethod ) focus ) . getFlags ( ) ) ; if ( isPrivate && ! CharOperation . equals ( methodBinding . declaringClass . sourceName , focus . getParent ( ) . getElementName ( ) . toCharArray ( ) ) ) { return ; } } } matchReportReference ( ( MessageSend ) reference , locator , ( ( MessageSend ) reference ) . binding ) ; } else { if ( reference instanceof SingleMemberAnnotation ) { reference = ( ( SingleMemberAnnotation ) reference ) . memberValuePairs ( ) [ 0 ] ; this . match . setImplicit ( true ) ; } int offset = reference . sourceStart ; int length = reference . sourceEnd - offset + 1 ; this . match . setOffset ( offset ) ; this . match . setLength ( length ) ; locator . report ( this . match ) ; } } } void matchReportReference ( MessageSend messageSend , MatchLocator locator , MethodBinding methodBinding ) throws CoreException { boolean isParameterized = false ; if ( methodBinding instanceof ParameterizedGenericMethodBinding ) { isParameterized = true ; ParameterizedGenericMethodBinding parameterizedMethodBinding = ( ParameterizedGenericMethodBinding ) methodBinding ; this . match . setRaw ( parameterizedMethodBinding . isRaw ) ; TypeBinding [ ] typeArguments = parameterizedMethodBinding . typeArguments ; updateMatch ( typeArguments , locator , this . pattern . methodArguments , this . pattern . hasMethodParameters ( ) ) ; if ( methodBinding . declaringClass . isParameterizedType ( ) || methodBinding . declaringClass . isRawType ( ) ) { ParameterizedTypeBinding parameterizedBinding = ( ParameterizedTypeBinding ) methodBinding . declaringClass ; if ( ! this . pattern . hasTypeArguments ( ) && this . pattern . hasMethodArguments ( ) || parameterizedBinding . isParameterizedWithOwnVariables ( ) ) { } else { updateMatch ( parameterizedBinding , this . pattern . getTypeArguments ( ) , this . pattern . hasTypeParameters ( ) , 0 , locator ) ; } } else if ( this . pattern . hasTypeArguments ( ) ) { this . match . setRule ( SearchPattern . R_ERASURE_MATCH ) ; } if ( this . match . getRule ( ) != 0 && messageSend . resolvedType == null ) { this . match . setRule ( SearchPattern . R_ERASURE_MATCH ) ; } } else if ( methodBinding instanceof ParameterizedMethodBinding ) { isParameterized = true ; if ( methodBinding . declaringClass . isParameterizedType ( ) || methodBinding . declaringClass . isRawType ( ) ) { ParameterizedTypeBinding parameterizedBinding = ( ParameterizedTypeBinding ) methodBinding . declaringClass ; if ( ! parameterizedBinding . isParameterizedWithOwnVariables ( ) ) { updateMatch ( parameterizedBinding , this . pattern . getTypeArguments ( ) , this . pattern . hasTypeParameters ( ) , 0 , locator ) ; } } else if ( this . pattern . hasTypeArguments ( ) ) { this . match . setRule ( SearchPattern . R_ERASURE_MATCH ) ; } if ( this . match . getRule ( ) != 0 && messageSend . resolvedType == null ) { this . match . setRule ( SearchPattern . R_ERASURE_MATCH ) ; } } else if ( this . pattern . hasMethodArguments ( ) ) { this . match . setRule ( SearchPattern . R_ERASURE_MATCH ) ; } if ( this . match . getRule ( ) == 0 ) return ; boolean report = ( this . isErasureMatch && this . match . isErasure ( ) ) || ( this . isEquivalentMatch && this . match . isEquivalent ( ) ) || this . match . isExact ( ) ; if ( ! report ) return ; int offset = ( int ) ( messageSend . nameSourcePosition >>> 32 ) ; this . match . setOffset ( offset ) ; this . match . setLength ( messageSend . sourceEnd - offset + 1 ) ; if ( isParameterized && this . pattern . hasMethodArguments ( ) ) { locator . reportAccurateParameterizedMethodReference ( this . match , messageSend , messageSend . typeArguments ) ; } else { locator . report ( this . match ) ; } } private boolean methodParametersEqualsPattern ( MethodBinding method ) { TypeBinding [ ] methodParameters = method . parameters ; int length = methodParameters . length ; if ( length != this . pattern . parameterSimpleNames . length ) return false ; for ( int i = 0 ; i < length ; i ++ ) { char [ ] paramQualifiedName = qualifiedPattern ( this . pattern . parameterSimpleNames [ i ] , this . pattern . parameterQualifications [ i ] ) ; if ( ! CharOperation . match ( paramQualifiedName , methodParameters [ i ] . readableName ( ) , this . isCaseSensitive ) ) { return false ; } } return true ; } public SearchMatch newDeclarationMatch ( ASTNode reference , IJavaElement element , Binding elementBinding , int accuracy , int length , MatchLocator locator ) { if ( elementBinding != null ) { MethodBinding methodBinding = ( MethodBinding ) elementBinding ; if ( this . methodDeclarationsWithInvalidParam . containsKey ( reference ) ) { Boolean report = ( Boolean ) this . methodDeclarationsWithInvalidParam . get ( reference ) ; if ( report != null ) { if ( report . booleanValue ( ) ) { return super . newDeclarationMatch ( reference , element , elementBinding , accuracy , length , locator ) ; } return null ; } if ( matchOverriddenMethod ( methodBinding . declaringClass , methodBinding , null ) ) { this . methodDeclarationsWithInvalidParam . put ( reference , Boolean . TRUE ) ; return super . newDeclarationMatch ( reference , element , elementBinding , accuracy , length , locator ) ; } if ( isTypeInSuperDeclaringTypeNames ( methodBinding . declaringClass . compoundName ) ) { MethodBinding patternBinding = locator . getMethodBinding ( this . pattern ) ; if ( patternBinding != null ) { if ( ! matchOverriddenMethod ( patternBinding . declaringClass , patternBinding , methodBinding ) ) { this . methodDeclarationsWithInvalidParam . put ( reference , Boolean . FALSE ) ; return null ; } } this . methodDeclarationsWithInvalidParam . put ( reference , Boolean . TRUE ) ; return super . newDeclarationMatch ( reference , element , elementBinding , accuracy , length , locator ) ; } this . methodDeclarationsWithInvalidParam . put ( reference , Boolean . FALSE ) ; return null ; } } return super . newDeclarationMatch ( reference , element , elementBinding , accuracy , length , locator ) ; } protected int referenceType ( ) { return IJavaElement . METHOD ; } protected void reportDeclaration ( MethodBinding methodBinding , MatchLocator locator , SimpleSet knownMethods ) throws CoreException { ReferenceBinding declaringClass = methodBinding . declaringClass ; IType type = locator . lookupType ( declaringClass ) ; if ( type == null ) return ; if ( type . isBinary ( ) ) { IMethod method = null ; TypeBinding [ ] parameters = methodBinding . original ( ) . parameters ; int parameterLength = parameters . length ; char [ ] [ ] parameterTypes = new char [ parameterLength ] [ ] ; for ( int i = 0 ; i < parameterLength ; i ++ ) { char [ ] typeName = parameters [ i ] . qualifiedSourceName ( ) ; for ( int j = 0 , dim = parameters [ i ] . dimensions ( ) ; j < dim ; j ++ ) { typeName = CharOperation . concat ( typeName , new char [ ] { '[' , ']' } ) ; } parameterTypes [ i ] = typeName ; } method = locator . createBinaryMethodHandle ( type , methodBinding . selector , parameterTypes ) ; if ( method == null || knownMethods . addIfNotIncluded ( method ) == null ) return ; IResource resource = type . getResource ( ) ; if ( resource == null ) resource = type . getJavaProject ( ) . getProject ( ) ; IBinaryType info = locator . getBinaryInfo ( ( org . eclipse . jdt . internal . core . ClassFile ) type . getClassFile ( ) , resource ) ; locator . reportBinaryMemberDeclaration ( resource , method , methodBinding , info , SearchMatch . A_ACCURATE ) ; return ; } IResource resource = type . getResource ( ) ; if ( declaringClass instanceof ParameterizedTypeBinding ) declaringClass = ( ( ParameterizedTypeBinding ) declaringClass ) . genericType ( ) ; ClassScope scope = ( ( SourceTypeBinding ) declaringClass ) . scope ; if ( scope != null ) { TypeDeclaration typeDecl = scope . referenceContext ; AbstractMethodDeclaration methodDecl = typeDecl . declarationOf ( methodBinding . original ( ) ) ; if ( methodDecl != null ) { String methodName = new String ( methodBinding . selector ) ; Argument [ ] arguments = methodDecl . arguments ; int length = arguments == null ? 0 : arguments . length ; String [ ] parameterTypes = new String [ length ] ; for ( int i = 0 ; i < length ; i ++ ) { char [ ] [ ] typeName = arguments [ i ] . type . getParameterizedTypeName ( ) ; parameterTypes [ i ] = Signature . createTypeSignature ( CharOperation . concatWith ( typeName , '.' ) , false ) ; } IMethod method = type . getMethod ( methodName , parameterTypes ) ; if ( method == null || knownMethods . addIfNotIncluded ( method ) == null ) return ; int offset = methodDecl . sourceStart ; this . match = new MethodDeclarationMatch ( method , SearchMatch . A_ACCURATE , offset , methodDecl . sourceEnd - offset + 1 , locator . getParticipant ( ) , resource ) ; locator . report ( this . match ) ; } } } public int resolveLevel ( ASTNode possibleMatchingNode ) { if ( this . pattern . findReferences ) { if ( possibleMatchingNode instanceof MessageSend ) { return resolveLevel ( ( MessageSend ) possibleMatchingNode ) ; } if ( possibleMatchingNode instanceof SingleMemberAnnotation ) { SingleMemberAnnotation annotation = ( SingleMemberAnnotation ) possibleMatchingNode ; return resolveLevel ( annotation . memberValuePairs ( ) [ 0 ] . binding ) ; } if ( possibleMatchingNode instanceof MemberValuePair ) { MemberValuePair memberValuePair = ( MemberValuePair ) possibleMatchingNode ; return resolveLevel ( memberValuePair . binding ) ; } } if ( this . pattern . findDeclarations ) { if ( possibleMatchingNode instanceof MethodDeclaration ) { return resolveLevel ( ( ( MethodDeclaration ) possibleMatchingNode ) . binding ) ; } } return IMPOSSIBLE_MATCH ; } public int resolveLevel ( Binding binding ) { if ( binding == null ) return INACCURATE_MATCH ; if ( ! ( binding instanceof MethodBinding ) ) return IMPOSSIBLE_MATCH ; MethodBinding method = ( MethodBinding ) binding ; boolean skipVerif = this . pattern . findDeclarations && this . mayBeGeneric ; int methodLevel = matchMethod ( method , skipVerif ) ; if ( methodLevel == IMPOSSIBLE_MATCH ) { if ( method != method . original ( ) ) methodLevel = matchMethod ( method . original ( ) , skipVerif ) ; if ( methodLevel == IMPOSSIBLE_MATCH ) { return IMPOSSIBLE_MATCH ; } else { method = method . original ( ) ; } } if ( this . pattern . declaringSimpleName == null && this . pattern . declaringQualification == null ) return methodLevel ; boolean subType = ! method . isStatic ( ) && ! method . isPrivate ( ) ; if ( subType && this . pattern . declaringQualification != null && method . declaringClass != null && method . declaringClass . fPackage != null ) { subType = CharOperation . compareWith ( this . pattern . declaringQualification , method . declaringClass . fPackage . shortReadableName ( ) ) == 0 ; } int declaringLevel = subType ? resolveLevelAsSubtype ( this . pattern . declaringSimpleName , this . pattern . declaringQualification , method . declaringClass , method . selector , null ) : resolveLevelForType ( this . pattern . declaringSimpleName , this . pattern . declaringQualification , method . declaringClass ) ; return ( methodLevel & MATCH_LEVEL_MASK ) > ( declaringLevel & MATCH_LEVEL_MASK ) ? declaringLevel : methodLevel ; } protected int resolveLevel ( MessageSend messageSend ) { MethodBinding method = messageSend . binding ; if ( method == null ) { return INACCURATE_MATCH ; } if ( messageSend . resolvedType == null ) { int argLength = messageSend . arguments == null ? 0 : messageSend . arguments . length ; if ( this . pattern . parameterSimpleNames == null || argLength == this . pattern . parameterSimpleNames . length ) { return INACCURATE_MATCH ; } return IMPOSSIBLE_MATCH ; } int methodLevel = matchMethod ( method , false ) ; if ( methodLevel == IMPOSSIBLE_MATCH ) { if ( method != method . original ( ) ) methodLevel = matchMethod ( method . original ( ) , false ) ; if ( methodLevel == IMPOSSIBLE_MATCH ) return IMPOSSIBLE_MATCH ; method = method . original ( ) ; } if ( this . pattern . declaringSimpleName == null && this . pattern . declaringQualification == null ) return methodLevel ; int declaringLevel ; if ( isVirtualInvoke ( method , messageSend ) && ( messageSend . actualReceiverType instanceof ReferenceBinding ) ) { ReferenceBinding methodReceiverType = ( ReferenceBinding ) messageSend . actualReceiverType ; declaringLevel = resolveLevelAsSubtype ( this . pattern . declaringSimpleName , this . pattern . declaringQualification , methodReceiverType , method . selector , method . parameters ) ; if ( declaringLevel == IMPOSSIBLE_MATCH ) { if ( method . declaringClass == null || this . allSuperDeclaringTypeNames == null ) { declaringLevel = INACCURATE_MATCH ; } else { if ( resolveLevelAsSuperInvocation ( methodReceiverType , method . parameters , true ) ) { declaringLevel = methodLevel | SUPER_INVOCATION_FLAVOR ; } } } if ( ( declaringLevel & FLAVORS_MASK ) != 0 ) { return declaringLevel ; } } else { declaringLevel = resolveLevelForType ( this . pattern . declaringSimpleName , this . pattern . declaringQualification , method . declaringClass ) ; } return ( methodLevel & MATCH_LEVEL_MASK ) > ( declaringLevel & MATCH_LEVEL_MASK ) ? declaringLevel : methodLevel ; } protected int resolveLevelAsSubtype ( char [ ] simplePattern , char [ ] qualifiedPattern , ReferenceBinding type , char [ ] methodName , TypeBinding [ ] argumentTypes ) { if ( type == null ) return INACCURATE_MATCH ; int level = resolveLevelForType ( simplePattern , qualifiedPattern , type ) ; if ( level != IMPOSSIBLE_MATCH ) { MethodBinding method = argumentTypes == null ? null : getMethodBinding ( type , methodName , argumentTypes ) ; if ( ( ( method != null && ! method . isAbstract ( ) ) || ! type . isAbstract ( ) ) && ! type . isInterface ( ) ) { level |= OVERRIDDEN_METHOD_FLAVOR ; } return level ; } if ( ! type . isInterface ( ) && ! CharOperation . equals ( type . compoundName , TypeConstants . JAVA_LANG_OBJECT ) ) { level = resolveLevelAsSubtype ( simplePattern , qualifiedPattern , type . superclass ( ) , methodName , argumentTypes ) ; if ( level != IMPOSSIBLE_MATCH ) { if ( argumentTypes != null ) { MethodBinding method = getMethodBinding ( type , methodName , argumentTypes ) ; if ( method != null ) { if ( ( level & OVERRIDDEN_METHOD_FLAVOR ) != 0 ) { return IMPOSSIBLE_MATCH ; } if ( ! method . isAbstract ( ) && ! type . isInterface ( ) ) { level |= OVERRIDDEN_METHOD_FLAVOR ; } } } return level | SUB_INVOCATION_FLAVOR ; } } ReferenceBinding [ ] interfaces = type . superInterfaces ( ) ; if ( interfaces == null ) return INACCURATE_MATCH ; for ( int i = 0 ; i < interfaces . length ; i ++ ) { level = resolveLevelAsSubtype ( simplePattern , qualifiedPattern , interfaces [ i ] , methodName , null ) ; if ( level != IMPOSSIBLE_MATCH ) { if ( ! type . isAbstract ( ) && ! type . isInterface ( ) ) { level |= OVERRIDDEN_METHOD_FLAVOR ; } return level | SUB_INVOCATION_FLAVOR ; } } return IMPOSSIBLE_MATCH ; } private boolean resolveLevelAsSuperInvocation ( ReferenceBinding type , TypeBinding [ ] argumentTypes , boolean methodAlreadyVerified ) { char [ ] [ ] compoundName = type . compoundName ; for ( int i = 0 , max = this . allSuperDeclaringTypeNames . length ; i < max ; i ++ ) { if ( CharOperation . equals ( this . allSuperDeclaringTypeNames [ i ] , compoundName ) ) { if ( methodAlreadyVerified ) return true ; MethodBinding [ ] methods = type . getMethods ( this . pattern . selector ) ; for ( int j = 0 , length = methods . length ; j < length ; j ++ ) { MethodBinding method = methods [ j ] ; TypeBinding [ ] parameters = method . parameters ; if ( argumentTypes . length == parameters . length ) { boolean found = true ; for ( int k = 0 , l = parameters . length ; k < l ; k ++ ) { if ( parameters [ k ] . erasure ( ) != argumentTypes [ k ] . erasure ( ) ) { found = false ; break ; } } if ( found ) { return true ; } } } break ; } } if ( type . isInterface ( ) ) { ReferenceBinding [ ] interfaces = type . superInterfaces ( ) ; if ( interfaces == null ) return false ; for ( int i = 0 ; i < interfaces . length ; i ++ ) { if ( resolveLevelAsSuperInvocation ( interfaces [ i ] , argumentTypes , false ) ) { return true ; } } } return false ; } public String toString ( ) { return "Locator for " + this . pattern . toString ( ) ; } } </s>