/*******************************************************************************
 * Copyright (c) 2000, 2010 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
 *******************************************************************************/
package org.eclipse.jdt.internal.core.search.matching;

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.JavaElement;

public class TypeReferenceLocator extends PatternLocator {

protected TypeReferencePattern pattern;
protected boolean isDeclarationOfReferencedTypesPattern;

private final int fineGrain;

public TypeReferenceLocator(TypeReferencePattern pattern) {

	super(pattern);

	this.pattern = pattern;
	this.fineGrain = pattern == null ? 0 : pattern.fineGrain;
	this.isDeclarationOfReferencedTypesPattern = this.pattern instanceof DeclarationOfReferencedTypesPattern;
}
protected IJavaElement findElement(IJavaElement element, int accuracy) {
	// need exact match to be able to open on type ref
	if (accuracy != SearchMatch.A_ACCURATE) return null;

	// element that references the type must be included in the enclosing element
	DeclarationOfReferencedTypesPattern declPattern = (DeclarationOfReferencedTypesPattern) this.pattern;
	while (element != null && !declPattern.enclosingElement.equals(element))
		element = element.getParent();
	return element;
}
protected int fineGrain() {
	return this.fineGrain;
}
public int match(Annotation node, MatchingNodeSet nodeSet) {
	return match(node.type, nodeSet);
}
public int match(ASTNode node, MatchingNodeSet nodeSet) { // interested in ImportReference
	if (!(node instanceof ImportReference)) return IMPOSSIBLE_MATCH;

	return nodeSet.addMatch(node, matchLevel((ImportReference) node));
}
//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 node, MatchingNodeSet nodeSet) - SKIP IT
//public int match(MessageSend node, MatchingNodeSet nodeSet) - SKIP IT
public int match(Reference node, MatchingNodeSet nodeSet) { // interested in NameReference & its subtypes
	if (!(node instanceof NameReference)) return IMPOSSIBLE_MATCH;

	if (this.pattern.simpleName == null)
		return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);

	if (node instanceof SingleNameReference) {
		if (matchesName(this.pattern.simpleName, ((SingleNameReference) node).token))
			return nodeSet.addMatch(node, POSSIBLE_MATCH); // resolution is needed to find out if it is a type ref
	} else {
		char[][] tokens = ((QualifiedNameReference) node).tokens;
		for (int i = 0, max = tokens.length; i < max; i++)
			if (matchesName(this.pattern.simpleName, tokens[i]))
				return nodeSet.addMatch(node, POSSIBLE_MATCH); // resolution is needed to find out if it is a type ref
	}

	return IMPOSSIBLE_MATCH;
}
//public int match(TypeDeclaration node, MatchingNodeSet nodeSet) - SKIP IT
public int match(TypeReference node, MatchingNodeSet nodeSet) {
	if (this.pattern.simpleName == null)
		return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);

	if (node instanceof SingleTypeReference) {
		if (matchesName(this.pattern.simpleName, ((SingleTypeReference) node).token))
			return nodeSet.addMatch(node, this.pattern.mustResolve ? POSSIBLE_MATCH : ACCURATE_MATCH);
	} else {
		char[][] tokens = ((QualifiedTypeReference) node).tokens;
		for (int i = 0, max = tokens.length; i < max; i++)
			if (matchesName(this.pattern.simpleName, tokens[i]))
				return nodeSet.addMatch(node, POSSIBLE_MATCH); // resolution is needed to find out if it is a type ref
	}

	return IMPOSSIBLE_MATCH;
}

protected int matchLevel(ImportReference importRef) {
	if (this.pattern.qualification == null) {
		if (this.pattern.simpleName == null) return ACCURATE_MATCH;
		char[][] tokens = importRef.tokens;
		boolean onDemand = (importRef.bits & ASTNode.OnDemand) != 0;
		final boolean isStatic = importRef.isStatic();
		if (!isStatic && onDemand) {
			return IMPOSSIBLE_MATCH;
		}
		int length = tokens.length;
		if (matchesName(this.pattern.simpleName, tokens[length-1])) {
			return ACCURATE_MATCH;
		}
		if (isStatic && !onDemand && length > 1) {
			if (matchesName(this.pattern.simpleName, tokens[length-2])) {
				return ACCURATE_MATCH;
			}
		}
	} else {
		char[][] tokens = importRef.tokens;
		char[] qualifiedPattern = this.pattern.simpleName == null
			? this.pattern.qualification
			: CharOperation.concat(this.pattern.qualification, this.pattern.simpleName, '.');
		char[] qualifiedTypeName = CharOperation.concatWith(tokens, '.');
		if (qualifiedPattern == null) return ACCURATE_MATCH; // null is as if it was "*"
		if (qualifiedTypeName == null) return IMPOSSIBLE_MATCH; // cannot match null name
		if (qualifiedTypeName.length == 0) { // empty name
			if (qualifiedPattern.length == 0) { // can only matches empty pattern
				return ACCURATE_MATCH;
			}
			return IMPOSSIBLE_MATCH;
		}
		boolean matchFirstChar = !this.isCaseSensitive || (qualifiedPattern[0] == qualifiedTypeName[0]);
		switch (this.matchMode) {
			case SearchPattern.R_EXACT_MATCH:
			case SearchPattern.R_PREFIX_MATCH:
				if (CharOperation.prefixEquals(qualifiedPattern, qualifiedTypeName, this.isCaseSensitive)) {
					return POSSIBLE_MATCH;
				}
				break;

			case SearchPattern.R_PATTERN_MATCH:
				if (CharOperation.match(qualifiedPattern, qualifiedTypeName, this.isCaseSensitive)) {
					return POSSIBLE_MATCH;
				}
				break;

			case SearchPattern.R_REGEXP_MATCH :
				// TODO (frederic) implement regular expression match
				break;
			case SearchPattern.R_CAMELCASE_MATCH:
				if (matchFirstChar && CharOperation.camelCaseMatch(qualifiedPattern, qualifiedTypeName, false)) {
					return POSSIBLE_MATCH;
				}
				// only test case insensitive as CamelCase already verified prefix case sensitive
				if (!this.isCaseSensitive && CharOperation.prefixEquals(qualifiedPattern, qualifiedTypeName, false)) {
					return POSSIBLE_MATCH;
				}
				break;
			case SearchPattern.R_CAMELCASE_SAME_PART_COUNT_MATCH:
				if (matchFirstChar && CharOperation.camelCaseMatch(qualifiedPattern, qualifiedTypeName, true)) {
					return POSSIBLE_MATCH;
				}
				break;
		}
	}
	return IMPOSSIBLE_MATCH;
}
/* (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)
 */
protected void matchLevelAndReportImportRef(ImportReference importRef, Binding binding, MatchLocator locator) throws CoreException {
	Binding refBinding = binding;
	if (importRef.isStatic()) {
		// for static import, binding can be a field binding or a member type binding
		// verify that in this case binding is static and use declaring class for fields
		if (binding instanceof FieldBinding) {
			FieldBinding fieldBinding = (FieldBinding) binding;
			if (!fieldBinding.isStatic()) return;
			refBinding = fieldBinding.declaringClass;
		} else if (binding instanceof MethodBinding) {
			MethodBinding methodBinding = (MethodBinding) binding;
			if (!methodBinding.isStatic()) return;
			refBinding = methodBinding.declaringClass;
		} else if (binding instanceof MemberTypeBinding) {
			MemberTypeBinding memberBinding = (MemberTypeBinding) binding;
			if (!memberBinding.isStatic()) return;
		}
		// resolve and report
		int level = resolveLevel(refBinding);
		if (level >= INACCURATE_MATCH) {
			matchReportImportRef(
				importRef,
				binding,
				locator.createImportHandle(importRef),
				level == ACCURATE_MATCH
					? SearchMatch.A_ACCURATE
					: SearchMatch.A_INACCURATE,
				locator);
		}
		return;
	}
	super.matchLevelAndReportImportRef(importRef, refBinding, locator);
}
protected void matchReportImportRef(ImportReference importRef, Binding binding, IJavaElement element, int accuracy, MatchLocator locator) throws CoreException {
	if (this.isDeclarationOfReferencedTypesPattern) {
		if ((element = findElement(element, accuracy)) != null) {
			SimpleSet knownTypes = ((DeclarationOfReferencedTypesPattern) this.pattern).knownTypes;
			while (binding instanceof ReferenceBinding) {
				ReferenceBinding typeBinding = (ReferenceBinding) binding;
				reportDeclaration(typeBinding, 1, locator, knownTypes);
				binding = typeBinding.enclosingType();
			}
		}
		return;
	}

	// return if this is not necessary to report
	if (this.pattern.hasTypeArguments() && !this.isEquivalentMatch &&!this.isErasureMatch) {
		return;
	}

	// Return if fine grain is on and does not concern import reference
	if ((this.pattern.fineGrain != 0 && (this.pattern.fineGrain & IJavaSearchConstants.IMPORT_DECLARATION_TYPE_REFERENCE) == 0)) {
		return;
	}

	// Create search match
	this.match = locator.newTypeReferenceMatch(element, binding, accuracy, importRef);

	// set match raw flag and rule
	this.match.setRaw(true);
	if (this.pattern.hasTypeArguments()) {
		// binding is raw => only compatible erasure if pattern has type arguments
		this.match.setRule(this.match.getRule() & (~SearchPattern.R_FULL_MATCH));
	}

	// Try to find best selection for match
	TypeBinding typeBinding = null;
	boolean lastButOne = false;
	if (binding instanceof ReferenceBinding) {
		typeBinding = (ReferenceBinding) binding;
	} else if (binding instanceof FieldBinding) { // may happen for static import
		typeBinding = ((FieldBinding)binding).declaringClass;
		lastButOne = importRef.isStatic() && ((importRef.bits & ASTNode.OnDemand) == 0);
	} else if (binding instanceof MethodBinding) { // may happen for static import
		typeBinding = ((MethodBinding)binding).declaringClass;
		lastButOne = importRef.isStatic() && ((importRef.bits & ASTNode.OnDemand) == 0);
	}
	if (typeBinding != null) {
		int lastIndex = importRef.tokens.length - 1;
		if (lastButOne) {
			// for field or method static import, use last but one token
			lastIndex--;
		}
		if (typeBinding instanceof ProblemReferenceBinding) {
			ProblemReferenceBinding pbBinding = (ProblemReferenceBinding) typeBinding;
			typeBinding = pbBinding.closestMatch();
			lastIndex = pbBinding.compoundName.length - 1;
		}
		// try to match all enclosing types for which the token matches as well.
		while (typeBinding != null && lastIndex >= 0) {
			if (resolveLevelForType(typeBinding) != IMPOSSIBLE_MATCH) {
				if (locator.encloses(element)) {
					long[] positions = importRef.sourcePositions;
					// index now depends on pattern type signature
					int index = lastIndex;
					if (this.pattern.qualification != null) {
						index = lastIndex - this.pattern.segmentsSize;
					}
					if (index < 0) index = 0;
					int start = (int) ((positions[index]) >>> 32);
					int end = (int) positions[lastIndex];
					// report match
					this.match.setOffset(start);
					this.match.setLength(end-start+1);
					locator.report(this.match);
				}
				return;
			}
			lastIndex--;
			typeBinding = typeBinding.enclosingType();
		}
	}
	locator.reportAccurateTypeReference(this.match, importRef, this.pattern.simpleName);
}
protected void matchReportReference(ArrayTypeReference arrayRef, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
	if (this.pattern.simpleName == null) {
		// TODO (frederic) need to add a test for this case while searching generic types...
		if (locator.encloses(element)) {
			int offset = arrayRef.sourceStart;
			int length = arrayRef.sourceEnd-offset+1;
			if (this.match == null) {
				this.match = locator.newTypeReferenceMatch(element, elementBinding, accuracy, offset, length, arrayRef);
			} else {
				this.match.setOffset(offset);
				this.match.setLength(length);
			}
			locator.report(this.match);
			return;
		}
	}
	this.match = locator.newTypeReferenceMatch(element, elementBinding, accuracy, arrayRef);
	if (arrayRef.resolvedType != null) {
		matchReportReference(arrayRef, -1, arrayRef.resolvedType.leafComponentType(), locator);
		return;
	}
	locator.reportAccurateTypeReference(this.match, arrayRef, this.pattern.simpleName);
}
/**
 * Reports the match of the given reference.
 */
protected void matchReportReference(ASTNode reference, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
	matchReportReference(reference, element, null, null, elementBinding, accuracy, locator);
}
/**
 * Reports the match of the given reference. Also provide a local and other elements to eventually report in match.
 */
protected void matchReportReference(ASTNode reference, IJavaElement element, IJavaElement localElement, IJavaElement[] otherElements, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
	if (this.isDeclarationOfReferencedTypesPattern) {
		if ((element = findElement(element, accuracy)) != null)
			reportDeclaration(reference, element, locator, ((DeclarationOfReferencedTypesPattern) this.pattern).knownTypes);
		return;
	}

	// Create search match
	TypeReferenceMatch refMatch = locator.newTypeReferenceMatch(element, elementBinding, accuracy, reference);
	refMatch.setLocalElement(localElement);
	refMatch.setOtherElements(otherElements);
	this.match = refMatch;

	// Report match depending on reference type
	if (reference instanceof QualifiedNameReference)
		matchReportReference((QualifiedNameReference) reference, element, elementBinding, accuracy, locator);
	else if (reference instanceof QualifiedTypeReference)
		matchReportReference((QualifiedTypeReference) reference, element, elementBinding, accuracy, locator);
	else if (reference instanceof ArrayTypeReference)
		matchReportReference((ArrayTypeReference) reference, element, elementBinding, accuracy, locator);
	else {
		TypeBinding typeBinding = reference instanceof Expression ? ((Expression)reference).resolvedType : null;
		if (typeBinding != null) {
			matchReportReference((Expression)reference, -1, typeBinding, locator);
			return;
		}
		locator.report(this.match);
	}
}
protected void matchReportReference(QualifiedNameReference qNameRef, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
	Binding binding = qNameRef.binding;
	TypeBinding typeBinding = null;
	int lastIndex = qNameRef.tokens.length - 1;
	switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
		case Binding.FIELD : // reading a field
			typeBinding = qNameRef.actualReceiverType;
			lastIndex -= qNameRef.otherBindings == null ? 1 : qNameRef.otherBindings.length + 1;
			break;
		case Binding.TYPE : //=============only type ==============
			if (binding instanceof TypeBinding)
				typeBinding = (TypeBinding) binding;
			break;
		case Binding.VARIABLE : //============unbound cases===========
		case Binding.TYPE | Binding.VARIABLE :
			if (binding instanceof ProblemReferenceBinding) {
				typeBinding = (TypeBinding) binding;
			} else if (binding instanceof ProblemFieldBinding) {
				typeBinding = qNameRef.actualReceiverType;
				lastIndex -= qNameRef.otherBindings == null ? 1 : qNameRef.otherBindings.length + 1;
			} else if (binding instanceof ProblemBinding) {
				typeBinding = ((ProblemBinding) binding).searchType;
			}
			break;
	}
	if (typeBinding instanceof ProblemReferenceBinding) {
		ProblemReferenceBinding pbBinding = (ProblemReferenceBinding) typeBinding;
		typeBinding = pbBinding.closestMatch();
		lastIndex = pbBinding.compoundName.length - 1;
	}

	// Create search match to report
	if (this.match == null) {
		this.match = locator.newTypeReferenceMatch(element, elementBinding, accuracy, qNameRef);
	}

	// try to match all enclosing types for which the token matches as well.
	if (typeBinding instanceof ReferenceBinding) {
		ReferenceBinding refBinding = (ReferenceBinding) typeBinding;
		while (refBinding != null && lastIndex >= 0) {
			if (resolveLevelForType(refBinding) == ACCURATE_MATCH) {
				if (locator.encloses(element)) {
					long[] positions = qNameRef.sourcePositions;
					// index now depends on pattern type signature
					int index = lastIndex;
					if (this.pattern.qualification != null) {
						index = lastIndex - this.pattern.segmentsSize;
					}
					if (index < 0) index = 0;
					int start = (int) ((positions[index]) >>> 32);
					int end = (int) positions[lastIndex];
					this.match.setOffset(start);
					this.match.setLength(end-start+1);

					//  Look if there's a need to special report for parameterized type
					matchReportReference(qNameRef, lastIndex, refBinding, locator);
				}
				return;
			}
			lastIndex--;
			refBinding = refBinding.enclosingType();
		}
	}
	locator.reportAccurateTypeReference(this.match, qNameRef, this.pattern.simpleName);
}
protected void matchReportReference(QualifiedTypeReference qTypeRef, IJavaElement element, Binding elementBinding, int accuracy, MatchLocator locator) throws CoreException {
	TypeBinding typeBinding = qTypeRef.resolvedType;
	int lastIndex = qTypeRef.tokens.length - 1;
	if (typeBinding instanceof ArrayBinding)
		typeBinding = ((ArrayBinding) typeBinding).leafComponentType;
	if (typeBinding instanceof ProblemReferenceBinding) {
		ProblemReferenceBinding pbBinding = (ProblemReferenceBinding) typeBinding;
		typeBinding = pbBinding.closestMatch();
		lastIndex = pbBinding.compoundName.length - 1;
	}

	// Create search match to report
	if (this.match == null) {
		this.match = locator.newTypeReferenceMatch(element, elementBinding, accuracy, qTypeRef);
	}

	// try to match all enclosing types for which the token matches as well
	if (typeBinding instanceof ReferenceBinding) {
		ReferenceBinding refBinding = (ReferenceBinding) typeBinding;
		while (refBinding != null && lastIndex >= 0) {
			if (resolveLevelForType(refBinding) != IMPOSSIBLE_MATCH) {
				if (locator.encloses(element)) {
					long[] positions = qTypeRef.sourcePositions;
					// index now depends on pattern type signature
					int index = lastIndex;
					if (this.pattern.qualification != null) {
						index = lastIndex - this.pattern.segmentsSize;
					}
					if (index < 0) index = 0;
					int start = (int) ((positions[index]) >>> 32);
					int end = (int) positions[lastIndex];
					this.match.setOffset(start);
					this.match.setLength(end-start+1);

					//  Look if there's a need to special report for parameterized type
					matchReportReference(qTypeRef, lastIndex, refBinding, locator);
				}
				return;
			}
			lastIndex--;
			refBinding = refBinding.enclosingType();
		}
	}
	locator.reportAccurateTypeReference(this.match, qTypeRef, this.pattern.simpleName);
}
void matchReportReference(Expression expr, int lastIndex, TypeBinding refBinding, MatchLocator locator) throws CoreException {

	// Look if there's a need to special report for parameterized type
	if (refBinding.isParameterizedType() || refBinding.isRawType()) {

		// Try to refine accuracy
		ParameterizedTypeBinding parameterizedBinding = (ParameterizedTypeBinding)refBinding;
		updateMatch(parameterizedBinding, this.pattern.getTypeArguments(), this.pattern.hasTypeParameters(), 0, locator);

		// See whether it is necessary to report or not
		if (this.match.getRule() == 0) return; // impossible match
		boolean report = (this.isErasureMatch && this.match.isErasure()) || (this.isEquivalentMatch && this.match.isEquivalent()) || this.match.isExact();
		if (!report) return;

		// Make a special report for parameterized types if necessary
		 if (refBinding.isParameterizedType() && this.pattern.hasTypeArguments())  {
			TypeReference typeRef = null;
			TypeReference[] typeArguments = null;
			if (expr instanceof ParameterizedQualifiedTypeReference) {
				typeRef = (ParameterizedQualifiedTypeReference) expr;
				typeArguments = ((ParameterizedQualifiedTypeReference) expr).typeArguments[lastIndex];
			}
			else if (expr instanceof ParameterizedSingleTypeReference) {
				typeRef = (ParameterizedSingleTypeReference) expr;
				typeArguments = ((ParameterizedSingleTypeReference) expr).typeArguments;
			}
			if (typeRef != null) {
				locator.reportAccurateParameterizedTypeReference(this.match, typeRef, lastIndex, typeArguments);
				return;
			}
		}
	} else if (this.pattern.hasTypeArguments()) { // binding has no type params, compatible erasure if pattern does
		this.match.setRule(SearchPattern.R_ERASURE_MATCH);
	}

	// Report match
	if (expr instanceof ArrayTypeReference) {
		locator.reportAccurateTypeReference(this.match, expr, this.pattern.simpleName);
		return;
	}
	if (refBinding.isLocalType()) {
		// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=82673
		LocalTypeBinding local = (LocalTypeBinding) refBinding.erasure();
		IJavaElement focus = this.pattern.focus;
		if (focus != null && local.enclosingMethod != null && focus.getParent().getElementType() == IJavaElement.METHOD) {
			IMethod method = (IMethod) focus.getParent();
			if (!CharOperation.equals(local.enclosingMethod.selector, method.getElementName().toCharArray())) {
				return;
			}
		}
	}
	if (this.pattern.simpleName == null) {
		this.match.setOffset(expr.sourceStart);
		this.match.setLength(expr.sourceEnd-expr.sourceStart+1);
	}
	locator.report(this.match);
}
protected int referenceType() {
	return IJavaElement.TYPE;
}
protected void reportDeclaration(ASTNode reference, IJavaElement element, MatchLocator locator, SimpleSet knownTypes) throws CoreException {
	int maxType = -1;
	TypeBinding typeBinding = null;
	if (reference instanceof TypeReference) {
		typeBinding = ((TypeReference) reference).resolvedType;
		maxType = Integer.MAX_VALUE;
	} else if (reference instanceof QualifiedNameReference) {
		QualifiedNameReference qNameRef = (QualifiedNameReference) reference;
		Binding binding = qNameRef.binding;
		maxType = qNameRef.tokens.length - 1;
		switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
			case Binding.FIELD : // reading a field
				typeBinding = qNameRef.actualReceiverType;
				maxType -= qNameRef.otherBindings == null ? 1 : qNameRef.otherBindings.length + 1;
				break;
			case Binding.TYPE : //=============only type ==============
				if (binding instanceof TypeBinding)
					typeBinding = (TypeBinding) binding;
				break;
			case Binding.VARIABLE : //============unbound cases===========
			case Binding.TYPE | Binding.VARIABLE :
				if (binding instanceof ProblemFieldBinding) {
					typeBinding = qNameRef.actualReceiverType;
					maxType -= qNameRef.otherBindings == null ? 1 : qNameRef.otherBindings.length + 1;
				} else if (binding instanceof ProblemBinding) {
					ProblemBinding pbBinding = (ProblemBinding) binding;
					typeBinding = pbBinding.searchType; // second chance with recorded type so far
					char[] partialQualifiedName = pbBinding.name;
					maxType = CharOperation.occurencesOf('.', partialQualifiedName) - 1; // index of last bound token is one before the pb token
					if (typeBinding == null || maxType < 0) return;
				}
				break;
		}
	} else if (reference instanceof SingleNameReference) {
		typeBinding = (TypeBinding) ((SingleNameReference) reference).binding;
		maxType = 1;
	}

	if (typeBinding instanceof ArrayBinding)
		typeBinding = ((ArrayBinding) typeBinding).leafComponentType;
	if (typeBinding == null || typeBinding instanceof BaseTypeBinding) return;
	if (typeBinding instanceof ProblemReferenceBinding) {
		TypeBinding original = typeBinding.closestMatch();
		if (original == null) return; // original may not be set (bug 71279)
		typeBinding = original;
	}
	typeBinding = typeBinding.erasure();
	reportDeclaration((ReferenceBinding) typeBinding, maxType, locator, knownTypes);
}
protected void reportDeclaration(ReferenceBinding typeBinding, int maxType, MatchLocator locator, SimpleSet knownTypes) throws CoreException {
	IType type = locator.lookupType(typeBinding);
	if (type == null) return; // case of a secondary type

	IResource resource = type.getResource();
	boolean isBinary = type.isBinary();
	IBinaryType info = null;
	if (isBinary) {
		if (resource == null)
			resource = type.getJavaProject().getProject();
		info = locator.getBinaryInfo((org.eclipse.jdt.internal.core.ClassFile) type.getClassFile(), resource);
	}
	while (maxType >= 0 && type != null) {
		if (!knownTypes.includes(type)) {
			if (isBinary) {
				locator.reportBinaryMemberDeclaration(resource, type, typeBinding, info, SearchMatch.A_ACCURATE);
			} else {
				if (typeBinding instanceof ParameterizedTypeBinding)
					typeBinding = ((ParameterizedTypeBinding) typeBinding).genericType();
				ClassScope scope = ((SourceTypeBinding) typeBinding).scope;
				if (scope != null) {
					TypeDeclaration typeDecl = scope.referenceContext;
					int offset = typeDecl.sourceStart;
					this.match = new TypeDeclarationMatch(((JavaElement) type).resolved(typeBinding), SearchMatch.A_ACCURATE, offset, typeDecl.sourceEnd-offset+1, locator.getParticipant(), resource);
					locator.report(this.match);
				}
			}
			knownTypes.add(type);
		}
		typeBinding = typeBinding.enclosingType();
		IJavaElement parent = type.getParent();
		if (parent instanceof IType) {
			type = (IType)parent;
		} else {
			type = null;
		}
		maxType--;
	}
}
public int resolveLevel(ASTNode node) {
	if (node instanceof TypeReference)
		return resolveLevel((TypeReference) node);
	if (node instanceof NameReference)
		return resolveLevel((NameReference) node);
//	if (node instanceof ImportReference) - Not called when resolve is true, see MatchingNodeSet.reportMatching(unit)
	return IMPOSSIBLE_MATCH;
}
public int resolveLevel(Binding binding) {
	if (binding == null) return INACCURATE_MATCH;
	if (!(binding instanceof TypeBinding)) return IMPOSSIBLE_MATCH;

	TypeBinding typeBinding = (TypeBinding) binding;
	if (typeBinding instanceof ArrayBinding)
		typeBinding = ((ArrayBinding) typeBinding).leafComponentType;
	if (typeBinding instanceof ProblemReferenceBinding)
		typeBinding = ((ProblemReferenceBinding) typeBinding).closestMatch();

	return resolveLevelForTypeOrEnclosingTypes(this.pattern.simpleName, this.pattern.qualification, typeBinding);
}
protected int resolveLevel(NameReference nameRef) {
	Binding binding = nameRef.binding;

	if (nameRef instanceof SingleNameReference) {
		if (binding instanceof ProblemReferenceBinding)
			binding = ((ProblemReferenceBinding) binding).closestMatch();
		if (binding instanceof ReferenceBinding)
			return resolveLevelForType((ReferenceBinding) binding);
		return binding == null || binding instanceof ProblemBinding ? INACCURATE_MATCH : IMPOSSIBLE_MATCH;
	}

	TypeBinding typeBinding = null;
	QualifiedNameReference qNameRef = (QualifiedNameReference) nameRef;
	switch (qNameRef.bits & ASTNode.RestrictiveFlagMASK) {
		case Binding.FIELD : // reading a field
			if (qNameRef.tokens.length < (qNameRef.otherBindings == null ? 2 : qNameRef.otherBindings.length + 2))
				return IMPOSSIBLE_MATCH; // must be at least A.x
			typeBinding = nameRef.actualReceiverType;
			break;
		case Binding.LOCAL : // reading a local variable
			return IMPOSSIBLE_MATCH; // no type match in it
		case Binding.TYPE : //=============only type ==============
			if (binding instanceof TypeBinding)
				typeBinding = (TypeBinding) binding;
			break;
		/*
		 * Handling of unbound qualified name references. The match may reside in the resolved fragment,
		 * which is recorded inside the problem binding, along with the portion of the name until it became a problem.
		 */
		case Binding.VARIABLE : //============unbound cases===========
		case Binding.TYPE | Binding.VARIABLE :
			if (binding instanceof ProblemReferenceBinding) {
				typeBinding = (TypeBinding) binding;
			} else if (binding instanceof ProblemFieldBinding) {
				if (qNameRef.tokens.length < (qNameRef.otherBindings == null ? 2 : qNameRef.otherBindings.length + 2))
					return IMPOSSIBLE_MATCH; // must be at least A.x
				typeBinding = nameRef.actualReceiverType;
			} else if (binding instanceof ProblemBinding) {
				ProblemBinding pbBinding = (ProblemBinding) binding;
				if (CharOperation.occurencesOf('.', pbBinding.name) <= 0) // index of last bound token is one before the pb token
					return INACCURATE_MATCH;
				typeBinding = pbBinding.searchType;
			}
			break;
	}
	return resolveLevel(typeBinding);
}
protected int resolveLevel(TypeReference typeRef) {
	TypeBinding typeBinding = typeRef.resolvedType;
	if (typeBinding instanceof ArrayBinding)
		typeBinding = ((ArrayBinding) typeBinding).leafComponentType;
	if (typeBinding instanceof ProblemReferenceBinding)
		typeBinding = ((ProblemReferenceBinding) typeBinding).closestMatch();

	if (typeRef instanceof SingleTypeReference) {
		return resolveLevelForType(typeBinding);
	} else
		return resolveLevelForTypeOrEnclosingTypes(this.pattern.simpleName, this.pattern.qualification, typeBinding);
}
/* (non-Javadoc)
 * Resolve level for type with a given binding.
 * This is just an helper to avoid call of method with all parameters...
 */
protected int resolveLevelForType(TypeBinding typeBinding) {
	if (typeBinding == null || !typeBinding.isValidBinding()) {
		if (this.pattern.typeSuffix != TYPE_SUFFIX) return INACCURATE_MATCH;
	} else {
		switch (this.pattern.typeSuffix) {
			case CLASS_SUFFIX:
				if (!typeBinding.isClass()) return IMPOSSIBLE_MATCH;
				break;
			case CLASS_AND_INTERFACE_SUFFIX:
				if (!(typeBinding.isClass() || (typeBinding.isInterface() && !typeBinding.isAnnotationType()))) return IMPOSSIBLE_MATCH;
				break;
			case CLASS_AND_ENUM_SUFFIX:
				if (!(typeBinding.isClass() || typeBinding.isEnum())) return IMPOSSIBLE_MATCH;
				break;
			case INTERFACE_SUFFIX:
				if (!typeBinding.isInterface() || typeBinding.isAnnotationType()) return IMPOSSIBLE_MATCH;
				break;
			case INTERFACE_AND_ANNOTATION_SUFFIX:
				if (!(typeBinding.isInterface() || typeBinding.isAnnotationType())) return IMPOSSIBLE_MATCH;
				break;
			case ENUM_SUFFIX:
				if (!typeBinding.isEnum()) return IMPOSSIBLE_MATCH;
				break;
			case ANNOTATION_TYPE_SUFFIX:
				if (!typeBinding.isAnnotationType()) return IMPOSSIBLE_MATCH;
				break;
			case TYPE_SUFFIX : // nothing
		}
	}
	return resolveLevelForType( this.pattern.simpleName,
						this.pattern.qualification,
						this.pattern.getTypeArguments(),
						0,
						typeBinding);
}
/**
 * Returns whether the given type binding or one of its enclosing types
 * matches the given simple name pattern and qualification pattern.
 * Returns ACCURATE_MATCH if it does.
 * Returns INACCURATE_MATCH if resolve failed.
 * Returns IMPOSSIBLE_MATCH if it doesn't.
 */
protected int resolveLevelForTypeOrEnclosingTypes(char[] simpleNamePattern, char[] qualificationPattern, TypeBinding binding) {
	if (binding == null) return INACCURATE_MATCH;

	if (binding instanceof ReferenceBinding) {
		ReferenceBinding type = (ReferenceBinding) binding;
		while (type != null) {
			int level = resolveLevelForType(type);
			if (level != IMPOSSIBLE_MATCH) return level;

			type = type.enclosingType();
		}
	}
	return IMPOSSIBLE_MATCH;
}
public String toString() {
	return "Locator for " + this.pattern.toString(); //$NON-NLS-1$
}
}
