Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright (c) 2000, 2012 IBM Corporation and others. All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html Contributors: IBM Corporation - initial API and implementation Samrat Dhillon samrat.dhillon@gmail.com - Search for method references is returning methods as overriden even if the superclass's method is only package-visible - https://bugs.eclipse.org/357547 /
 
 package org.eclipse.jdt.internal.core.search.matching;
 
 
 import  org.eclipse.core.resources.IResource;
 import  org.eclipse.core.runtime.*;
 
 public class MethodLocator extends PatternLocator {
 
 protected MethodPattern pattern;
 
 //extra reference info
 public char[][][] allSuperDeclaringTypeNames;
 
 // This is set only if focus is null. In these cases
 // it will be hard to determine if the super class is of the same package
 // at a latter point. Hence, this array is created with all the super class 
 // names of the same package name as of the matching class name.
 // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=357547
 private char[][][] samePkgSuperDeclaringTypeNames;
 
 //method declarations which parameters verification fail
 
 
 public MethodLocator(MethodPattern pattern) {
 	super(pattern);
 
 	this. = pattern;
 }
 /*
  * Clear caches
  */
 protected void clear() {
 }
 protected int fineGrain() {
 	return this..;
 }
 
 	if (binding == nullreturn null;
 	ReferenceBinding superBinding = binding.superclass();
 	int level = resolveLevelForType(this..this..superBinding);
 	if (level != return superBinding;
 	// matches superclass
 	if (!binding.isInterface() && !CharOperation.equals(binding.compoundName.)) {
 		superBinding = getMatchingSuper(superBinding);
 		if (superBinding != nullreturn superBinding;
 	}
 	// matches interfaces
 	ReferenceBinding[] interfaces = binding.superInterfaces();
 	if (interfaces == nullreturn null;
 	for (int i = 0; i < interfaces.lengthi++) {
 		if (level != return interfaces[i];
 		superBinding = getMatchingSuper(interfaces[i]);
 		if (superBinding != nullreturn superBinding;
 	}
 	return null;
 }
 
 private MethodBinding getMethodBinding(ReferenceBinding typechar[] methodNameTypeBinding[] argumentTypes) {
 	MethodBinding[] methods = type.getMethods(methodName);
 	MethodBinding method = null;
 	methodsLoop: for (int i=0, length=methods.lengthi<lengthi++) {
 		method = methods[i];
 		TypeBinding[] parameters = method.parameters;
 		if (argumentTypes.length == parameters.length) {
 			for (int j=0,l=parameters.lengthj<lj++) {
 				if (parameters[j].erasure() != argumentTypes[j].erasure()) {
 					continue methodsLoop;
 				}
 			}
 			return method;
		}
	}
	return null;
public void initializePolymorphicSearch(MatchLocator locator) {
	long start = 0;
		start = System.currentTimeMillis();
	}
	try {
		SuperTypeNamesCollector namesCollector = 
				this.,
				locator,
				locator.progressMonitor);
		this. = namesCollector.collect();
		this. = locator;	
catch (JavaModelException e) {
		// inaccurate matches will be found
	}
		..println("Time to initialize polymorphic search: "+(System.currentTimeMillis()-start)); //$NON-NLS-1$
	}
/*
 * Return whether a type name is in pattern all super declaring types names.
 */
private boolean isTypeInSuperDeclaringTypeNames(char[][] typeName) {
	if (this. == nullreturn false;
	int length = this..length;
	for (int i= 0; i<lengthi++) {
		if (CharOperation.equals(this.[i], typeName)) {
			return true;
		}
	}
	return false;
Returns whether the code gen will use an invoke virtual for this message send or not.
protected boolean isVirtualInvoke(MethodBinding methodMessageSend messageSend) {
		return !method.isStatic() && !method.isPrivate() && !messageSend.isSuperAccess()
			&& !(method.isDefault() && this.. != null 
			&& !CharOperation.equals(this..method.declaringClass.qualifiedPackageName()));
public int match(ASTNode nodeMatchingNodeSet nodeSet) {
	int declarationsLevel = ;
	if (this..) {
		if (node instanceof ImportReference) {
			// With static import, we can have static method reference in import reference
			ImportReference importRef = (ImportReferencenode;
			int length = importRef.tokens.length-1;
			if (importRef.isStatic() && ((importRef.bits & .) == 0) && matchesName(this..importRef.tokens[length])) {
				char[][] compoundName = new char[length][];
				System.arraycopy(importRef.tokens, 0, compoundName, 0, length);
				char[] declaringType = CharOperation.concat(this..this..'.');
				if (matchesName(declaringType, CharOperation.concatWith(compoundName'.'))) {
					declarationsLevel = this.. ?  : ;
				}
			}
		}
	}
	return nodeSet.addMatch(nodedeclarationsLevel);
//public int match(ConstructorDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
//public int match(Expression node, MatchingNodeSet nodeSet) - SKIP IT
//public int match(FieldDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
public int match(MethodDeclaration nodeMatchingNodeSet nodeSet) {
	// Verify method name
	if (!matchesName(this..node.selector)) return ;
	// Verify parameters types
	boolean resolve = this..;
	if (this.. != null) {
		int length = this...length;
		ASTNode[] args = node.arguments;
		int argsLength = args == null ? 0 : args.length;
		if (length != argsLengthreturn ;
		for (int i = 0; i < argsLengthi++) {
			if (args != null && !matchesTypeReference(this..[i], ((Argumentargs[i]).)) {
				// Do not return as impossible when source level is at least 1.5
				if (this.) {
					if (!this..) {
						// Set resolution flag on node set in case of types was inferred in parameterized types from generic ones...
					 	// (see  bugs https://bugs.eclipse.org/bugs/show_bug.cgi?id=79990, 96761, 96763)
						nodeSet.mustResolve = true;
						resolve = true;
					}
else {
				}
			}
		}
	}
	// Verify type arguments (do not reject if pattern has no argument as it can be an erasure match)
		if (node.typeParameters == null || node.typeParameters.length != this...lengthreturn ;
	}
	// Method declaration may match pattern
	return nodeSet.addMatch(noderesolve ?  : );
public int match(MemberValuePair nodeMatchingNodeSet nodeSet) {
	if (!matchesName(this..node.name)) return ;
	return nodeSet.addMatch(nodethis.. ?  : );
public int match(MessageSend nodeMatchingNodeSet nodeSet) {
	if (!matchesName(this..node.selector)) return ;
	if (this.. != null && (!this.. || ((node.bits & .) != 0))) {
		int length = this...length;
		ASTNode[] args = node.arguments;
		int argsLength = args == null ? 0 : args.length;
		if (length != argsLengthreturn ;
	}
	return nodeSet.addMatch(nodethis.. ?  : );
//public int match(Reference node, MatchingNodeSet nodeSet) - SKIP IT
public int match(Annotation nodeMatchingNodeSet nodeSet) {
	MemberValuePair[] pairs = node.memberValuePairs();
	if (pairs == null || pairs.length == 0) return ;
	int length = pairs.length;
	MemberValuePair pair = null;
	for (int i=0; i<lengthi++) {
		pair = node.memberValuePairs()[i];
		if (matchesName(this..pair.name)) {
			ASTNode possibleNode = (node instanceof SingleMemberAnnotation) ? (ASTNodenode : pair;
			return nodeSet.addMatch(possibleNodethis.. ?  : );
		}
	}
//public int match(TypeDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
//public int match(TypeReference node, MatchingNodeSet nodeSet) - SKIP IT
protected int matchContainer() {
	if (this..) {
		// need to look almost everywhere to find in javadocs and static import
	}
/* (non-Javadoc)
 * @see org.eclipse.jdt.internal.core.search.matching.PatternLocator#matchLevelAndReportImportRef(org.eclipse.jdt.internal.compiler.ast.ImportReference, org.eclipse.jdt.internal.compiler.lookup.Binding, org.eclipse.jdt.internal.core.search.matching.MatchLocator)
 * Accept to report match of static field on static import
 */
protected void matchLevelAndReportImportRef(ImportReference importRefBinding bindingMatchLocator locatorthrows CoreException {
	if (importRef.isStatic() && binding instanceof MethodBinding) {
		super.matchLevelAndReportImportRef(importRefbindinglocator);
	}
protected int matchMethod(MethodBinding methodboolean skipImpossibleArg) {
	if (!matchesName(this..method.selector)) return ;
	int level = ;
	// look at return type only if declaring type is not specified
	if (this.. == null) {
		// TODO (frederic) use this call to refine accuracy on return type
		// int newLevel = resolveLevelForType(this.pattern.returnSimpleName, this.pattern.returnQualification, this.pattern.returnTypeArguments, 0, method.returnType);
		int newLevel = resolveLevelForType(this..this..method.returnType);
		if (level > newLevel) {
			if (newLevel == return ;
			level = newLevel// can only be downgraded
		}
	}
	// parameter types
	int parameterCount = this.. == null ? -1 : this...length;
	if (parameterCount > -1) {
		// global verification
		if (method.parameters == nullreturn ;
		if (parameterCount != method.parameters.lengthreturn ;
		if (!method.isValidBinding() && ((ProblemMethodBinding)method).problemId() == .) {
			// return inaccurate match for ambiguous call (bug 80890)
		}
		boolean foundTypeVariable = false;
		// verify each parameter
		for (int i = 0; i < parameterCounti++) {
			TypeBinding argType = method.parameters[i];
			int newLevel = ;
			if (argType.isMemberType()) {
				// only compare source name for member type (bug 41018)
				newLevel = CharOperation.match(this..[i], argType.sourceName(), this.)
else {
				// TODO (frederic) use this call to refine accuracy on parameter types
//				 newLevel = resolveLevelForType(this.pattern.parameterSimpleNames[i], this.pattern.parameterQualifications[i], this.pattern.parametersTypeArguments[i], 0, argType);
			}
			if (level > newLevel) {
				if (newLevel == ) {
					if (skipImpossibleArg) {
						// Do not consider match as impossible while finding declarations and source level >= 1.5
					 	// (see  bugs https://bugs.eclipse.org/bugs/show_bug.cgi?id=79990, 96761, 96763)
						newLevel = level;
else if (argType.isTypeVariable()) {
						newLevel = level;
						foundTypeVariable = true;
else {
					}
				}
				level = newLevel// can only be downgraded
			}
		}
		if (foundTypeVariable) {
			if (!method.isStatic() && !method.isPrivate()) {
				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=123836, No point in textually comparing type variables, captures etc with concrete types. 
				MethodBinding focusMethodBinding = this..getMethodBinding(this.);
				if (focusMethodBinding != null) {
					if (matchOverriddenMethod(focusMethodBinding.declaringClassfocusMethodBindingmethod)) {
					}
				}
		}
	}
	return level;
// This works for only methods of parameterized types.
private boolean matchOverriddenMethod(ReferenceBinding typeMethodBinding methodMethodBinding matchMethod) {
	if (type == null || this.. == nullreturn false;
	// matches superclass
	if (!type.isInterface() && !CharOperation.equals(type.compoundName.)) {
		ReferenceBinding superClass = type.superclass();
		if (superClass.isParameterizedType()) {
			MethodBinding[] methods = superClass.getMethods(this..);
			int length = methods.length;
			for (int i = 0; i<lengthi++) {
				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(superClassmethodmatchMethod)) {
			return true;
		}
	}
	// matches interfaces
	ReferenceBinding[] interfaces = type.superInterfaces();
	if (interfaces == nullreturn false;
	int iLength = interfaces.length;
	for (int i = 0; i<iLengthi++) {
		if (interfaces[i].isParameterizedType()) {
			MethodBinding[] methods = interfaces[i].getMethods(this..);
			int length = methods.length;
			for (int j = 0; j<lengthj++) {
				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], methodmatchMethod)) {
			return true;
		}
	}
	return false;
protected void matchReportReference(ASTNode referenceIJavaElement elementBinding elementBindingint accuracyMatchLocator locatorthrows CoreException {
	matchReportReference(referenceelementnullnullelementBindingaccuracylocator);

See also:
org.eclipse.jdt.internal.core.search.matching.PatternLocator.matchReportReference(org.eclipse.jdt.internal.compiler.ast.ASTNode, org.eclipse.jdt.core.IJavaElement, Binding, int, org.eclipse.jdt.internal.core.search.matching.MatchLocator)
protected void matchReportReference(ASTNode referenceIJavaElement elementIJavaElement localElementIJavaElement[] otherElementsBinding elementBindingint accuracyMatchLocator locatorthrows CoreException {
	MethodBinding methodBinding = (reference instanceof MessageSend) ? ((MessageSend)reference).: ((elementBinding instanceof MethodBinding) ? (MethodBindingelementBinding : null);
		if (methodBinding == nullreturn;
		// need exact match to be able to open on type ref
		if (accuracy != .return;
		// element that references the method must be included in the enclosing element
		while (element != null && !declPattern.enclosingElement.equals(element))
			element = element.getParent();
		if (element != null) {
			reportDeclaration(methodBindinglocatordeclPattern.knownMethods);
		}
else {
		MethodReferenceMatch methodReferenceMatch = locator.newMethodReferenceMatch(elementelementBindingaccuracy, -1, -1, false /*not constructor*/false/*not synthetic*/reference);
		methodReferenceMatch.setLocalElement(localElement);
		this. = methodReferenceMatch;
		if (this.. && reference instanceof MessageSend) {
			IJavaElement focus = this..;
			// verify closest match if pattern was bound
			// (see bug 70827)
			if (focus != null && focus.getElementType() == .) {
				if (methodBinding != null && methodBinding.declaringClass != null) {
					boolean isPrivate = Flags.isPrivate(((IMethodfocus).getFlags());
					if (isPrivate && !CharOperation.equals(methodBinding.declaringClass.sourceNamefocus.getParent().getElementName().toCharArray())) {
						return// finally the match was not possible
					}
				}
			}
			matchReportReference((MessageSend)referencelocatoraccuracy, ((MessageSend)reference).);
else {
			if (reference instanceof SingleMemberAnnotation) {
				reference = ((SingleMemberAnnotation)reference).memberValuePairs()[0];
				this..setImplicit(true);
			}
			int offset = reference.sourceStart;
			int length =  reference.sourceEnd - offset + 1;
			this..setOffset(offset);
			this..setLength(length);
			locator.report(this.);
		}
	}
void matchReportReference(MessageSend messageSendMatchLocator locatorint accuracyMethodBinding methodBindingthrows CoreException {
	// Look if there's a need to special report for parameterized type
	boolean isParameterized = false;
	if (methodBinding instanceof ParameterizedGenericMethodBinding) { // parameterized generic method
		isParameterized = true;
		// Update match regarding method type arguments
		ParameterizedGenericMethodBinding parameterizedMethodBinding = (ParameterizedGenericMethodBindingmethodBinding;
		this..setRaw(parameterizedMethodBinding.isRaw);
		TypeBinding[] typeArguments = /*parameterizedMethodBinding.isRaw ? null :*/ parameterizedMethodBinding.typeArguments;
		updateMatch(typeArgumentslocatorthis..this..hasMethodParameters());
		// Update match regarding declaring class type arguments
		if (methodBinding.declaringClass.isParameterizedType() || methodBinding.declaringClass.isRawType()) {
			ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding)methodBinding.declaringClass;
			if (!this..hasTypeArguments() && this..hasMethodArguments() || parameterizedBinding.isParameterizedWithOwnVariables()) {
				// special case for pattern which defines method arguments but not its declaring type
				// in this case, we do not refine accuracy using declaring type arguments...!
else {
				updateMatch(parameterizedBindingthis..getTypeArguments(), this..hasTypeParameters(), 0, locator);
			}
else if (this..hasTypeArguments()) {
		}
		// Update match regarding method parameters
		// TODO ? (frederic)
		// Update match regarding method return type
		// TODO ? (frederic)
		// Special case for errors
		if (this..getRule() != 0 && messageSend.resolvedType == null) {
		}
else if (methodBinding instanceof ParameterizedMethodBinding) {
		isParameterized = true;
		if (methodBinding.declaringClass.isParameterizedType() || methodBinding.declaringClass.isRawType()) {
			ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding)methodBinding.declaringClass;
			if (!parameterizedBinding.isParameterizedWithOwnVariables()) {
				if ((accuracy & ( | )) != 0) {
					// type parameters need to be compared with the class that is really being searched
					// https://bugs.eclipse.org/375971
					ReferenceBinding refBinding = getMatchingSuper(((ReferenceBinding)messageSend.actualReceiverType));
					if (refBinding instanceof ParameterizedTypeBinding) {
						parameterizedBinding = ((ParameterizedTypeBinding)refBinding);
					}
				}
				if ((accuracy & ) == 0) {
					// not able to get the type parameters if the match is super
					updateMatch(parameterizedBindingthis..getTypeArguments(), this..hasTypeParameters(), 0, locator);
				}
			}
else if (this..hasTypeArguments()) {
		}
		// Update match regarding method parameters
		// TODO ? (frederic)
		// Update match regarding method return type
		// TODO ? (frederic)
		// Special case for errors
		if (this..getRule() != 0 && messageSend.resolvedType == null) {
		}
else if (this..hasMethodArguments()) { // binding has no type params, compatible erasure if pattern does
	}
	// See whether it is necessary to report or not
	if (this..getRule() == 0) return// impossible match
	boolean report = (this. && this..isErasure()) || (this. && this..isEquivalent()) || this..isExact();
	if (!reportreturn;
	// Report match
	int offset = (int) (messageSend.nameSourcePosition >>> 32);
	this..setOffset(offset);
	this..setLength(messageSend.sourceEnd - offset + 1);
	 if (isParameterized && this..hasMethodArguments())  {
		locator.reportAccurateParameterizedMethodReference(this.messageSendmessageSend.typeArguments);
else {
		locator.report(this.);
	}
/*
 * Return whether method parameters are equals to pattern ones.
 */
private boolean methodParametersEqualsPattern(MethodBinding method) {
	TypeBinding[] methodParameters = method.parameters;
	int length = methodParameters.length;
	if (length != this...lengthreturn false;
	for (int i = 0; i < lengthi++) {
		char[] paramQualifiedName = qualifiedPattern(this..[i], this..[i]);
		if (!CharOperation.match(paramQualifiedNamemethodParameters[i].readableName(), this.)) {
			return false;
		}
	}
	return true;
public SearchMatch newDeclarationMatch(ASTNode referenceIJavaElement elementBinding elementBindingint accuracyint lengthMatchLocator locator) {
	if (elementBinding != null) {
		MethodBinding methodBinding = (MethodBindingelementBinding;
		// If method parameters verification was not valid, then try to see if method arguments can match a method in hierarchy
			// First see if this reference has already been resolved => report match if validated
			Boolean report = (Booleanthis..get(reference);
			if (report != null) {
				if (report.booleanValue()) {
					return super.newDeclarationMatch(referenceelementelementBindingaccuracylengthlocator);
				}
				return null;
			}
			if (matchOverriddenMethod(methodBinding.declaringClassmethodBindingnull)) {
				return super.newDeclarationMatch(referenceelementelementBindingaccuracylengthlocator);
			}
			if (isTypeInSuperDeclaringTypeNames(methodBinding.declaringClass.compoundName)) {
				MethodBinding patternBinding = locator.getMethodBinding(this.);
				if (patternBinding != null) {
					if (!matchOverriddenMethod(patternBinding.declaringClasspatternBindingmethodBinding)) {
						return null;
					}
				}
				return super.newDeclarationMatch(referenceelementelementBindingaccuracylengthlocator);
			}
			return null;
		}
	}
	return super.newDeclarationMatch(referenceelementelementBindingaccuracylengthlocator);
protected int referenceType() {
protected void reportDeclaration(MethodBinding methodBindingMatchLocator locatorSimpleSet knownMethodsthrows CoreException {
	ReferenceBinding declaringClass = methodBinding.declaringClass;
	IType type = locator.lookupType(declaringClass);
	if (type == nullreturn// case of a secondary type
	// Report match for binary
	if (type.isBinary()) {
		IMethod method = null;
		TypeBinding[] parameters = methodBinding.original().;
		int parameterLength = parameters.length;
		char[][] parameterTypes = new char[parameterLength][];
		for (int i = 0; i<parameterLengthi++) {
			char[] typeName = parameters[i].qualifiedSourceName();
			for (int j=0, dim=parameters[i].dimensions(); j<dimj++) {
				typeName = CharOperation.concat(typeNamenew char[] {'['']'});
			}
			parameterTypes[i] = typeName;
		}
		method = locator.createBinaryMethodHandle(typemethodBinding.selectorparameterTypes);
		if (method == null || knownMethods.addIfNotIncluded(method) == nullreturn;
		IResource resource = type.getResource();
		if (resource == null)
			resource = type.getJavaProject().getProject();
		locator.reportBinaryMemberDeclaration(resourcemethodmethodBindinginfo.);
		return;
	}
	// When source is available, report match if method is found in the declaring type
	IResource resource = type.getResource();
	if (declaringClass instanceof ParameterizedTypeBinding)
		declaringClass = ((ParameterizedTypeBindingdeclaringClass).genericType();
	ClassScope scope = ((SourceTypeBindingdeclaringClass).;
	if (scope != null) {
		TypeDeclaration typeDecl = scope.referenceContext;
		AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(methodBinding.original());
		if (methodDecl != null) {
			// Create method handle from method declaration
			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  < lengthi++) {
				char[][] typeName = arguments[i]..getParameterizedTypeName();
				parameterTypes[i] = Signature.createTypeSignature(CharOperation.concatWith(typeName'.'), false);
			}
			IMethod method = type.getMethod(methodNameparameterTypes);
			if (method == null || knownMethods.addIfNotIncluded(method) == nullreturn;
			// Create and report corresponding match
			int offset = methodDecl.sourceStart;
			this. = new MethodDeclarationMatch(method.offsetmethodDecl.sourceEnd-offset+1, locator.getParticipant(), resource);
			locator.report(this.);
		}
	}
public int resolveLevel(ASTNode possibleMatchingNode) {
	if (this..) {
		if (possibleMatchingNode instanceof MessageSend) {
			return resolveLevel((MessageSendpossibleMatchingNode);
		}
		if (possibleMatchingNode instanceof SingleMemberAnnotation) {
			SingleMemberAnnotation annotation = (SingleMemberAnnotationpossibleMatchingNode;
			return resolveLevel(annotation.memberValuePairs()[0].);
		}
		if (possibleMatchingNode instanceof MemberValuePair) {
			MemberValuePair memberValuePair = (MemberValuePairpossibleMatchingNode;
			return resolveLevel(memberValuePair.binding);
		}
	}
		if (possibleMatchingNode instanceof MethodDeclaration) {
			return resolveLevel(((MethodDeclarationpossibleMatchingNode).);
		}
	}
public int resolveLevel(Binding binding) {
	if (binding == nullreturn ;
	if (!(binding instanceof MethodBinding)) return ;
	MethodBinding method = (MethodBindingbinding;
	boolean skipVerif = this.. && this.;
	int methodLevel = matchMethod(methodskipVerif);
	if (methodLevel == ) {
		if (method != method.original()) methodLevel = matchMethod(method.original(), skipVerif);
		if (methodLevel == ) {
else {
			method = method.original();
		}
	}
	// declaring type
	if (this.. == null && this.. == nullreturn methodLevel// since any declaring class will do
	boolean subType = !method.isStatic() && !method.isPrivate();
	if (subType && this.. != null && method.declaringClass != null && method.declaringClass.fPackage != null) {
		subType = CharOperation.compareWith(this..method.declaringClass.fPackage.shortReadableName()) == 0;
	}
	int declaringLevel = subType
resolveLevelAsSubtype(this..this..method.declaringClassmethod.selectornullmethod.declaringClass.qualifiedPackageName(), method.isDefault())
	return (methodLevel & ) > (declaringLevel & ) ? declaringLevel : methodLevel// return the weaker match
protected int resolveLevel(MessageSend messageSend) {
	MethodBinding method = messageSend.binding;
	if (method == null) {
	}
	if (messageSend.resolvedType == null) {
		// Closest match may have different argument numbers when ProblemReason is NotFound
		// see MessageSend#resolveType(BlockScope)
		// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=97322
		int argLength = messageSend.arguments == null ? 0 : messageSend.arguments.length;
		if (this.. == null || argLength == this...length) {
		}
	}
	int methodLevel = matchMethod(methodfalse);
	if (methodLevel == ) {
		if (method != method.original()) methodLevel = matchMethod(method.original(), false);
		if (methodLevel == return ;
		method = method.original();
	}
	// receiver type
	if (this.. == null && this.. == nullreturn methodLevel// since any declaring class will do
	int declaringLevel;
	if (isVirtualInvoke(methodmessageSend) && (messageSend.actualReceiverType instanceof ReferenceBinding)) {
		ReferenceBinding methodReceiverType = (ReferenceBindingmessageSend.actualReceiverType;
		declaringLevel = resolveLevelAsSubtype(this..this..methodReceiverTypemethod.selectormethod.parametersmethodReceiverType.qualifiedPackageName(), method.isDefault());
		if (declaringLevel == ) {
			if (method.declaringClass == null || this. == null) {
				declaringLevel = ;
else {
				char[][][] superTypeNames = (method.isDefault() && this.. == null) ? this.this.;
				if (superTypeNames != null && resolveLevelAsSuperInvocation(methodReceiverTypemethod.parameterssuperTypeNamestrue)) {
						declaringLevel = methodLevel // since this is an ACCURATE_MATCH so return the possibly weaker match
// this is an overridden method => add flavor to returned level
				}
			}
		}
		if ((declaringLevel & ) != 0) {
			// level got some flavors => return it
			return declaringLevel;
		}
else {
		declaringLevel = resolveLevelForType(this..this..method.declaringClass);
	}
	return (methodLevel & ) > (declaringLevel & ) ? declaringLevel : methodLevel// return the weaker match
Returns whether the given reference type binding matches or is a subtype of a type that matches the given qualified pattern. Returns ACCURATE_MATCH if it does. Returns INACCURATE_MATCH if resolve fails Returns IMPOSSIBLE_MATCH if it doesn't.
protected int resolveLevelAsSubtype(char[] simplePatternchar[] qualifiedPatternReferenceBinding typechar[] methodNameTypeBinding[] argumentTypeschar[] packageNameboolean isDefault) {
	if (type == nullreturn ;
	int level = resolveLevelForType(simplePatternqualifiedPatterntype);
	if (level != ) {
		if (isDefault && !CharOperation.equals(packageNametype.qualifiedPackageName())) {
		}
		MethodBinding method = argumentTypes == null ? null : getMethodBinding(typemethodNameargumentTypes);
		if (((method != null && !method.isAbstract()) || !type.isAbstract()) && !type.isInterface()) { // if concrete, then method is overridden
		}
		return level;
	}
	// matches superclass
	if (!type.isInterface() && !CharOperation.equals(type.compoundName.)) {
		level = resolveLevelAsSubtype(simplePatternqualifiedPatterntype.superclass(), methodNameargumentTypespackageNameisDefault);
		if (level != ) {
			if (argumentTypes != null) {
				// need to verify if method may be overridden
				MethodBinding method = getMethodBinding(typemethodNameargumentTypes);
				if (method != null) { // one method match in hierarchy
					if ((level & ) != 0) {
						// this method is already overridden on a super class, current match is impossible
					}
					if (!method.isAbstract() && !type.isInterface()) {
						// store the fact that the method is overridden
					}
				}
			}
			return level | // add flavor to returned level
		}
	}
	// matches interfaces
	ReferenceBinding[] interfaces = type.superInterfaces();
	if (interfaces == nullreturn ;
	for (int i = 0; i < interfaces.lengthi++) {
		level = resolveLevelAsSubtype(simplePatternqualifiedPatterninterfaces[i], methodNamenullpackageNameisDefault);
		if (level != ) {
			if (!type.isAbstract() && !type.isInterface()) { // if concrete class, then method is overridden
			}
			return level | // add flavor to returned level
		}
	}
/*
 * Return whether the given type binding or one of its possible super interfaces
 * matches a type in the declaring type names hierarchy.
 */
private boolean resolveLevelAsSuperInvocation(ReferenceBinding typeTypeBinding[] argumentTypeschar[][][] superTypeNamesboolean methodAlreadyVerified) {
	char[][] compoundName = type.compoundName;
	for (int i = 0, max = superTypeNames.lengthi < maxi++) {
		if (CharOperation.equals(superTypeNames[i], compoundName)) {
			// need to verify if the type implements the pattern method
			if (methodAlreadyVerifiedreturn true// already verified before enter into this method (see resolveLevel(MessageSend))
			MethodBinding[] methods = type.getMethods(this..);
			for (int j=0, length=methods.lengthj<lengthj++) {
				MethodBinding method = methods[j];
				TypeBinding[] parameters = method.parameters;
				if (argumentTypes.length == parameters.length) {
					boolean found = true;
					for (int k=0,l=parameters.lengthk<lk++) {
						if (parameters[k].erasure() != argumentTypes[k].erasure()) {
							found = false;
							break;
						}
					}
					if (found) {
						return true;
					}
				}
			}
			break;
		}
	}
	// If the given type is an interface then a common super interface may be found
	// in a parallel branch of the super hierarchy, so we need to verify all super interfaces.
	// If it's a class then there's only one possible branch for the hierarchy and
	// this branch has been already verified by the test above
	if (type.isInterface()) {
		ReferenceBinding[] interfaces = type.superInterfaces();
		if (interfaces == nullreturn false;
		for (int i = 0; i < interfaces.lengthi++) {
			if (resolveLevelAsSuperInvocation(interfaces[i], argumentTypessuperTypeNamesfalse)) {
				return true;
			}
		}
	}
	return false;
public String toString() {
	return "Locator for " + this..toString(); //$NON-NLS-1$