/*******************************************************************************
 * Copyright (c) 2000, 2011 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.runtime.CoreException;
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.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.classfmt.FieldInfo;
import org.eclipse.jdt.internal.compiler.classfmt.MethodInfo;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.core.*;
import org.eclipse.jdt.internal.core.search.indexing.IIndexConstants;

public class ClassFileMatchLocator implements IIndexConstants {

private static final long TARGET_ANNOTATION_BITS =
	TagBits.AnnotationForType |
	TagBits.AnnotationForParameter |
	TagBits.AnnotationForPackage |
	TagBits.AnnotationForMethod |
	TagBits.AnnotationForLocalVariable |
	TagBits.AnnotationForField |
	TagBits.AnnotationForConstructor |
	TagBits.AnnotationForAnnotationType;
private static final char[] JAVA_LANG_ANNOTATION_ELEMENTTYPE = CharOperation.concatWith(TypeConstants.JAVA_LANG_ANNOTATION_ELEMENTTYPE, '.');
public static char[] convertClassFileFormat(char[] name) {
	return CharOperation.replaceOnCopy(name, '/', '.');
}

private  boolean checkAnnotation(IBinaryAnnotation annotation, TypeReferencePattern pattern) {
	if (checkTypeName(pattern.simpleName, pattern.qualification, convertClassFileFormat(Signature.toCharArray(annotation.getTypeName())), pattern.isCaseSensitive, pattern.isCamelCase)) {
		return true;
	}
	IBinaryElementValuePair[] valuePairs = annotation.getElementValuePairs();
	if (valuePairs != null) {
		for (int j=0, vpLength=valuePairs.length; j<vpLength; j++) {
			IBinaryElementValuePair valuePair = valuePairs[j];
			Object pairValue = valuePair.getValue();
			if (pairValue instanceof IBinaryAnnotation) {
				if (checkAnnotation((IBinaryAnnotation) pairValue, pattern)) {
					return true;
				}
			}
		}
	}
	return false;
}
private boolean checkAnnotations(TypeReferencePattern pattern, IBinaryAnnotation[] annotations, long tagBits) {
	if (annotations != null) {
		for (int a=0, length=annotations.length; a<length; a++) {
			IBinaryAnnotation annotation = annotations[a];
			if (checkAnnotation(annotation, pattern)) {
				return true;
			}
		}
	}
	if ((tagBits & TagBits.AllStandardAnnotationsMask) != 0 && checkStandardAnnotations(tagBits, pattern)) {
		return true;
	}
	return false;
}
private boolean checkAnnotationTypeReference(char[] fullyQualifiedName, TypeReferencePattern pattern) {
	return checkTypeName(pattern.simpleName, pattern.qualification, fullyQualifiedName, pattern.isCaseSensitive, pattern.isCamelCase);
}
private boolean checkDeclaringType(IBinaryType enclosingBinaryType, char[] simpleName, char[] qualification, boolean isCaseSensitive, boolean isCamelCase) {
	if (simpleName == null && qualification == null) return true;
	if (enclosingBinaryType == null) return true;

	char[] declaringTypeName = convertClassFileFormat(enclosingBinaryType.getName());
	return checkTypeName(simpleName, qualification, declaringTypeName, isCaseSensitive, isCamelCase);
}
private boolean checkParameters(char[] methodDescriptor, char[][] parameterSimpleNames, char[][] parameterQualifications, boolean isCaseSensitive, boolean isCamelCase) {
	char[][] arguments = Signature.getParameterTypes(methodDescriptor);
	int parameterCount = parameterSimpleNames.length;
	if (parameterCount != arguments.length) return false;
	for (int i = 0; i < parameterCount; i++)
		if (!checkTypeName(parameterSimpleNames[i], parameterQualifications[i], Signature.toCharArray(arguments[i]), isCaseSensitive, isCamelCase))
			return false;
	return true;
}
private boolean checkStandardAnnotations(long annotationTagBits, TypeReferencePattern pattern) {
	if ((annotationTagBits & TagBits.AnnotationTargetMASK) != 0) {
		char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_TARGET;
		if (checkAnnotationTypeReference(CharOperation.concatWith(compoundName, '.'), pattern) ||
			((annotationTagBits & TARGET_ANNOTATION_BITS) != 0 && checkAnnotationTypeReference(JAVA_LANG_ANNOTATION_ELEMENTTYPE, pattern))) {
			return true;
		}
	}
	if ((annotationTagBits & TagBits.AnnotationRetentionMASK) != 0) {
		char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_RETENTION;
		if (checkAnnotationTypeReference(CharOperation.concatWith(compoundName, '.'), pattern) ||
			checkAnnotationTypeReference(CharOperation.concatWith(TypeConstants.JAVA_LANG_ANNOTATION_RETENTIONPOLICY, '.'), pattern)) {
			return true;
		}
	}
	if ((annotationTagBits & TagBits.AnnotationDeprecated) != 0) {
		char[][] compoundName = TypeConstants.JAVA_LANG_DEPRECATED;
		if (checkAnnotationTypeReference(CharOperation.concatWith(compoundName, '.'), pattern)) {
			return true;
		}
	}
	if ((annotationTagBits & TagBits.AnnotationDocumented) != 0) {
		char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_DOCUMENTED;
		if (checkAnnotationTypeReference(CharOperation.concatWith(compoundName, '.'), pattern)) {
			return true;
		}
	}
	if ((annotationTagBits & TagBits.AnnotationInherited) != 0) {
		char[][] compoundName = TypeConstants.JAVA_LANG_ANNOTATION_INHERITED;
		if (checkAnnotationTypeReference(CharOperation.concatWith(compoundName, '.'), pattern)) {
			return true;
		}
	}
	if ((annotationTagBits & TagBits.AnnotationOverride) != 0) {
		char[][] compoundName = TypeConstants.JAVA_LANG_OVERRIDE;
		if (checkAnnotationTypeReference(CharOperation.concatWith(compoundName, '.'), pattern)) {
			return true;
		}
	}
	if ((annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0) {
		char[][] compoundName = TypeConstants.JAVA_LANG_SUPPRESSWARNINGS;
		if (checkAnnotationTypeReference(CharOperation.concatWith(compoundName, '.'), pattern)) {
			return true;
		}
	}
	if ((annotationTagBits & TagBits.AnnotationSafeVarargs) != 0) {
		char[][] compoundName = TypeConstants.JAVA_LANG_SAFEVARARGS;
		if (checkAnnotationTypeReference(CharOperation.concatWith(compoundName, '.'), pattern)) {
			return true;
		}
	}
	if ((annotationTagBits & TagBits.AnnotationPolymorphicSignature) != 0) {
		char[][] compoundName = TypeConstants.JAVA_LANG_INVOKE_METHODHANDLE_$_POLYMORPHICSIGNATURE;
		if (checkAnnotationTypeReference(CharOperation.concatWith(compoundName, '.'), pattern)) {
			return true;
		}
	}
	return false;
}
private boolean checkTypeName(char[] simpleName, char[] qualification, char[] fullyQualifiedTypeName, boolean isCaseSensitive, boolean isCamelCase) {
	// NOTE: if case insensitive then simpleName & qualification are assumed to be lowercase
	char[] wildcardPattern = PatternLocator.qualifiedPattern(simpleName, qualification);
	if (wildcardPattern == null) return true;
	return CharOperation.match(wildcardPattern, fullyQualifiedTypeName, isCaseSensitive);
}
/**
 * Locate declaration in the current class file. This class file is always in a jar.
 */
public void locateMatches(MatchLocator locator, ClassFile classFile, IBinaryType info) throws CoreException {
	SearchPattern pattern = locator.pattern;

	// check annotations references
	matchAnnotations(pattern, locator, classFile, info);

	// check class definition
	BinaryType binaryType = (BinaryType) classFile.getType();
	if (matchBinary(pattern, info, null)) {
		binaryType = new ResolvedBinaryType((JavaElement) binaryType.getParent(), binaryType.getElementName(), binaryType.getKey());
		locator.reportBinaryMemberDeclaration(null, binaryType, null, info, SearchMatch.A_ACCURATE);
		return;
	}

	// Define arrays to store methods/fields from binary type if necessary
	IBinaryMethod[] binaryMethods = info.getMethods();
	int bMethodsLength = binaryMethods == null ? 0 : binaryMethods.length;
	IBinaryMethod[] unresolvedMethods = null;
	char[][] binaryMethodSignatures = null;
	boolean hasUnresolvedMethods = false;

	// Get fields from binary type info
	IBinaryField[] binaryFields = info.getFields();
	int bFieldsLength = binaryFields == null ? 0 : binaryFields.length;
	IBinaryField[] unresolvedFields = null;
	boolean hasUnresolvedFields = false;

	// Report as many accurate matches as possible
	int accuracy = SearchMatch.A_ACCURATE;
	boolean mustResolve = pattern.mustResolve;
	if (mustResolve) {
		BinaryTypeBinding binding = locator.cacheBinaryType(binaryType, info);
		if (binding != null) {
			// filter out element not in hierarchy scope
			if (!locator.typeInHierarchy(binding)) return;

			// Search matches on resolved methods
			MethodBinding[] availableMethods = binding.availableMethods();
			int aMethodsLength = availableMethods == null ? 0 : availableMethods.length;
			hasUnresolvedMethods = bMethodsLength != aMethodsLength;
			for (int i = 0; i < aMethodsLength; i++) {
				MethodBinding method = availableMethods[i];
				char[] methodSignature = method.genericSignature();
				if (methodSignature == null) methodSignature = method.signature();

				// Report the match if possible
				int level = locator.patternLocator.resolveLevel(method);
				if (level != PatternLocator.IMPOSSIBLE_MATCH) {
					IMethod methodHandle = binaryType.getMethod(
						new String(method.isConstructor() ? binding.compoundName[binding.compoundName.length-1] : method.selector),
						CharOperation.toStrings(Signature.getParameterTypes(convertClassFileFormat(methodSignature))));
					accuracy = level == PatternLocator.ACCURATE_MATCH ? SearchMatch.A_ACCURATE : SearchMatch.A_INACCURATE;
					locator.reportBinaryMemberDeclaration(null, methodHandle, method, info, accuracy);
				}

				// Remove method from unresolved list
				if (hasUnresolvedMethods) {
					if (binaryMethodSignatures == null) { // Store binary method signatures to avoid multiple computation
						binaryMethodSignatures = new char[bMethodsLength][];
						for (int j=0; j<bMethodsLength; j++) {
							IBinaryMethod binaryMethod = binaryMethods[j];
							char[] signature = binaryMethod.getGenericSignature();
							if (signature == null) signature = binaryMethod.getMethodDescriptor();
							binaryMethodSignatures[j] = signature;
						}
					}
					for (int j=0; j<bMethodsLength; j++) {
						if (CharOperation.equals(binaryMethods[j].getSelector(), method.selector) && CharOperation.equals(binaryMethodSignatures[j], methodSignature)) {
							if (unresolvedMethods == null) {
								System.arraycopy(binaryMethods, 0, unresolvedMethods = new IBinaryMethod[bMethodsLength], 0, bMethodsLength);
							}
							unresolvedMethods[j] = null;
							break;
						}
					}
				}
			}

			// Search matches on resolved fields
			FieldBinding[] availableFields = binding.availableFields();
			int aFieldsLength = availableFields == null ? 0 : availableFields.length;
			hasUnresolvedFields = bFieldsLength != aFieldsLength;
			for (int i = 0; i < aFieldsLength; i++) {
				FieldBinding field = availableFields[i];

				// Report the match if possible
				int level = locator.patternLocator.resolveLevel(field);
				if (level != PatternLocator.IMPOSSIBLE_MATCH) {
					IField fieldHandle = binaryType.getField(new String(field.name));
					accuracy = level == PatternLocator.ACCURATE_MATCH ? SearchMatch.A_ACCURATE : SearchMatch.A_INACCURATE;
					locator.reportBinaryMemberDeclaration(null, fieldHandle, field, info, accuracy);
				}

				// Remove the field from unresolved list
				if (hasUnresolvedFields) {
					for (int j=0; j<bFieldsLength; j++) {
						if ( CharOperation.equals(binaryFields[j].getName(), field.name)) {
							if (unresolvedFields == null) {
								System.arraycopy(binaryFields, 0, unresolvedFields = new IBinaryField[bFieldsLength], 0, bFieldsLength);
							}
							unresolvedFields[j] = null;
							break;
						}
					}
				}
			}

			// If all methods/fields were accurate then returns now
			if (!hasUnresolvedMethods && !hasUnresolvedFields) {
				return;
			}
		}
		accuracy = SearchMatch.A_INACCURATE;
	}

	// Report inaccurate methods
	if (mustResolve) binaryMethods = unresolvedMethods;
	bMethodsLength = binaryMethods == null ? 0 : binaryMethods.length;
	for (int i=0; i < bMethodsLength; i++) {
		IBinaryMethod method = binaryMethods[i];
		if (method == null) continue; // impossible match or already reported as accurate
		if (matchBinary(pattern, method, info)) {
			char[] name;
			if (method.isConstructor()) {
				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=329727
				// We don't need the enclosing type name for the constructor name
				name = info.getSourceName();
			} else {
				name = method.getSelector();
			}
			String selector = new String(name);
			char[] methodSignature = binaryMethodSignatures == null ? null : binaryMethodSignatures[i];
			if (methodSignature == null) {
				methodSignature = method.getGenericSignature();
				if (methodSignature == null) methodSignature = method.getMethodDescriptor();
			}
			String[] parameterTypes = CharOperation.toStrings(Signature.getParameterTypes(convertClassFileFormat(methodSignature)));
			IMethod methodHandle = binaryType.getMethod(selector, parameterTypes);
			methodHandle = new ResolvedBinaryMethod(binaryType, selector, parameterTypes, methodHandle.getKey());
			locator.reportBinaryMemberDeclaration(null, methodHandle, null, info, accuracy);
		}
	}

	// Report inaccurate fields
	if (mustResolve) binaryFields =  unresolvedFields;
	bFieldsLength = binaryFields == null ? 0 : binaryFields.length;
	for (int i=0; i<bFieldsLength; i++) {
		IBinaryField field = binaryFields[i];
		if (field == null) continue; // impossible match or already reported as accurate
		if (matchBinary(pattern, field, info)) {
			String fieldName = new String(field.getName());
			IField fieldHandle = binaryType.getField(fieldName);
			fieldHandle = new ResolvedBinaryField(binaryType, fieldName, fieldHandle.getKey());
			locator.reportBinaryMemberDeclaration(null, fieldHandle, null, info, accuracy);
		}
	}
}
/*
 * Look for annotations references
 */
private void matchAnnotations(SearchPattern pattern, MatchLocator locator, ClassFile classFile, IBinaryType binaryType) throws CoreException {
	// Only process TypeReference patterns
	switch (pattern.kind) {
		case TYPE_REF_PATTERN:
			break;
		case OR_PATTERN:
			SearchPattern[] patterns = ((OrPattern) pattern).patterns;
			for (int i = 0, length = patterns.length; i < length; i++) {
				matchAnnotations(patterns[i], locator, classFile, binaryType);
			}
			// $FALL-THROUGH$ - fall through default to return
		default:
			return;
	}
	TypeReferencePattern typeReferencePattern  = (TypeReferencePattern) pattern;

	// Look for references in class annotations
	IBinaryAnnotation[] annotations = binaryType.getAnnotations();
	BinaryType classFileBinaryType = (BinaryType) classFile.getType();
	BinaryTypeBinding binaryTypeBinding = null;
	if (checkAnnotations(typeReferencePattern, annotations, binaryType.getTagBits())) {
		classFileBinaryType = new ResolvedBinaryType((JavaElement) classFileBinaryType.getParent(), classFileBinaryType.getElementName(), classFileBinaryType.getKey());
		TypeReferenceMatch match = new TypeReferenceMatch(classFileBinaryType, SearchMatch.A_ACCURATE, -1, 0, false, locator.getParticipant(), locator.currentPossibleMatch.resource);
		// TODO 3.4 M7 (frederic) - bug 209996: see how create the annotation handle from the binary and put it in the local element
		match.setLocalElement(null);
		locator.report(match);
	}

	// Look for references in methods annotations
	MethodInfo[] methods = (MethodInfo[]) binaryType.getMethods();
	if (methods != null) {
		for (int i = 0, max = methods.length; i < max; i++) {
			MethodInfo method = methods[i];
			if (checkAnnotations(typeReferencePattern, method.getAnnotations(), method.getTagBits())) {
					binaryTypeBinding = locator.cacheBinaryType(classFileBinaryType, binaryType);
					IMethod methodHandle = classFileBinaryType.getMethod(
						new String(method.isConstructor() ? binaryTypeBinding.compoundName[binaryTypeBinding.compoundName.length-1] : method.getSelector()),
						CharOperation.toStrings(Signature.getParameterTypes(convertClassFileFormat(method.getMethodDescriptor()))));
					TypeReferenceMatch match = new TypeReferenceMatch(methodHandle, SearchMatch.A_ACCURATE, -1, 0, false, locator.getParticipant(), locator.currentPossibleMatch.resource);
					// TODO 3.4 M7 (frederic) - bug 209996: see how create the annotation handle from the binary and put it in the local element
					match.setLocalElement(null);
					locator.report(match);
			}
		}
	}

	// Look for references in fields annotations
	FieldInfo[] fields = (FieldInfo[]) binaryType.getFields();
	if (fields != null) {
		for (int i = 0, max = fields.length; i < max; i++) {
			FieldInfo field = fields[i];
			if (checkAnnotations(typeReferencePattern, field.getAnnotations(), field.getTagBits())) {
					IField fieldHandle = classFileBinaryType.getField(new String(field.getName()));
					TypeReferenceMatch match = new TypeReferenceMatch(fieldHandle, SearchMatch.A_ACCURATE, -1, 0, false, locator.getParticipant(), locator.currentPossibleMatch.resource);
					// TODO 3.4 M7 (frederic) - bug 209996: see how create the annotation handle from the binary and put it in the local element
					match.setLocalElement(null);
					locator.report(match);
			}
		}
	}
}
/**
 * Finds out whether the given binary info matches the search pattern.
 * Default is to return false.
 */
boolean matchBinary(SearchPattern pattern, Object binaryInfo, IBinaryType enclosingBinaryType) {
	switch (pattern.kind) {
		case CONSTRUCTOR_PATTERN :
			return matchConstructor((ConstructorPattern) pattern, binaryInfo, enclosingBinaryType);
		case FIELD_PATTERN :
			return matchField((FieldPattern) pattern, binaryInfo, enclosingBinaryType);
		case METHOD_PATTERN :
			return matchMethod((MethodPattern) pattern, binaryInfo, enclosingBinaryType);
		case SUPER_REF_PATTERN :
			return matchSuperTypeReference((SuperTypeReferencePattern) pattern, binaryInfo, enclosingBinaryType);
		case TYPE_DECL_PATTERN :
			return matchTypeDeclaration((TypeDeclarationPattern) pattern, binaryInfo, enclosingBinaryType);
		case OR_PATTERN :
			SearchPattern[] patterns = ((OrPattern) pattern).patterns;
			for (int i = 0, length = patterns.length; i < length; i++)
				if (matchBinary(patterns[i], binaryInfo, enclosingBinaryType)) return true;
	}
	return false;
}
boolean matchConstructor(ConstructorPattern pattern, Object binaryInfo, IBinaryType enclosingBinaryType) {
	if (!pattern.findDeclarations) return false; // only relevant when finding declarations
	if (!(binaryInfo instanceof IBinaryMethod)) return false;

	IBinaryMethod method = (IBinaryMethod) binaryInfo;
	if (!method.isConstructor()) return false;
	if (!checkDeclaringType(enclosingBinaryType, pattern.declaringSimpleName, pattern.declaringQualification, pattern.isCaseSensitive(), pattern.isCamelCase()))
		return false;
	if (pattern.parameterSimpleNames != null) {
		char[] methodDescriptor = convertClassFileFormat(method.getMethodDescriptor());
		if (!checkParameters(methodDescriptor, pattern.parameterSimpleNames, pattern.parameterQualifications, pattern.isCaseSensitive(), pattern.isCamelCase()))
			return false;
	}
	return true;
}
boolean matchField(FieldPattern pattern, Object binaryInfo, IBinaryType enclosingBinaryType) {
	if (!pattern.findDeclarations) return false; // only relevant when finding declarations
	if (!(binaryInfo instanceof IBinaryField)) return false;

	IBinaryField field = (IBinaryField) binaryInfo;
	if (!pattern.matchesName(pattern.name, field.getName())) return false;
	if (!checkDeclaringType(enclosingBinaryType, pattern.declaringSimpleName, pattern.declaringQualification, pattern.isCaseSensitive(), pattern.isCamelCase()))
		return false;

	char[] fieldTypeSignature = Signature.toCharArray(convertClassFileFormat(field.getTypeName()));
	return checkTypeName(pattern.typeSimpleName, pattern.typeQualification, fieldTypeSignature, pattern.isCaseSensitive(), pattern.isCamelCase());
}
boolean matchMethod(MethodPattern pattern, Object binaryInfo, IBinaryType enclosingBinaryType) {
	if (!pattern.findDeclarations) return false; // only relevant when finding declarations
	if (!(binaryInfo instanceof IBinaryMethod)) return false;

	IBinaryMethod method = (IBinaryMethod) binaryInfo;
	if (!pattern.matchesName(pattern.selector, method.getSelector())) return false;
	if (!checkDeclaringType(enclosingBinaryType, pattern.declaringSimpleName, pattern.declaringQualification, pattern.isCaseSensitive(), pattern.isCamelCase()))
		return false;

	// look at return type only if declaring type is not specified
	boolean checkReturnType = pattern.declaringSimpleName == null && (pattern.returnSimpleName != null || pattern.returnQualification != null);
	boolean checkParameters = pattern.parameterSimpleNames != null;
	if (checkReturnType || checkParameters) {
		char[] methodDescriptor = convertClassFileFormat(method.getMethodDescriptor());
		if (checkReturnType) {
			char[] returnTypeSignature = Signature.toCharArray(Signature.getReturnType(methodDescriptor));
			if (!checkTypeName(pattern.returnSimpleName, pattern.returnQualification, returnTypeSignature, pattern.isCaseSensitive(), pattern.isCamelCase()))
				return false;
		}
		if (checkParameters &&  !checkParameters(methodDescriptor, pattern.parameterSimpleNames, pattern.parameterQualifications, pattern.isCaseSensitive(), pattern.isCamelCase()))
			return false;
	}
	return true;
}
boolean matchSuperTypeReference(SuperTypeReferencePattern pattern, Object binaryInfo, IBinaryType enclosingBinaryType) {
	if (!(binaryInfo instanceof IBinaryType)) return false;

	IBinaryType type = (IBinaryType) binaryInfo;
	if (pattern.superRefKind != SuperTypeReferencePattern.ONLY_SUPER_INTERFACES) {
		char[] vmName = type.getSuperclassName();
		if (vmName != null) {
			char[] superclassName = convertClassFileFormat(vmName);
			if (checkTypeName(pattern.superSimpleName, pattern.superQualification, superclassName, pattern.isCaseSensitive(), pattern.isCamelCase()))
				return true;
		}
	}

	if (pattern.superRefKind != SuperTypeReferencePattern.ONLY_SUPER_CLASSES) {
		char[][] superInterfaces = type.getInterfaceNames();
		if (superInterfaces != null) {
			for (int i = 0, max = superInterfaces.length; i < max; i++) {
				char[] superInterfaceName = convertClassFileFormat(superInterfaces[i]);
				if (checkTypeName(pattern.superSimpleName, pattern.superQualification, superInterfaceName, pattern.isCaseSensitive(), pattern.isCamelCase()))
					return true;
			}
		}
	}
	return false;
}
boolean matchTypeDeclaration(TypeDeclarationPattern pattern, Object binaryInfo, IBinaryType enclosingBinaryType) {
	if (!(binaryInfo instanceof IBinaryType)) return false;

	IBinaryType type = (IBinaryType) binaryInfo;
	char[] fullyQualifiedTypeName = convertClassFileFormat(type.getName());
	boolean qualifiedPattern = pattern instanceof QualifiedTypeDeclarationPattern;
	if (pattern.enclosingTypeNames == null || qualifiedPattern) {
		char[] simpleName = (pattern.getMatchMode() == SearchPattern.R_PREFIX_MATCH)
			? CharOperation.concat(pattern.simpleName, IIndexConstants.ONE_STAR)
			: pattern.simpleName;
		char[] pkg = qualifiedPattern ? ((QualifiedTypeDeclarationPattern)pattern).qualification : pattern.pkg;
		if (!checkTypeName(simpleName, pkg, fullyQualifiedTypeName, pattern.isCaseSensitive(), pattern.isCamelCase())) return false;
	} else {
		char[] enclosingTypeName = CharOperation.concatWith(pattern.enclosingTypeNames, '.');
		char[] patternString = pattern.pkg == null
			? enclosingTypeName
			: CharOperation.concat(pattern.pkg, enclosingTypeName, '.');
		if (!checkTypeName(pattern.simpleName, patternString, fullyQualifiedTypeName, pattern.isCaseSensitive(), pattern.isCamelCase())) return false;
	}

	int kind  = TypeDeclaration.kind(type.getModifiers());
	switch (pattern.typeSuffix) {
		case CLASS_SUFFIX:
			return kind == TypeDeclaration.CLASS_DECL;
		case INTERFACE_SUFFIX:
			return kind == TypeDeclaration.INTERFACE_DECL;
		case ENUM_SUFFIX:
			return kind == TypeDeclaration.ENUM_DECL;
		case ANNOTATION_TYPE_SUFFIX:
			return kind == TypeDeclaration.ANNOTATION_TYPE_DECL;
		case CLASS_AND_INTERFACE_SUFFIX:
			return kind == TypeDeclaration.CLASS_DECL || kind == TypeDeclaration.INTERFACE_DECL;
		case CLASS_AND_ENUM_SUFFIX:
			return kind == TypeDeclaration.CLASS_DECL || kind == TypeDeclaration.ENUM_DECL;
		case INTERFACE_AND_ANNOTATION_SUFFIX:
			return kind == TypeDeclaration.INTERFACE_DECL || kind == TypeDeclaration.ANNOTATION_TYPE_DECL;
		case TYPE_SUFFIX: // nothing
	}
	return true;
}
}
