/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Fraunhofer FIRST - extended API and implementation
 *     Technical University Berlin - extended API and implementation
 *     Stephan Herrmann - Contribution for
 *								Bug 377883 - NPE on open Call Hierarchy
 *******************************************************************************/
package org.eclipse.jdt.internal.core.search.matching;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.zip.ZipFile;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IAnnotatable;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelStatusConstants;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IModuleDescription;
import org.eclipse.jdt.core.IOpenable;
import org.eclipse.jdt.core.IOrdinaryClassFile;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.core.search.*;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.parser.*;
import org.eclipse.jdt.internal.compiler.problem.*;
import org.eclipse.jdt.internal.compiler.util.HashtableOfIntValues;
import org.eclipse.jdt.internal.compiler.util.Messages;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.SimpleSet;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.core.hierarchy.HierarchyResolver;
import org.eclipse.jdt.internal.core.AbstractModule;
import org.eclipse.jdt.internal.core.BinaryMember;
import org.eclipse.jdt.internal.core.BinaryMethod;
import org.eclipse.jdt.internal.core.BinaryType;
import org.eclipse.jdt.internal.core.ClassFile;
import org.eclipse.jdt.internal.core.CompilationUnit;
import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
import org.eclipse.jdt.internal.core.JavaElement;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.internal.core.LambdaFactory;
import org.eclipse.jdt.internal.core.LocalVariable;
import org.eclipse.jdt.internal.core.ModularClassFile;
import org.eclipse.jdt.internal.core.NameLookup;
import org.eclipse.jdt.internal.core.Openable;
import org.eclipse.jdt.internal.core.PackageFragment;
import org.eclipse.jdt.internal.core.PackageFragmentRoot;
import org.eclipse.jdt.internal.core.SearchableEnvironment;
import org.eclipse.jdt.internal.core.SourceMapper;
import org.eclipse.jdt.internal.core.SourceMethod;
import org.eclipse.jdt.internal.core.SourceType;
import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
import org.eclipse.jdt.internal.core.index.Index;
import org.eclipse.jdt.internal.core.search.*;
import org.eclipse.jdt.internal.core.util.ASTNodeFinder;
import org.eclipse.jdt.internal.core.util.HandleFactory;
import org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.objectteams.otdt.core.IMethodMapping;
import org.eclipse.objectteams.otdt.core.IRoleType;
import org.eclipse.objectteams.otdt.core.OTModelManager;
import org.eclipse.objectteams.otdt.core.TypeHelper;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.internal.core.RoleType;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CalloutMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.PrecedenceDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateHelper;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.MethodSignatureEnhancer;

/**
 * OTDT changes:
 * 
 * What: Harnessing of all compiler calls with Dependencies (throughout)
 *
 * Retrenching several mangled names/signatures:
 * ---------------------------------------------
 * What: retrench signature of callin method
 * How:  use MethodSignatureEnhancer.getSourceArguments(method);
 * 
 * What: Strip leading __OT__
 * Where: 
 * 		 - createHandle(AbstractMethodDeclaration method, ...) if method is a ctor
 * 		 - reportMatching(TypeDeclaration type, ...)
 *
 * What: when matching methods:
 * 		 - filter generated methods
 * 		 - look in interface part, too
 *  
 * Handle new elements:
 * --------------------
 * What: account for a new kind of variable: TYPE_VALUE_PARAMETER.
 * 
 * What: Support matching "team package" decl as a type reference
 * 
 * What: report matching of new node kinds:
 * 	     - base class
 * 		 - method mappings
 * 
 * What: Acount for OTJavaElement
 * How:  Before casting to JavaElement check whether we should actually use OTJavaElement
 * 
 * 
 * ROFI:
 * -----
 * What: Account for role files when traversing type declarations
 * Where: purgeMethodStatements()
 */
@SuppressWarnings({"rawtypes", "unchecked"})
public class MatchLocator implements ITypeRequestor {

public static final int MAX_AT_ONCE;
static {
	long maxMemory = Runtime.getRuntime().maxMemory();
	int ratio = (int) Math.round(((double) maxMemory) / (64 * 0x100000));
	switch (ratio) {
		case 0:
		case 1:
			MAX_AT_ONCE = 100;
			break;
		case 2:
			MAX_AT_ONCE = 200;
			break;
		case 3:
			MAX_AT_ONCE = 300;
			break;
		default:
			MAX_AT_ONCE = 400;
			break;
	}
}

// permanent state
public SearchPattern pattern;
public PatternLocator patternLocator;
public int matchContainer;
public SearchRequestor requestor;
public IJavaSearchScope scope;
public IProgressMonitor progressMonitor;
private IJavaSearchScope subScope = null;

public org.eclipse.jdt.core.ICompilationUnit[] workingCopies;
public HandleFactory handleFactory;

// cache of all super type names if scope is hierarchy scope
public char[][][] allSuperTypeNames;

// the following is valid for the current project
public MatchLocatorParser parser;
private Parser basicParser;
public INameEnvironment nameEnvironment;
public NameLookup nameLookup;
public LookupEnvironment lookupEnvironment;
public HierarchyResolver hierarchyResolver;

public CompilerOptions options;

// management of PossibleMatch to be processed
public int numberOfMatches; // (numberOfMatches - 1) is the last unit in matchesToProcess
public PossibleMatch[] matchesToProcess;
public PossibleMatch currentPossibleMatch;

/* package */HashMap<SearchMatch, Binding> matchBinding = new HashMap<>();
/*
 * Time spent in the IJavaSearchResultCollector
 */
public long resultCollectorTime = 0;

// Progress information
int progressStep;
int progressWorked;

// Binding resolution and cache
CompilationUnitScope unitScope;
SimpleLookupTable bindings;

HashtableOfIntValues inTypeOccurrencesCounts = new HashtableOfIntValues();
// Cache for method handles
HashSet methodHandles;
private TypeBinding unitScopeTypeBinding = null; // cached

private final boolean searchPackageDeclaration;
private int sourceStartOfMethodToRetain;
private int sourceEndOfMethodToRetain;

public static class WorkingCopyDocument extends JavaSearchDocument {
	public org.eclipse.jdt.core.ICompilationUnit workingCopy;
	WorkingCopyDocument(org.eclipse.jdt.core.ICompilationUnit workingCopy, SearchParticipant participant) {
		super(workingCopy.getPath().toString(), participant);
		this.charContents = ((CompilationUnit)workingCopy).getContents();
		this.workingCopy = workingCopy;
	}
	@Override
	public String toString() {
		return "WorkingCopyDocument for " + getPath(); //$NON-NLS-1$
	}
}

public static class WrappedCoreException extends RuntimeException {
	private static final long serialVersionUID = 8354329870126121212L; // backward compatible
	public CoreException coreException;
	public WrappedCoreException(CoreException coreException) {
		this.coreException = coreException;
	}
}

public static SearchDocument[] addWorkingCopies(SearchPattern pattern, SearchDocument[] indexMatches, org.eclipse.jdt.core.ICompilationUnit[] copies, SearchParticipant participant) {
	if (copies == null) return indexMatches;
	// working copies take precedence over corresponding compilation units
	HashMap workingCopyDocuments = workingCopiesThatCanSeeFocus(copies, pattern, participant);
	if (workingCopyDocuments.size() == 0) return indexMatches;
	SearchDocument[] matches = null;
	int length = indexMatches.length;
	for (int i = 0; i < length; i++) {
		SearchDocument searchDocument = indexMatches[i];
		if (searchDocument.getParticipant() == participant) {
			SearchDocument workingCopyDocument = (SearchDocument) workingCopyDocuments.remove(searchDocument.getPath());
			if (workingCopyDocument != null) {
				if (matches == null) {
					System.arraycopy(indexMatches, 0, matches = new SearchDocument[length], 0, length);
				}
				matches[i] = workingCopyDocument;
			}
		}
	}
	if (matches == null) { // no working copy
		matches = indexMatches;
	}
	int remainingWorkingCopiesSize = workingCopyDocuments.size();
	if (remainingWorkingCopiesSize != 0) {
		System.arraycopy(matches, 0, matches = new SearchDocument[length+remainingWorkingCopiesSize], 0, length);
		Iterator iterator = workingCopyDocuments.values().iterator();
		int index = length;
		while (iterator.hasNext()) {
			matches[index++] = (SearchDocument) iterator.next();
		}
	}
	return matches;
}

public static void setFocus(SearchPattern pattern, IJavaElement focus) {
	pattern.focus = focus;
}

/*
 * Returns the working copies that can see the given focus.
 */
private static HashMap workingCopiesThatCanSeeFocus(org.eclipse.jdt.core.ICompilationUnit[] copies, SearchPattern pattern, SearchParticipant participant) {
	if (copies == null) return new HashMap();
	HashMap result = new HashMap();
	for (int i=0, length = copies.length; i<length; i++) {
		org.eclipse.jdt.core.ICompilationUnit workingCopy = copies[i];
		IPath projectOrJar = MatchLocator.getProjectOrJar(workingCopy).getPath();
		if (pattern.focus == null || IndexSelector.canSeeFocus(pattern, projectOrJar) != IndexSelector.PROJECT_CAN_NOT_SEE_FOCUS) {
			result.put(
				workingCopy.getPath().toString(),
				new WorkingCopyDocument(workingCopy, participant)
			);
		}
	}
	return result;
}

public static IBinaryType classFileReader(IType type) {
	IOrdinaryClassFile classFile = type.getClassFile();
	JavaModelManager manager = JavaModelManager.getJavaModelManager();
	if (classFile.isOpen())
		return (IBinaryType)manager.getInfo(type);

	PackageFragment pkg = (PackageFragment) type.getPackageFragment();
	IPackageFragmentRoot root = (IPackageFragmentRoot) pkg.getParent();
	try {
		if (!root.isArchive())
			return Util.newClassFileReader(((JavaElement) type).resource());

		String rootPath = root.getPath().toOSString();
		if (org.eclipse.jdt.internal.compiler.util.Util.isJrt(rootPath)) {
			String classFileName = classFile.getElementName();
			String path = Util.concatWith(pkg.names, classFileName, '/');
			return ClassFileReader.readFromJrt(new File(rootPath), null, path);
		} else {
			ZipFile zipFile = null;
			try {
				IPath zipPath = root.getPath();
				if (JavaModelManager.ZIP_ACCESS_VERBOSE)
					System.out.println("(" + Thread.currentThread() + ") [MatchLocator.classFileReader()] Creating ZipFile on " + zipPath); //$NON-NLS-1$	//$NON-NLS-2$
				zipFile = manager.getZipFile(zipPath);
				String classFileName = classFile.getElementName();
				String path = Util.concatWith(pkg.names, classFileName, '/');
				return ClassFileReader.read(zipFile, path);
			} finally {
				manager.closeZipFile(zipFile);
			}
		}
	} catch (ClassFormatException | CoreException | IOException e) {
		// invalid class file: return null
	}
	return null;
}

/**
 * Query a given index for matching entries. Assumes the sender has opened the index and will close when finished.
 */
public static void findIndexMatches(SearchPattern pattern, Index index, IndexQueryRequestor requestor, SearchParticipant participant, IJavaSearchScope scope, IProgressMonitor monitor) throws IOException {
	pattern.findIndexMatches(index, requestor, participant, scope, monitor);
}

public static IJavaElement getProjectOrJar(IJavaElement element) {
	while (!(element instanceof IJavaProject) && !(element instanceof JarPackageFragmentRoot)) {
		element = element.getParent();
	}
	return element;
}

public static IJavaElement projectOrJarFocus(SearchPattern pattern) {
	return pattern == null || pattern.focus == null ? null : getProjectOrJar(pattern.focus);
}

public MatchLocator(
	SearchPattern pattern,
	SearchRequestor requestor,
	IJavaSearchScope scope,
	IProgressMonitor progressMonitor) {

	this.pattern = pattern;
	this.patternLocator = PatternLocator.patternLocator(this.pattern);
	this.matchContainer = this.patternLocator == null ? 0 : this.patternLocator.matchContainer();
	this.requestor = requestor;
	this.scope = scope;
	this.progressMonitor = progressMonitor;
	if (pattern instanceof PackageDeclarationPattern) {
		this.searchPackageDeclaration = true;
	} else if (pattern instanceof OrPattern) {
		this.searchPackageDeclaration = ((OrPattern)pattern).hasPackageDeclaration();
	} else {
		this.searchPackageDeclaration = false;
	}
	if (pattern instanceof MethodPattern) {
	    IType type = ((MethodPattern) pattern).declaringType;
	    if (type != null && !type.isBinary()) {
	    	SourceType sourceType = (SourceType) type;
	    	IMember local = sourceType.getOuterMostLocalContext();
	    	if (local instanceof IMethod) { // remember this method's range so we don't purge its statements.
	    		try {
	    			ISourceRange range = local.getSourceRange();
	    			this.sourceStartOfMethodToRetain  = range.getOffset();
	    			this.sourceEndOfMethodToRetain = this.sourceStartOfMethodToRetain + range.getLength() - 1; // offset is 0 based.
	    		} catch (JavaModelException e) {
	    			// drop silently. 
	    		}
	    	}
	    }
	}
}
/**
 * Add an additional binary type
 */
@Override
public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
	this.lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
}
/**
 * Add an additional compilation unit into the loop
 *  ->  build compilation unit declarations, their bindings and record their results.
 */
@Override
public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
	// Switch the current policy and compilation result for this unit to the requested one.
	CompilationResult unitResult = new CompilationResult(sourceUnit, 1, 1, this.options.maxProblemsPerUnit);
//{ObjectTeams: setup Dependencies for the other parser etc.
/* orig:
	try {
:giro */
	try (Config config = Dependencies.setup(this, basicParser(), this.lookupEnvironment, true, true))
	{
	// strictDiet since we will only dietParse and not even go beyond STATE_BINDINGS_COMPLETED
//carp}
		CompilationUnitDeclaration parsedUnit = basicParser().dietParse(sourceUnit, unitResult);
//{ObjectTeams: never try to get this unit's method bodies:
		parsedUnit.parseMethodBodies = false;
// SH}			
		this.lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction);
		this.lookupEnvironment.completeTypeBindings(parsedUnit, true);
	} catch (AbortCompilationUnit e) {
		// at this point, currentCompilationUnitResult may not be sourceUnit, but some other
		// one requested further along to resolve sourceUnit.
		if (unitResult.compilationUnit == sourceUnit) { // only report once
			//requestor.acceptResult(unitResult.tagAsAccepted());
		} else {
			throw e; // want to abort enclosing request to compile
		}
	}
	// Display unit error in debug mode
	if (BasicSearchEngine.VERBOSE) {
		if (unitResult.problemCount > 0) {
			System.out.println(unitResult);
		}
	}
}
/**
 * Add additional source types
 */
@Override
public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
	// case of SearchableEnvironment of an IJavaProject is used
	ISourceType sourceType = sourceTypes[0];
	while (sourceType.getEnclosingType() != null)
		sourceType = sourceType.getEnclosingType();
	if (sourceType instanceof SourceTypeElementInfo) {
		// get source
		SourceTypeElementInfo elementInfo = (SourceTypeElementInfo) sourceType;
		IType type = elementInfo.getHandle();
		ICompilationUnit sourceUnit = (ICompilationUnit) type.getCompilationUnit();
		accept(sourceUnit, accessRestriction);
	} else {
		CompilationResult result = new CompilationResult(sourceType.getFileName(), 1, 1, 0);
		CompilationUnitDeclaration unit =
			SourceTypeConverter.buildCompilationUnit(
				sourceTypes,
				SourceTypeConverter.FIELD_AND_METHOD // need field and methods
				| SourceTypeConverter.MEMBER_TYPE, // need member types
				// no need for field initialization
				this.lookupEnvironment.problemReporter,
				result);
//{ObjectTeams: Unchanged, but note, that this is controlled by Dependencies:
		if(unit != null) {
			this.lookupEnvironment.buildTypeBindings(unit, accessRestriction);
			this.lookupEnvironment.completeTypeBindings(unit, true);
		}
// SH}
	}
}
protected Parser basicParser() {
	if (this.basicParser == null) {
		ProblemReporter problemReporter =
			new ProblemReporter(
				DefaultErrorHandlingPolicies.proceedWithAllProblems(),
				this.options,
				new DefaultProblemFactory());
		this.basicParser = new Parser(problemReporter, false);
		this.basicParser.reportOnlyOneSyntaxError = true;
	}
	return this.basicParser;
}
/*
 * Caches the given binary type in the lookup environment and returns it.
 * Returns the existing one if already cached.
 * Returns null if source type binding was cached.
 */
protected BinaryTypeBinding cacheBinaryType(IType type, IBinaryType binaryType) throws JavaModelException {
	IType enclosingType = type.getDeclaringType();
	if (enclosingType != null)
		cacheBinaryType(enclosingType, null); // cache enclosing types first, so that binary type can be found in lookup enviroment
	if (binaryType == null) {
		ClassFile classFile = (ClassFile) type.getClassFile();
		try {
			binaryType = getBinaryInfo(classFile, classFile.resource());
		} catch (CoreException e) {
			if (e instanceof JavaModelException) {
				throw (JavaModelException) e;
			} else {
				throw new JavaModelException(e);
			}
		}
	}
	BinaryTypeBinding binding = this.lookupEnvironment.cacheBinaryType(binaryType, null /*no access restriction*/);
	if (binding == null) { // it was already cached as a result of a previous query
		char[][] compoundName = CharOperation.splitOn('.', type.getFullyQualifiedName().toCharArray());
		ReferenceBinding referenceBinding = this.lookupEnvironment.getCachedType(compoundName);
		if (referenceBinding != null && (referenceBinding instanceof BinaryTypeBinding))
			binding = (BinaryTypeBinding) referenceBinding; // if the binding could be found and if it comes from a binary type
	}
	return binding;
}
/*
 * Computes the super type names of the focus type if any.
 */
protected char[][][] computeSuperTypeNames(IType focusType) {
	String fullyQualifiedName = focusType.getFullyQualifiedName();
	int lastDot = fullyQualifiedName.lastIndexOf('.');
	char[] qualification = lastDot == -1 ? CharOperation.NO_CHAR : fullyQualifiedName.substring(0, lastDot).toCharArray();
	char[] simpleName = focusType.getElementName().toCharArray();

	SuperTypeNamesCollector superTypeNamesCollector =
		new SuperTypeNamesCollector(
			this.pattern,
			simpleName,
			qualification,
			new MatchLocator(this.pattern, this.requestor, this.scope, this.progressMonitor), // clone MatchLocator so that it has no side effect
			focusType,
			this.progressMonitor);
	try {
		this.allSuperTypeNames = superTypeNamesCollector.collect();
	} catch (JavaModelException e) {
		// problem collecting super type names: leave it null
	}
	return this.allSuperTypeNames;
}
/**
 * Creates an IMethod from the given lambda declaration and type.
 */
protected IJavaElement createHandle(LambdaExpression lambdaExpression, IJavaElement parent) {
	org.eclipse.jdt.internal.core.LambdaExpression lambdaElement = LambdaFactory.createLambdaExpression((JavaElement) parent, lambdaExpression);
	IMethod lambdaMethodElement = lambdaElement.getMethod();
	this.methodHandles.add(lambdaMethodElement);
	return lambdaMethodElement;
}
/**
 * Creates an IMethod from the given method declaration and type.
 */
protected IJavaElement createHandle(AbstractMethodDeclaration method, IJavaElement parent) {
	if (!(parent instanceof IType)) return parent;

	IType type = (IType) parent;
//{ObjectTeams: retrench signature of callin method:
/* orig:
	Argument[] arguments = method.arguments;
  :giro */	
	Argument[] arguments = MethodSignatureEnhancer.getSourceArguments(method, this.options.weavingScheme);
// SH}
	int argCount = arguments == null ? 0 : arguments.length;
	if (type.isBinary()) {
		// don't cache the methods of the binary type
		// fall thru if its a constructor with a synthetic argument... find it the slower way
		IBinaryType reader = classFileReader(type);
		if (reader != null) {
			// build arguments names
			boolean firstIsSynthetic = false;
			if (reader.isMember() && method.isConstructor() && !Flags.isStatic(reader.getModifiers())) { // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=48261
				firstIsSynthetic = true;
				argCount++;
			}
			char[][] argumentTypeNames = new char[argCount][];
			for (int i = 0; i < argCount; i++) {
				char[] typeName = null;
				if (i == 0 && firstIsSynthetic) {
					typeName = type.getDeclaringType().getFullyQualifiedName().toCharArray();
				} else if (arguments != null) {
					TypeReference typeRef = arguments[firstIsSynthetic ? i - 1 : i].type;
					typeName = CharOperation.concatWith(typeRef.getTypeName(), '.');
					for (int k = 0, dim = typeRef.dimensions(); k < dim; k++)
						typeName = CharOperation.concat(typeName, new char[] {'[', ']'});
				}
				if (typeName == null) {
					// invalid type name
					return null;
				}
				argumentTypeNames[i] = typeName;
			}
			// return binary method
			IMethod binaryMethod = createBinaryMethodHandle(type, method.selector, argumentTypeNames);
			if (binaryMethod == null) {
				// when first attempt fails, try with similar matches if any...
				PossibleMatch similarMatch = this.currentPossibleMatch.getSimilarMatch();
				while (similarMatch != null) {
					type = ((ClassFile)similarMatch.openable).getType();
					binaryMethod = createBinaryMethodHandle(type, method.selector, argumentTypeNames);
					if (binaryMethod != null) {
						return binaryMethod;
					}
					similarMatch = similarMatch.getSimilarMatch();
				}
			}
			return binaryMethod;
		}
		if (BasicSearchEngine.VERBOSE) {
			System.out.println("Not able to createHandle for the method " + //$NON-NLS-1$
					CharOperation.charToString(method.selector) + " May miss some results");  //$NON-NLS-1$
		}
		return null;
	}

	String[] parameterTypeSignatures = new String[argCount];
	if (arguments != null) {
		for (int i = 0; i < argCount; i++) {
			TypeReference typeRef = arguments[i].type;
			char[] typeName = CharOperation.concatWith(typeRef.getParameterizedTypeName(), '.');
			parameterTypeSignatures[i] = Signature.createTypeSignature(typeName, false);
		}
	}
//{ObjectTeams: be sure to use correct selectors even for role constructors (with __OT__)	
	String selector = new String(method.selector);
	if (method.isConstructor()) 
		selector = parent.getElementName();
	return createMethodHandle(type, selector, parameterTypeSignatures);
/* orig:	
	return createMethodHandle(type, new String(method.selector), parameterTypeSignatures);
  :giro */
//jsv,gbr+SH}
}
/*
 * Create binary method handle
 */
IMethod createBinaryMethodHandle(IType type, char[] methodSelector, char[][] argumentTypeNames) {
	IBinaryType reader = MatchLocator.classFileReader(type);
	if (reader != null) {
		IBinaryMethod[] methods = reader.getMethods();
		if (methods != null) {
			int argCount = argumentTypeNames == null ? 0 : argumentTypeNames.length;
			nextMethod : for (int i = 0, methodsLength = methods.length; i < methodsLength; i++) {
				IBinaryMethod binaryMethod = methods[i];
				char[] selector = binaryMethod.isConstructor() ? type.getElementName().toCharArray() : binaryMethod.getSelector();
				if (CharOperation.equals(selector, methodSelector)) {
					char[] signature = binaryMethod.getGenericSignature();
					if (signature == null) signature = binaryMethod.getMethodDescriptor();
					char[][] parameterTypes = Signature.getParameterTypes(signature);
					if (argCount != parameterTypes.length) continue nextMethod;
					if (argumentTypeNames != null) {
						for (int j = 0; j < argCount; j++) {
							char[] parameterTypeName = ClassFileMatchLocator.convertClassFileFormat(parameterTypes[j]);
							if (!CharOperation.endsWith(Signature.toCharArray(Signature.getTypeErasure(parameterTypeName)), CharOperation.replaceOnCopy(argumentTypeNames[j], '$', '.')))
								continue nextMethod;
							parameterTypes[j] = parameterTypeName;
						}
					}
					return (IMethod) createMethodHandle(type, new String(selector), CharOperation.toStrings(parameterTypes));
				}
			}
		}
	}
	return null;
}
/*
 * Create method handle.
 * Store occurrences for create handle to retrieve possible duplicate ones.
 */
private IJavaElement createMethodHandle(IType type, String methodName, String[] parameterTypeSignatures) {
	IMethod methodHandle = type.getMethod(methodName, parameterTypeSignatures);
	if (methodHandle instanceof SourceMethod) {
		while (this.methodHandles.contains(methodHandle)) {
			((SourceMethod) methodHandle).occurrenceCount++;
		}
	}
	this.methodHandles.add(methodHandle);
	return methodHandle;
}
/**
 * Creates an IField from the given field declaration and type.
 */
protected IJavaElement createHandle(FieldDeclaration fieldDeclaration, TypeDeclaration typeDeclaration, IJavaElement parent) {
	if (!(parent instanceof IType)) return parent;
	IType type = (IType) parent;

	switch (fieldDeclaration.getKind()) {
		case AbstractVariableDeclaration.FIELD :
		case AbstractVariableDeclaration.ENUM_CONSTANT :
			return ((IType) parent).getField(new String(fieldDeclaration.name));
	}
	if (type.isBinary()) {
		// do not return initializer for binary types
		// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=98378
		return type;
	}
	// find occurrence count of the given initializer in its type declaration
	int occurrenceCount = 0;
	FieldDeclaration[] fields = typeDeclaration.fields;
	int length = fields == null ? 0 : fields.length;
	for (int i = 0; i < length; i++) {
		if (fields[i].getKind() == AbstractVariableDeclaration.INITIALIZER) {
			occurrenceCount++;
			if (fields[i].equals(fieldDeclaration)) break;
		}
	}
	return ((IType) parent).getInitializer(occurrenceCount);
}
/**
 * Create an handle for a local variable declaration (may be a local variable or type parameter).
 */
protected IJavaElement createHandle(AbstractVariableDeclaration variableDeclaration, IJavaElement parent) {
	boolean isParameter = true;
	switch (variableDeclaration.getKind()) {
		case AbstractVariableDeclaration.LOCAL_VARIABLE:
			isParameter = false;
			//$FALL-THROUGH$
		case AbstractVariableDeclaration.PARAMETER:
			if (variableDeclaration.type.resolvedType != null) {
				return new LocalVariable((JavaElement)parent,
					new String(variableDeclaration.name),
					variableDeclaration.declarationSourceStart,
					variableDeclaration.declarationSourceEnd,
					variableDeclaration.sourceStart,
					variableDeclaration.sourceEnd,
					new String(variableDeclaration.type.resolvedType.signature()),
					variableDeclaration.annotations,
					variableDeclaration.modifiers,
					isParameter,
					variableDeclaration.type.getAnnotationsOnDimensions()
				);
			}
			break;
		case AbstractVariableDeclaration.TYPE_PARAMETER:
			return new org.eclipse.jdt.internal.core.TypeParameter((JavaElement)parent, new String(variableDeclaration.name));
//{ObjectTeams: TypeValueParameter: TODO(SH): test it
		case AbstractVariableDeclaration.TYPE_VALUE_PARAMETER:
			if (!(parent instanceof IType)) return parent;
			return ((IType) parent).getField(new String(variableDeclaration.name));
// SH}	
	}
	return null;
}
/**
 * Create an handle for a local variable declaration (may be a local variable or type parameter).
 */
protected IJavaElement createHandle(Annotation annotation, IAnnotatable parent) {
	if (parent == null) return null;
	TypeReference typeRef = annotation.type;
	char[][] typeName = typeRef.getTypeName();
	String name = new String(typeName[typeName.length-1]);
	try {
		IAnnotation[] annotations = parent.getAnnotations();
		int length = annotations == null ? 0 : annotations.length;
		for (int i=0; i<length; i++) {
			if (annotations[i].getElementName().equals(name)) {
				return annotations[i];
			}
		}
		if (parent instanceof LocalVariable) {
			LocalVariable localVariable = (LocalVariable) parent;
			IAnnotation[][] annotationsOnDimensions = localVariable.annotationsOnDimensions;
			int noOfDimensions = annotationsOnDimensions == null ? 0 : annotationsOnDimensions.length;
			for (int i = 0; i < noOfDimensions; ++i) {
				IAnnotation[] dimAnnotations = annotationsOnDimensions[i];
				int noOfAnnotations = dimAnnotations.length;
				for (int j = 0; j < noOfAnnotations; ++j) {
					if (dimAnnotations[j].getElementName().equals(name))
						return dimAnnotations[j];
				}
			}
		}
	}
	catch (JavaModelException jme) {
		// skip
	}
	return null;
}
/*
 * Create handles for a list of fields
 */
private IJavaElement[] createHandles(FieldDeclaration[] fields, TypeDeclaration type, IJavaElement parent) {
	IJavaElement[] otherElements = null;
	if (fields != null) {
		int length = fields.length;
		int size = 0;
		while (size<length && fields[size] != null) {
			size++;
		}
		otherElements = new IJavaElement[size];
		for (int j=0; j<size; j++) {
			otherElements[j] = createHandle(fields[j], type, parent);
		}
	}
	return otherElements;
}
/*
 * Creates hierarchy resolver if needed.
 * Returns whether focus is visible.
 */
protected boolean createHierarchyResolver(IType focusType, PossibleMatch[] possibleMatches) {
	// cache focus type if not a possible match
	char[][] compoundName = CharOperation.splitOn('.', focusType.getFullyQualifiedName().toCharArray());
	boolean isPossibleMatch = false;
	for (int i = 0, length = possibleMatches.length; i < length; i++) {
		if (CharOperation.equals(possibleMatches[i].compoundName, compoundName)) {
			isPossibleMatch = true;
			break;
		}
	}
	if (!isPossibleMatch) {
		if (focusType.isBinary()) {
			try {
				cacheBinaryType(focusType, null);
			} catch (JavaModelException e) {
				return false;
			}
		} else {
			// cache all types in the focus' compilation unit (even secondary types)
			accept((ICompilationUnit) focusType.getCompilationUnit(), null /*TODO no access restriction*/);
		}
	}

	// resolve focus type
	this.hierarchyResolver = new HierarchyResolver(this.lookupEnvironment, null/*hierarchy is not going to be computed*/);
	ReferenceBinding binding = this.hierarchyResolver.setFocusType(compoundName);
	return binding != null && binding.isValidBinding() && (binding.tagBits & TagBits.HierarchyHasProblems) == 0;
}
/**
 * Creates an IImportDeclaration from the given import statement
 */
protected IJavaElement createImportHandle(ImportReference importRef) {
	char[] importName = CharOperation.concatWith(importRef.getImportName(), '.');
	if ((importRef.bits & ASTNode.OnDemand) != 0)
		importName = CharOperation.concat(importName, ".*" .toCharArray()); //$NON-NLS-1$
	Openable openable = this.currentPossibleMatch.openable;
	if (openable instanceof CompilationUnit)
		return ((CompilationUnit) openable).getImport(new String(importName));

	if (openable instanceof ModularClassFile)
		return openable;
	// binary types do not contain import statements so just answer the top-level type as the element
	IType binaryType = ((ClassFile) openable).getType();
	String typeName = binaryType.getElementName();
	int lastDollar = typeName.lastIndexOf('$');
	if (lastDollar == -1) return binaryType;
	return createTypeHandle(typeName.substring(0, lastDollar));
}
/**
 * Creates an IImportDeclaration from the given import statement
 */
protected IJavaElement createPackageDeclarationHandle(CompilationUnitDeclaration unit) {
	if (unit.isPackageInfo()) {
		char[] packName = CharOperation.concatWith(unit.currentPackage.getImportName(), '.');
		Openable openable = this.currentPossibleMatch.openable;
		if (openable instanceof CompilationUnit) {
			return ((CompilationUnit) openable).getPackageDeclaration(new String(packName));
		}
	}
	return createTypeHandle(new String(unit.getMainTypeName()));
}
/**
 * Creates an IType from the given simple top level type name.
 */
protected IType createTypeHandle(String simpleTypeName) {
	Openable openable = this.currentPossibleMatch.openable;
	if (openable instanceof CompilationUnit)
		return ((CompilationUnit) openable).getType(simpleTypeName);

	IType binaryType = ((ClassFile) openable).getType();
	String binaryTypeQualifiedName = binaryType.getTypeQualifiedName();
	if (simpleTypeName.equals(binaryTypeQualifiedName))
		return binaryType; // answer only top-level types, sometimes the classFile is for a member/local type

	// type name may be null for anonymous (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=164791)
	String classFileName = simpleTypeName.length() == 0 ? binaryTypeQualifiedName : simpleTypeName;
	IOrdinaryClassFile classFile = binaryType.getPackageFragment().getOrdinaryClassFile(classFileName + SuffixConstants.SUFFIX_STRING_class);
	return classFile.getType();
}
//{ObjectTeams: accessible for ReferenceToTeamLocator:
/* orig:
protected boolean encloses(IJavaElement element) {
  :giro */
public boolean encloses(IJavaElement element) {
// SH}
	if (element != null) {
		if (this.scope instanceof HierarchyScope)
			return ((HierarchyScope)this.scope).encloses(element, this.progressMonitor);
		else 
			return this.scope.encloses(element);
	}
	return false;
}
private boolean filterEnum(SearchMatch match) {
	
	// filter org.apache.commons.lang.enum package for projects above 1.5 
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=317264	
	IJavaElement element = (IJavaElement)match.getElement();
	PackageFragment pkg = (PackageFragment)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
	if (pkg != null) {
		// enum was found in org.apache.commons.lang.enum at index 5
		if (pkg.names.length == 5 && pkg.names[4].equals("enum")) {  //$NON-NLS-1$
			if (this.options == null) {
				IJavaProject proj = (IJavaProject)pkg.getAncestor(IJavaElement.JAVA_PROJECT);
				String complianceStr = proj.getOption(CompilerOptions.OPTION_Source, true);
				if (CompilerOptions.versionToJdkLevel(complianceStr) >= ClassFileConstants.JDK1_5)
					return true;
			} else if (this.options.sourceLevel >= ClassFileConstants.JDK1_5) {
				return true;
			}
		}
	}
	return false;
}

/* (non-Javadoc)
 * Return info about last type argument of a parameterized type reference.
 * These info are made of concatenation of 2 int values which are respectively
 *  depth and end position of the last type argument.
 * For example, this method will return 0x300000020 for type ref List<List<List<String>>>
 * if end position of type reference "String" equals 32.
 */
private long findLastTypeArgumentInfo(TypeReference typeRef) {
	// Get last list of type arguments for parameterized qualified type reference
	TypeReference lastTypeArgument = typeRef;
	int depth = 0;
	while (true) {
		TypeReference[] lastTypeArguments = null;
		if (lastTypeArgument instanceof ParameterizedQualifiedTypeReference) {
			ParameterizedQualifiedTypeReference pqtRef = (ParameterizedQualifiedTypeReference) lastTypeArgument;
			for (int i=pqtRef.typeArguments.length-1; i>=0 && lastTypeArguments==null; i--) {
				lastTypeArguments = pqtRef.typeArguments[i];
			}
		}
		// Get last type argument for single type reference of last list of argument of parameterized qualified type reference
		TypeReference last = null;
		if (lastTypeArgument instanceof ParameterizedSingleTypeReference || lastTypeArguments != null) {
			if (lastTypeArguments == null) {
				lastTypeArguments = ((ParameterizedSingleTypeReference)lastTypeArgument).typeArguments;
			}
			if (lastTypeArguments != null) {
				for (int i=lastTypeArguments.length-1; i>=0 && last==null; i++) {
					last = lastTypeArguments[i];
				}
			}
		}
		if (last == null) break;
		depth++;
		lastTypeArgument = last;
	}
	// Current type reference is not parameterized. So, it is the last type argument
	return (((long) depth) << 32) + lastTypeArgument.sourceEnd;
}
protected IBinaryType getBinaryInfo(ClassFile classFile, IResource resource) throws CoreException {
	BinaryType binaryType = (BinaryType) classFile.getType();
	if (classFile.isOpen())
		return (IBinaryType) binaryType.getElementInfo(); // reuse the info from the java model cache

	// create a temporary info
	IBinaryType info;
	try {
		PackageFragment pkg = (PackageFragment) classFile.getParent();
		PackageFragmentRoot root = (PackageFragmentRoot) pkg.getParent();
		if (root.isArchive()) {
			// class file in a jar
			String classFileName = classFile.getElementName();
			String classFilePath = Util.concatWith(pkg.names, classFileName, '/');
			ZipFile zipFile = null;
			try {
				zipFile = ((JarPackageFragmentRoot) root).getJar();
				info = ClassFileReader.read(zipFile, classFilePath);
			} finally {
				JavaModelManager.getJavaModelManager().closeZipFile(zipFile);
			}
		} else {
			// class file in a directory
			info = Util.newClassFileReader(resource);
		}
		if (info == null) throw binaryType.newNotPresentException();
		return info;
	} catch (ClassFormatException e) {
		//e.printStackTrace();
		return null;
	} catch (java.io.IOException e) {
		throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
	}
}
protected IType getFocusType() {
	return this.scope instanceof HierarchyScope ? ((HierarchyScope) this.scope).focusType : null;
}
protected void getMethodBodies(CompilationUnitDeclaration unit, MatchingNodeSet nodeSet) {
	if (unit.ignoreMethodBodies) {
		unit.ignoreFurtherInvestigation = true;
		return; // if initial diet parse did not work, no need to dig into method bodies.
	}

	// save existing values to restore them at the end of the parsing process
	// see bug 47079 for more details
	int[] oldLineEnds = this.parser.scanner.lineEnds;
	int oldLinePtr = this.parser.scanner.linePtr;

	try {
		CompilationResult compilationResult = unit.compilationResult;
		this.parser.scanner.setSource(compilationResult);

		if (this.parser.javadocParser.checkDocComment) {
			char[] contents = compilationResult.compilationUnit.getContents();
			this.parser.javadocParser.scanner.setSource(contents);
		}
		this.parser.nodeSet = nodeSet;
		this.parser.parseBodies(unit);
	} finally {
		this.parser.nodeSet = null;
		// this is done to prevent any side effects on the compilation unit result
		// line separator positions array.
		this.parser.scanner.lineEnds = oldLineEnds;
		this.parser.scanner.linePtr = oldLinePtr;
	}
}
protected TypeBinding getType(Object typeKey, char[] typeName) {
	if (this.unitScope == null || typeName == null || typeName.length == 0) return null;
	// Try to get binding from cache
	Binding binding = (Binding) this.bindings.get(typeKey);
	if (binding != null) {
		if (binding instanceof TypeBinding && binding.isValidBinding())
			return (TypeBinding) binding;
		return null;
	}
	// Get binding from unit scope
	char[][] compoundName = CharOperation.splitOn('.', typeName);
	TypeBinding typeBinding = this.unitScope.getType(compoundName, compoundName.length);
	this.unitScopeTypeBinding = typeBinding; //cache.
	if (typeBinding == null || !typeBinding.isValidBinding()) {
		typeBinding = this.lookupEnvironment.getType(compoundName, this.unitScope.module());
	}
	this.bindings.put(typeKey, typeBinding);
	return typeBinding != null && typeBinding.isValidBinding() ? typeBinding : null;
}
public MethodBinding getMethodBinding(MethodPattern methodPattern) {
	this.unitScopeTypeBinding = null;
    MethodBinding methodBinding = getMethodBinding0(methodPattern);
    if (methodBinding != null)
    	return methodBinding; // known to be valid.
    // special handling for methods of anonymous/local types. Since these cannot be looked up in the environment the usual way ...
    if (methodPattern.focus instanceof SourceMethod) {
    	char[] typeName = PatternLocator.qualifiedPattern(methodPattern.declaringSimpleName, methodPattern.declaringQualification);
    	if (typeName != null) {
    		IType type = methodPattern.declaringType;
    		IType enclosingType = type.getDeclaringType();
    		while (enclosingType != null) {
    			type = enclosingType;
    			enclosingType = type.getDeclaringType();
    		}
    		typeName = type.getFullyQualifiedName().toCharArray();
    		TypeBinding declaringTypeBinding = getType(typeName, typeName);
    		if (declaringTypeBinding instanceof SourceTypeBinding) {
    			SourceTypeBinding sourceTypeBinding = ((SourceTypeBinding) declaringTypeBinding);
    			ClassScope skope = sourceTypeBinding.scope;
    			if (skope != null) {
    				CompilationUnitDeclaration unit = skope.referenceCompilationUnit();
    				if (unit != null) {
    					AbstractMethodDeclaration amd = new ASTNodeFinder(unit).findMethod((IMethod) methodPattern.focus);
    					if (amd != null && amd.binding != null && amd.binding.isValidBinding()) {
    						this.bindings.put(methodPattern, amd.binding);
    						return amd.binding;
    					}
    				}
    			}
    		}
    	}
    } else if (methodPattern.focus instanceof BinaryMethod &&
    		methodPattern.declaringType instanceof BinaryType &&
    		this.unitScopeTypeBinding instanceof ProblemReferenceBinding) {//Get binding from unit scope for non-visible member of binary type
    	char[] typeName = PatternLocator.qualifiedPattern(methodPattern.declaringSimpleName, methodPattern.declaringQualification);
    	if (typeName != null) {
    		IType type = methodPattern.declaringType;
    		IType enclosingType = type.getDeclaringType();
    		while (enclosingType != null) {
    			type = enclosingType;
    			enclosingType = type.getDeclaringType();
    		}
    		typeName = type.getFullyQualifiedName().toCharArray();
    		TypeBinding typeBinding = this.unitScopeTypeBinding;
    		if (typeBinding instanceof ProblemReferenceBinding) {
    			ProblemReferenceBinding problemReferenceBinding = (ProblemReferenceBinding) this.unitScopeTypeBinding;
    			ReferenceBinding closestMatch = (problemReferenceBinding.problemId() == ProblemReasons.NotVisible) ?
    					problemReferenceBinding.closestReferenceMatch() : null;
    					return closestMatch != null ?  getMethodBinding(methodPattern, closestMatch) : null;
    		}
    	}
    }
	return null;
}

private List<String> getInverseFullName(char[] qualifier, char[] simpleName) {
	List <String> result = new ArrayList<String>();
	if (qualifier != null && qualifier.length > 0) {
		result.addAll(Arrays.asList(new String(qualifier).split("\\.")));//$NON-NLS-1$
		Collections.reverse(result);
	}
	if (simpleName != null) result.add(0, new String(simpleName));
	return result;
}

/** returns the row index which has the highest column entry.
 * TODO: rewrite this code with list when (if) we move to 1.8 [with FP constructs].
 */
private int  getMaxResult(int[][] resultsMap) {
	int rows = resultsMap.length;
	int cols = resultsMap[0].length;
	List <Integer> candidates = new ArrayList<Integer>();
	candidates.add(0); //default row

	for (int j = 0; j < cols; ++j) {
		int current = resultsMap[0][j];
		for (int i = 1; i < rows; ++i) {
			int tmp = resultsMap[i][j];
			if (tmp < current) continue;
			if (tmp > current)  { 
				current = tmp;
				candidates.clear();
			}
			candidates.add(i);// there is atleast one element always.
		}
		if (candidates.size() <= 1) break; // found
	}
	return candidates.get(0);
}

/** apply the function to map the parameter full name to an index 
 */
private int mapParameter(List <String> patternParameterFullName, List <String> methodParameterFullName) {
	int patternLen = patternParameterFullName.size();
	int methodLen = methodParameterFullName.size();
	int size = patternLen < methodLen ? patternLen : methodLen;
	int result = -1;
	for (int i = 0; i < size; i++) {
		if (!patternParameterFullName.get(i).equals(methodParameterFullName.get(i))) break;
		++result;
	}
	return patternLen == methodLen && result + 1 == patternLen ? Integer.MAX_VALUE : result;
}
/**
 * returns an array of integers whose elements are matching indices.
 * As a special case, full match would have max value as the index.
 */
private int[] getResultMap(Map<Integer, List<String>> patternMap, Map<Integer, List<String>> methodMap) {
	int paramLength = methodMap.size();
	int[] result = new int[paramLength];
	for (int p = 0; p < paramLength; p++) {
		result[p] = mapParameter(patternMap.get(p), methodMap.get(p));
	}
	return result;
}

private Map<Integer, List<String>> getSplitNames(char[][] qualifiedNames, char[][] simpleNames) {
	int paramLength = simpleNames.length;
	Map <Integer, List<String>> result = new HashMap<Integer, List<String>>();
	for (int p = 0; p < paramLength; p++) result.put(p, getInverseFullName(qualifiedNames[p], simpleNames[p]));
	return result;
}

private Map<Integer, List<String>> getSplitNames(MethodBinding method) {
	TypeBinding[] methodParameters = method.parameters;
	int paramLength = methodParameters == null ? 0 : methodParameters.length;
	Map <Integer, List<String>> result = new HashMap<Integer, List<String>>();
	for (int p = 0; p < paramLength; p++) result.put(p, getInverseFullName(methodParameters[p].qualifiedSourceName(), null)); // source is part of qualifiedSourceName here);
	return result;
}

/**
 * Selects the most applicable method (though similar but not to be confused with its namesake in jls)
 * All this machinery for that elusive uncommon case referred in bug 431357.
 */
private MethodBinding getMostApplicableMethod(List<MethodBinding> possibleMethods, MethodPattern methodPattern) {
	int size = possibleMethods.size();
	MethodBinding result = size != 0 ? possibleMethods.get(0) : null;
	if (size > 1) {
		// can cache but may not be worth since this is not a common case
		Map<Integer, List<String>> methodPatternReverseNames = getSplitNames(methodPattern.parameterQualifications, methodPattern.parameterSimpleNames);
		int len = possibleMethods.size();
		int[][] resultMaps = new int[len][];
		for (int i = 0; i < len; ++i) resultMaps[i] = getResultMap(methodPatternReverseNames, getSplitNames(possibleMethods.get(i)));
		result = possibleMethods.get(getMaxResult(resultMaps));
	}
	return result;
}

private MethodBinding getMethodBinding0(MethodPattern methodPattern) {
	if (this.unitScope == null) return null;
	// Try to get binding from cache
	Binding binding = (Binding) this.bindings.get(methodPattern);
	if (binding != null) {
		if (binding instanceof MethodBinding && binding.isValidBinding())
			return (MethodBinding) binding;
	}
	//	Get binding from unit scope
	char[] typeName = PatternLocator.qualifiedPattern(methodPattern.declaringSimpleName, methodPattern.declaringQualification);
	if (typeName == null) {
		if (methodPattern.declaringType == null) return null;
		typeName = methodPattern.declaringType.getFullyQualifiedName().toCharArray();
	}
	TypeBinding declaringTypeBinding = getType(typeName, typeName);
	MethodBinding result = null;
	if (declaringTypeBinding != null) {
		if (declaringTypeBinding.isArrayType()) {
			declaringTypeBinding = declaringTypeBinding.leafComponentType();
		}
		if (!declaringTypeBinding.isBaseType()) {
			result = getMethodBinding(methodPattern, declaringTypeBinding);
		}
	}
	this.bindings.put(methodPattern, result != null ? result : new ProblemMethodBinding(methodPattern.selector, null, ProblemReasons.NotFound));
	return result;
}
private boolean matchParams(MethodPattern methodPattern, int index, TypeBinding binding) {
	char[] qualifier = CharOperation.concat(methodPattern.parameterQualifications[index], methodPattern.parameterSimpleNames[index], '.');
	int offset = (qualifier.length > 0 && qualifier[0] == '*') ? 1 : 0;
	String s1 = new String(qualifier, offset, qualifier.length - offset);
	char[] s2 = CharOperation.concat(binding.qualifiedPackageName(), binding.qualifiedSourceName(), '.');
	return new String(s2).endsWith(s1);
}

private MethodBinding getMethodBinding(MethodPattern methodPattern, TypeBinding declaringTypeBinding) {
	MethodBinding result;
	char[][] parameterTypes = methodPattern.parameterSimpleNames;
	if (parameterTypes == null) return null;
	int paramTypeslength = parameterTypes.length;
	ReferenceBinding referenceBinding = (ReferenceBinding) declaringTypeBinding;
	MethodBinding[] methods = referenceBinding.getMethods(methodPattern.selector);
	int methodsLength = methods.length;
	TypeVariableBinding[] refTypeVariables = referenceBinding.typeVariables();
	int typeVarLength = refTypeVariables==null ? 0 : refTypeVariables.length;
	List <MethodBinding> possibleMethods = new ArrayList<MethodBinding>(methodsLength);
	for (int i=0; i<methodsLength; i++) {
		TypeBinding[] methodParameters = methods[i].parameters;
		int paramLength = methodParameters==null ? 0 : methodParameters.length;
		TypeVariableBinding[] methodTypeVariables = methods[i].typeVariables;
		int methTypeVarLength = methodTypeVariables==null ? 0 : methodTypeVariables.length;
		boolean found = false;
		if (methodParameters != null && paramLength == paramTypeslength) {
			for (int p=0; p<paramLength; p++) {
				TypeBinding parameter = methodParameters[p];
				if (matchParams(methodPattern, p, parameter)) {
					// param erasure match
					found = true;
				} else {
					// type variable
					found = false;
					if (refTypeVariables != null) {
						for (int v=0; v<typeVarLength; v++) {
							if (!CharOperation.equals(refTypeVariables[v].sourceName, parameterTypes[p])) {
								found = false;
								break;
							}
							found = true;
						}
					}
					if (!found && methodTypeVariables != null) {
						for (int v=0; v<methTypeVarLength; v++) {
							if (!CharOperation.equals(methodTypeVariables[v].sourceName, parameterTypes[p])) {
								found = false;
								break;
							}
							found = true;
						}
					}
					if (!found) break;
				}
			}
		}
		if (found) {
			possibleMethods.add(methods[i]);
		}
	}
	result =  getMostApplicableMethod(possibleMethods, methodPattern);
	return result;
}
protected boolean hasAlreadyDefinedType(CompilationUnitDeclaration parsedUnit) {
	CompilationResult result = parsedUnit.compilationResult;
	if (result == null) return false;
	for (int i = 0; i < result.problemCount; i++)
		if (result.problems[i].getID() == IProblem.DuplicateTypes)
			return true;
	return false;
}
/**
 * Create a new parser for the given project, as well as a lookup environment.
 */
public void initialize(JavaProject project, int possibleMatchSize) throws JavaModelException {
	// clean up name environment only if there are several possible match as it is reused
	// when only one possible match (bug 58581)
	if (this.nameEnvironment != null && possibleMatchSize != 1) {
		this.nameEnvironment.cleanup();
		this.unitScope = null; // don't leak a reference to the cleaned-up name environment
	}

	SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(this.workingCopies);

	List<IJavaProject> projects = new ArrayList<>();
	projects.add(project);
	if (this.pattern.focus != null) {
		IJavaProject focusProject = this.pattern.focus.getJavaProject();
		if (focusProject != project) {
			projects.add(focusProject);
		}
	}
	this.nameEnvironment = IndexBasedJavaSearchEnvironment.create(projects, this.workingCopies);

	// create lookup environment
	Map map = project.getOptions(true);
	map.put(CompilerOptions.OPTION_TaskTags, org.eclipse.jdt.internal.compiler.util.Util.EMPTY_STRING);
	this.options = new CompilerOptions(map);
	ProblemReporter problemReporter =
		new ProblemReporter(
			DefaultErrorHandlingPolicies.proceedWithAllProblems(),
			this.options,
			new DefaultProblemFactory());
	this.lookupEnvironment = new LookupEnvironment(this, this.options, problemReporter, this.nameEnvironment);
	this.lookupEnvironment.mayTolerateMissingType = true;
	this.parser = MatchLocatorParser.createParser(problemReporter, this);
	this.bindings = new SimpleLookupTable(); // For every LE

	// basic parser needs also to be reset as project options may have changed
	// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=163072
	this.basicParser = null;

	// remember project's name lookup
	this.nameLookup = searchableEnvironment.nameLookup;

	// initialize queue of units
	this.numberOfMatches = 0;
	this.matchesToProcess = new PossibleMatch[possibleMatchSize];

	this.lookupEnvironment.addResolutionListener(this.patternLocator);
}
private boolean skipMatch(JavaProject javaProject, PossibleMatch possibleMatch) {
	if (this.options.sourceLevel >= ClassFileConstants.JDK9) {
		char[] pModuleName = possibleMatch.getModuleName();
		if (pModuleName != null && this.lookupEnvironment.getModule(pModuleName) == null)
			return true;
	}
	return false;
}
protected void locateMatches(JavaProject javaProject, PossibleMatch[] possibleMatches, int start, int length) throws CoreException {
	initialize(javaProject, length);

	// create and resolve binding (equivalent to beginCompilation() in Compiler)
	boolean mustResolvePattern = this.pattern.mustResolve;
	boolean mustResolve = mustResolvePattern;
	this.patternLocator.mayBeGeneric = this.options.sourceLevel >= ClassFileConstants.JDK1_5;
	boolean bindingsWereCreated = mustResolve;

//{ObjectTeams: setup Dependencies
/* orig:
	try {
:giro */
	try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true, true)) // is strictDiet correct here? (SH).
	{
//carp}

//{ObjectTeams: by sorting short compound names to the front we force to
//              analyze teams before their role files, thus avoiding to #accept()
//              these role files which could later case duplicate type errors
//              (see Trac #92).
		Arrays.sort(possibleMatches, new Comparator<PossibleMatch> () {
			@Override
			public int compare(PossibleMatch o1, PossibleMatch o2) {
				// prefer source types over class files:
				boolean source1 = o1.openable instanceof CompilationUnit;
				boolean source2 = o2.openable instanceof CompilationUnit;
				if (source1 != source2)
					return source1 ? -1 : 1;
				// prefer short names over longer ones:
				int l1 = o1.compoundName != null ? o1.compoundName.length : 0;
				int l2 = o2.compoundName != null ? o2.compoundName.length : 0;
				if (l1 < l2) return -1;
				if (l1 > l2) return 1;
				return 0;
			}
		});
// SH}
		for (int i = start, maxUnits = start + length; i < maxUnits; i++) {
			PossibleMatch possibleMatch = possibleMatches[i];
			if (skipMatch(javaProject, possibleMatch)) continue;
			try {
				if (!parseAndBuildBindings(possibleMatch, mustResolvePattern)) continue;
				// Currently we only need to resolve over pattern flag if there's potential parameterized types
				if (this.patternLocator.mayBeGeneric) {
					// If pattern does not resolve then rely on possible match node set resolution
					// which may have been modified while locator was adding possible matches to it
					if (!mustResolvePattern && !mustResolve) {
						mustResolve = possibleMatch.nodeSet.mustResolve;
						bindingsWereCreated = mustResolve;
					}
				} else {
					// Reset matching node resolution with pattern one if there's no potential parameterized type
					// to minimize side effect on previous search behavior
					possibleMatch.nodeSet.mustResolve = mustResolvePattern;
				}
				// possible match node resolution has been merged with pattern one, so rely on it to know
				// whether we need to process compilation unit now or later
				if (!possibleMatch.nodeSet.mustResolve) {
					if (this.progressMonitor != null) {
						this.progressWorked++;
						if ((this.progressWorked%this.progressStep)==0) this.progressMonitor.worked(this.progressStep);
					}
					process(possibleMatch, bindingsWereCreated);
					if (this.numberOfMatches>0 && this.matchesToProcess[this.numberOfMatches-1] == possibleMatch) {
						// forget last possible match as it was processed
						this.numberOfMatches--;
					}
				}
			} finally {
				if (possibleMatch.hasSimilarMatch()) {
					// If there is similar match, then also process it
					// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=211872
					possibleMatches[i] = possibleMatch.getSimilarMatch();
					i--;
				}
				if (!possibleMatch.nodeSet.mustResolve)
					possibleMatch.cleanUp();
			}
		}
		if (mustResolve)
			this.lookupEnvironment.completeTypeBindings();

		// create hierarchy resolver if needed
		IType focusType = getFocusType();
		if (focusType == null) {
			this.hierarchyResolver = null;
		} else if (!createHierarchyResolver(focusType, possibleMatches)) {
			// focus type is not visible, use the super type names instead of the bindings
			if (computeSuperTypeNames(focusType) == null) return;
		}
	} catch (AbortCompilation e) {
		bindingsWereCreated = false;
	}

	if (!mustResolve) {
		return;
	}

	// possible match resolution
	for (int i = 0; i < this.numberOfMatches; i++) {
		if (this.progressMonitor != null && this.progressMonitor.isCanceled())
			throw new OperationCanceledException();
		PossibleMatch possibleMatch = this.matchesToProcess[i];
		this.matchesToProcess[i] = null; // release reference to processed possible match
		try {
			process(possibleMatch, bindingsWereCreated);
		} catch (AbortCompilation e) {
			// problem with class path: it could not find base classes
			// continue and try next matching openable reporting inaccurate matches (since bindings will be null)
			bindingsWereCreated = false;
		} catch (JavaModelException e) {
			// problem with class path: it could not find base classes
			// continue and try next matching openable reporting inaccurate matches (since bindings will be null)
			bindingsWereCreated = false;
		} finally {
			if (this.progressMonitor != null) {
				this.progressWorked++;
				if ((this.progressWorked%this.progressStep)==0) this.progressMonitor.worked(this.progressStep);
			}
			if (this.options.verbose)
				System.out.println(
					Messages.bind(Messages.compilation_done,
						new String[] {
							String.valueOf(i + 1),
							String.valueOf(this.numberOfMatches),
							new String(possibleMatch.parsedUnit.getFileName())
						}));
			// cleanup compilation unit result
			possibleMatch.cleanUp();
		}
	}
}
/**
 * Locate the matches amongst the possible matches.
 */
protected void locateMatches(JavaProject javaProject, PossibleMatchSet matchSet, int expected) throws CoreException {
	PossibleMatch[] possibleMatches = matchSet.getPossibleMatches(javaProject.getPackageFragmentRoots());
	int length = possibleMatches.length;
	// increase progress from duplicate matches not stored in matchSet while adding...
	if (this.progressMonitor != null && expected>length) {
		this.progressWorked += expected-length;
		this.progressMonitor.worked( expected-length);
	}
	// locate matches (processed matches are limited to avoid problem while using VM default memory heap size)
	for (int index = 0; index < length;) {
		int max = Math.min(MAX_AT_ONCE, length - index);
		locateMatches(javaProject, possibleMatches, index, max);
		index += max;
	}
	this.patternLocator.clear();
}
/**
 * Locate the matches in the given files and report them using the search requestor.
 */
public void locateMatches(SearchDocument[] searchDocuments) throws CoreException {
	if (this.patternLocator == null) return;
	int docsLength = searchDocuments.length;
	int progressLength = docsLength;
	if (BasicSearchEngine.VERBOSE) {
		System.out.println("Locating matches in documents ["); //$NON-NLS-1$
		for (int i = 0; i < docsLength; i++)
			System.out.println("\t" + searchDocuments[i]); //$NON-NLS-1$
		System.out.println("]"); //$NON-NLS-1$
	}
	IJavaProject[] javaModelProjects = null;
	if (this.searchPackageDeclaration) {
		javaModelProjects = JavaModelManager.getJavaModelManager().getJavaModel().getJavaProjects();
		progressLength += javaModelProjects.length;
	}

	// init infos for progress increasing
	int n = progressLength<1000 ? Math.min(Math.max(progressLength/200+1, 2),4) : 5 *(progressLength/1000);
	this.progressStep = progressLength < n ? 1 : progressLength / n; // step should not be 0
	this.progressWorked = 0;

	// extract working copies
	ArrayList copies = new ArrayList();
	for (int i = 0; i < docsLength; i++) {
		SearchDocument document = searchDocuments[i];
		if (document instanceof WorkingCopyDocument) {
			copies.add(((WorkingCopyDocument)document).workingCopy);
		}
	}
	int copiesLength = copies.size();
	this.workingCopies = new org.eclipse.jdt.core.ICompilationUnit[copiesLength];
	copies.toArray(this.workingCopies);

	JavaModelManager manager = JavaModelManager.getJavaModelManager();
	this.bindings = new SimpleLookupTable();
	try {
		// optimize access to zip files during search operation
		manager.cacheZipFiles(this);

		// initialize handle factory (used as a cache of handles so as to optimize space)
		if (this.handleFactory == null)
			this.handleFactory = new HandleFactory();

		if (this.progressMonitor != null) {
			this.progressMonitor.beginTask("", searchDocuments.length); //$NON-NLS-1$
		}

		// initialize pattern for polymorphic search (i.e. method reference pattern)
		this.patternLocator.initializePolymorphicSearch(this);

		JavaProject previousJavaProject = null;
		PossibleMatchSet matchSet = new PossibleMatchSet();
		Util.sort(searchDocuments, new Util.Comparer() {
			@Override
			public int compare(Object a, Object b) {
				return ((SearchDocument)a).getPath().compareTo(((SearchDocument)b).getPath());
			}
		});
		int displayed = 0; // progress worked displayed
		String previousPath = null;
		SearchParticipant searchParticipant = null;
		for (int i = 0; i < docsLength; i++) {
			if (this.progressMonitor != null && this.progressMonitor.isCanceled()) {
				throw new OperationCanceledException();
			}

			// skip duplicate paths
			SearchDocument searchDocument = searchDocuments[i];
			if (searchParticipant == null) {
				searchParticipant = searchDocument.getParticipant();
			}
			searchDocuments[i] = null; // free current document
			String pathString = searchDocument.getPath();
			if (i > 0 && pathString.equals(previousPath)) {
				if (this.progressMonitor != null) {
					this.progressWorked++;
					if ((this.progressWorked%this.progressStep)==0) this.progressMonitor.worked(this.progressStep);
				}
				displayed++;
				continue;
			}
			previousPath = pathString;

			Openable openable;
			org.eclipse.jdt.core.ICompilationUnit workingCopy = null;
			if (searchDocument instanceof WorkingCopyDocument) {
				workingCopy = ((WorkingCopyDocument)searchDocument).workingCopy;
				openable = (Openable) workingCopy;
			} else {
				openable = this.handleFactory.createOpenable(pathString, this.scope);
			}
			if (openable == null) {
				if (this.progressMonitor != null) {
					this.progressWorked++;
					if ((this.progressWorked%this.progressStep)==0) this.progressMonitor.worked(this.progressStep);
				}
				displayed++;
				continue; // match is outside classpath
			}

			// create new parser and lookup environment if this is a new project
			IResource resource = null;
			openable = getCloserOpenable(openable, pathString);
			JavaProject javaProject = (JavaProject) openable.getJavaProject();
			resource = workingCopy != null ? workingCopy.getResource() : openable.getResource();
			if (resource == null)
				resource = javaProject.getProject(); // case of a file in an external jar or external folder
			if (!javaProject.equals(previousJavaProject)) {
				// locate matches in previous project
				if (previousJavaProject != null) {
					try {
						locateMatches(previousJavaProject, matchSet, i-displayed);
						displayed = i;
					} catch (JavaModelException e) {
						// problem with classpath in this project -> skip it
					}
					matchSet.reset();
				}
				previousJavaProject = javaProject;
			}
			PossibleMatch possibleMatch = new PossibleMatch(this, resource, openable, searchDocument,this.pattern.mustResolve);
			matchSet.add(possibleMatch);
			if (pathString.endsWith(TypeConstants.AUTOMATIC_MODULE_NAME)) {
				IPath path = resource.getFullPath();
				String s = (pathString.contains(path.lastSegment())) ?
						JavaModelManager.getLocalFile(path).toPath().toAbsolutePath().toString() :
						pathString.split(Pattern.quote("|"))[0]; //$NON-NLS-1$
				possibleMatch.autoModuleName = new String(AutomaticModuleNaming.determineAutomaticModuleName(s));
			}			
		}

		// last project
		if (previousJavaProject != null) {
			try {
				locateMatches(previousJavaProject, matchSet, docsLength-displayed);
			} catch (JavaModelException e) {
				// problem with classpath in last project -> ignore
			}
		}

		if (this.searchPackageDeclaration) {
			locatePackageDeclarations(searchParticipant, javaModelProjects);
		}

	} finally {
		if (this.progressMonitor != null)
			this.progressMonitor.done();
		if (this.nameEnvironment != null)
			this.nameEnvironment.cleanup();
		this.unitScope = null;
		manager.flushZipFiles(this);
		this.bindings = null;
	}
}
private IJavaSearchScope getSubScope(String optionString, long value, boolean ref) {
	if (this.subScope != null)
		return this.subScope;
	IPath[] enclosingProjectsAndJars = this.scope.enclosingProjectsAndJars();
	JavaModelManager manager = JavaModelManager.getJavaModelManager();
	HashSet<IJavaProject> set = new HashSet<>();
	for (int i = 0, l = enclosingProjectsAndJars.length; i < l; i++) {
		IPath path = enclosingProjectsAndJars[i];
		if (path.segmentCount() == 1) {
			IJavaProject p = manager.getJavaModel().getJavaProject(path.segment(0));
			if (p == null) continue;
			if (CompilerOptions.versionToJdkLevel(p.getOption(optionString, true)) >= value) {
				set.add(p);
			}
		}
	}
	return this.subScope = BasicSearchEngine.createJavaSearchScope(set.toArray(new IJavaProject[0]), ref);
}
private Openable getCloserOpenable(Openable openable, String pathString) {
	if (this.pattern instanceof TypeDeclarationPattern &&
			((TypeDeclarationPattern) this.pattern).moduleNames != null) {
		JavaProject javaProject = (JavaProject) openable.getJavaProject();
		PackageFragmentRoot root = openable.getPackageFragmentRoot();
		if (root instanceof JarPackageFragmentRoot) {
			JarPackageFragmentRoot jpkf = (JarPackageFragmentRoot) root;
			if (jpkf.getModuleDescription() != null &&
					CompilerOptions.versionToJdkLevel(javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true)) <
					ClassFileConstants.JDK9) {
				openable = this.handleFactory.createOpenable(pathString, 
						getSubScope(JavaCore.COMPILER_COMPLIANCE, ClassFileConstants.JDK9, false));
			}
		}
	}
	return openable;
}

/**
 * Locates the package declarations corresponding to this locator's pattern.
 */
protected void locatePackageDeclarations(SearchParticipant participant, IJavaProject[] projects) throws CoreException {
	locatePackageDeclarations(this.pattern, participant, projects);
}
/**
 * Locates the package declarations corresponding to the search pattern.
 */
protected void locatePackageDeclarations(SearchPattern searchPattern, SearchParticipant participant, IJavaProject[] projects) throws CoreException {
	if (this.progressMonitor != null && this.progressMonitor.isCanceled()) {
		throw new OperationCanceledException();
	}
	if (searchPattern instanceof OrPattern) {
		SearchPattern[] patterns = ((OrPattern) searchPattern).patterns;
		for (int i = 0, length = patterns.length; i < length; i++) {
			locatePackageDeclarations(patterns[i], participant, projects);
		}
	} else if (searchPattern instanceof PackageDeclarationPattern) {
		IJavaElement focus = searchPattern.focus;
		if (focus != null) {
			if (encloses(focus)) {
				SearchMatch match = new PackageDeclarationMatch(focus.getAncestor(IJavaElement.PACKAGE_FRAGMENT), SearchMatch.A_ACCURATE, -1, -1, participant, focus.getResource());
				report(match);
			}
			return;
		}
		PackageDeclarationPattern pkgPattern = (PackageDeclarationPattern) searchPattern;
		boolean isWorkspaceScope = this.scope == JavaModelManager.getJavaModelManager().getWorkspaceScope();
		IPath[] scopeProjectsAndJars =  isWorkspaceScope ? null : this.scope.enclosingProjectsAndJars();
		int scopeLength = isWorkspaceScope ? 0 : scopeProjectsAndJars.length;
		SimpleSet packages = new SimpleSet();
		for (int i = 0, length = projects.length; i < length; i++) {
			IJavaProject javaProject = projects[i];
			if (this.progressMonitor != null) {
				if (this.progressMonitor.isCanceled()) throw new OperationCanceledException();
				this.progressWorked++;
				if ((this.progressWorked%this.progressStep)==0) this.progressMonitor.worked(this.progressStep);
			}
			// Verify that project belongs to the scope
			if (!isWorkspaceScope) {
				boolean found = false;
				for (int j=0; j<scopeLength; j++) {
					if (javaProject.getPath().equals(scopeProjectsAndJars[j])) {
						found = true;
						break;
					}
				}
				if (!found) continue;
			}
			// Get all project package fragment names
			this.nameLookup = ((JavaProject) projects[i]).newNameLookup(this.workingCopies);
			IPackageFragment[] packageFragments = this.nameLookup.findPackageFragments(new String(pkgPattern.pkgName), false, true);
			int pLength = packageFragments == null ? 0 : packageFragments.length;
			// Report matches avoiding duplicate names
			for (int p=0; p<pLength; p++) {
				IPackageFragment fragment = packageFragments[p];
				if (packages.addIfNotIncluded(fragment) == null) continue;
				if (encloses(fragment)) {
					IResource resource = fragment.getResource();
					if (resource == null) // case of a file in an external jar
						resource = javaProject.getProject();
					try {
						if (encloses(fragment)) {
							SearchMatch match = new PackageDeclarationMatch(fragment, SearchMatch.A_ACCURATE, -1, -1, participant, resource);
							report(match);
						}
					} catch (JavaModelException e) {
						throw e;
					} catch (CoreException e) {
						throw new JavaModelException(e);
					}
				}
			}
		}
	}
}
//*/
protected IType lookupType(ReferenceBinding typeBinding) {
	if (typeBinding == null || !typeBinding.isValidBinding()) return null;

	char[] packageName = typeBinding.qualifiedPackageName();
	IPackageFragment[] pkgs = this.nameLookup.findPackageFragments(
		(packageName == null || packageName.length == 0)
			? IPackageFragment.DEFAULT_PACKAGE_NAME
			: new String(packageName),
		false);

	// iterate type lookup in each package fragment
	char[] sourceName = typeBinding.qualifiedSourceName();
	String typeName = new String(sourceName);
	int acceptFlag = 0;
	if (typeBinding.isAnnotationType()) {
		acceptFlag = NameLookup.ACCEPT_ANNOTATIONS;
	} else if (typeBinding.isEnum()) {
		acceptFlag = NameLookup.ACCEPT_ENUMS;
	} else if (typeBinding.isInterface()) {
		acceptFlag = NameLookup.ACCEPT_INTERFACES;
	} else if (typeBinding.isClass()) {
		acceptFlag = NameLookup.ACCEPT_CLASSES;
	}
	if (pkgs != null) {
		for (int i = 0, length = pkgs.length; i < length; i++) {
			IType type = this.nameLookup.findType(typeName, pkgs[i],  false,  acceptFlag, false, true/*consider secondary types*/);
			if (type != null) return type;
		}
	}

	// search inside enclosing element
	char[][] qualifiedName = CharOperation.splitOn('.', sourceName);
	int length = qualifiedName.length;
	if (length == 0) return null;

	IType type = createTypeHandle(new String(qualifiedName[0])); // find the top-level type
	if (type == null) return null;

	for (int i = 1; i < length; i++) {
		type = type.getType(new String(qualifiedName[i]));
		if (type == null) return null;
	}
	if (type.exists()) return type;
	return null;
}
public SearchMatch newDeclarationMatch(
		IJavaElement element,
		Binding binding,
		int accuracy,
		int offset,
		int length) {
	SearchParticipant participant = getParticipant();
	IResource resource = this.currentPossibleMatch.resource;
	return newDeclarationMatch(element, binding, accuracy, offset, length, participant, resource);
}

public SearchMatch newDeclarationMatch(
		IJavaElement element,
		Binding binding,
		int accuracy,
		int offset,
		int length,
		SearchParticipant participant,
		IResource resource) {
	switch (element.getElementType()) {
		//FIXME (carp): add support for method specs, etc.
		//FIXME (carp): also might need to beautify some copy-inheritance and other generated things
		case IJavaElement.PACKAGE_FRAGMENT:
			return new PackageDeclarationMatch(element, accuracy, offset, length, participant, resource);
		case IJavaElement.TYPE:
			return new TypeDeclarationMatch(binding == null ? element : ((JavaElement) element).resolved(binding), accuracy, offset, length, participant, resource);
		case IJavaElement.FIELD:
			return new FieldDeclarationMatch(binding == null ? element : ((JavaElement) element).resolved(binding), accuracy, offset, length, participant, resource);
		case IJavaElement.METHOD:
			return new MethodDeclarationMatch(binding == null ? element : ((JavaElement) element).resolved(binding), accuracy, offset, length, participant, resource);
		case IJavaElement.LOCAL_VARIABLE:
			return new LocalVariableDeclarationMatch(element, accuracy, offset, length, participant, resource);
		case IJavaElement.PACKAGE_DECLARATION:
			return new PackageDeclarationMatch(element, accuracy, offset, length, participant, resource);
		case IJavaElement.TYPE_PARAMETER:
			return new TypeParameterDeclarationMatch(element, accuracy, offset, length, participant, resource);
		case IJavaElement.JAVA_MODULE:
			ModuleDeclarationMatch match = new ModuleDeclarationMatch(binding == null ? element : ((JavaElement) element).resolved(binding), accuracy, offset, length, participant, resource);
			this.matchBinding.put(match, binding);
			return match;
		default:
			return null;
	}
}

public FieldReferenceMatch newFieldReferenceMatch(
		IJavaElement enclosingElement,
		IJavaElement localElement,
		Binding enclosingBinding,
		int accuracy,
		int offset,
		int length, ASTNode reference) {
	int bits = reference.bits;
	boolean isCompoundAssigned = (bits & ASTNode.IsCompoundAssigned) != 0;
	boolean isReadAccess = isCompoundAssigned || (bits & ASTNode.IsStrictlyAssigned) == 0;
	boolean isWriteAccess = isCompoundAssigned || (bits & ASTNode.IsStrictlyAssigned) != 0;
	if (isWriteAccess) {
		if (reference instanceof QualifiedNameReference) {
			char[][] tokens = ((QualifiedNameReference)reference).tokens;
			char[] lastToken = tokens[tokens.length-1];
			if (this.pattern instanceof OrPattern) {
				SearchPattern[] patterns = ((OrPattern) this.pattern).patterns;
				for (int i = 0, pLength = patterns.length; i < pLength; i++) {
					if (!this.patternLocator.matchesName(((VariablePattern)patterns[i]).name, lastToken)) {
			        	isWriteAccess = false;
			        	isReadAccess = true;
					}
				}
			} else if (!this.patternLocator.matchesName(((VariablePattern)this.pattern).name, lastToken)) {
	        	isWriteAccess = false;
	        	isReadAccess = true;
			}
        }
	}
	boolean insideDocComment = (bits & ASTNode.InsideJavadoc) != 0;
	SearchParticipant participant = getParticipant();
	IResource resource = this.currentPossibleMatch.resource;
	if (enclosingBinding != null) {
		enclosingElement = ((JavaElement) enclosingElement).resolved(enclosingBinding);
	}
	FieldReferenceMatch match = new FieldReferenceMatch(enclosingElement, accuracy, offset, length, isReadAccess, isWriteAccess, insideDocComment, participant, resource);
	match.setLocalElement(localElement);
	return match;
}

public SearchMatch newLocalVariableReferenceMatch(
		IJavaElement enclosingElement,
		int accuracy,
		int offset,
		int length,
		ASTNode reference) {
	int bits = reference.bits;
	boolean isCompoundAssigned = (bits & ASTNode.IsCompoundAssigned) != 0;
	boolean isReadAccess = isCompoundAssigned || (bits & ASTNode.IsStrictlyAssigned) == 0;
	boolean isWriteAccess = isCompoundAssigned || (bits & ASTNode.IsStrictlyAssigned) != 0;
	if (isWriteAccess) {
		if (reference instanceof QualifiedNameReference) {
			char[][] tokens = ((QualifiedNameReference)reference).tokens;
			char[] lastToken = tokens[tokens.length-1];
			if (this.pattern instanceof OrPattern) {
				SearchPattern[] patterns = ((OrPattern) this.pattern).patterns;
				for (int i = 0, pLength = patterns.length; i < pLength; i++) {
					if (!this.patternLocator.matchesName(((VariablePattern)patterns[i]).name, lastToken)) {
			        	isWriteAccess = false;
			        	isReadAccess = true;
					}
				}
			} else if (!this.patternLocator.matchesName(((VariablePattern)this.pattern).name, lastToken)) {
	        	isWriteAccess = false;
	        	isReadAccess = true;
			}
        }
	}
	boolean insideDocComment = (bits & ASTNode.InsideJavadoc) != 0;
	SearchParticipant participant = getParticipant();
	IResource resource = this.currentPossibleMatch.resource;
	return new LocalVariableReferenceMatch(enclosingElement, accuracy, offset, length, isReadAccess, isWriteAccess, insideDocComment, participant, resource);
}

public MethodReferenceMatch newMethodReferenceMatch(
		IJavaElement enclosingElement,
		Binding enclosingBinding,
		int accuracy,
		int offset,
		int length,
		boolean isConstructor,
		boolean isSynthetic,
		ASTNode reference) {
	SearchParticipant participant = getParticipant();
	IResource resource = this.currentPossibleMatch.resource;
	boolean insideDocComment = (reference.bits & ASTNode.InsideJavadoc) != 0;
	if (enclosingBinding != null) {
		enclosingElement = ((JavaElement) enclosingElement).resolved(enclosingBinding);
	}
	boolean isOverridden = (accuracy & PatternLocator.SUPER_INVOCATION_FLAVOR) != 0;
	return new MethodReferenceMatch(enclosingElement, accuracy, offset, length, isConstructor, isSynthetic, isOverridden, insideDocComment, participant, resource);
}

public PackageReferenceMatch newPackageReferenceMatch(
		IJavaElement enclosingElement,
		int accuracy,
		int offset,
		int length,
		ASTNode reference) {
	SearchParticipant participant = getParticipant();
	IResource resource = this.currentPossibleMatch.resource;
	boolean insideDocComment = reference != null && (reference.bits & ASTNode.InsideJavadoc) != 0;
	return new PackageReferenceMatch(enclosingElement, accuracy, offset, length, insideDocComment, participant, resource);
}

public SearchMatch newTypeParameterReferenceMatch(
		IJavaElement enclosingElement,
		int accuracy,
		int offset,
		int length,
		ASTNode reference) {
	int bits = reference.bits;
	boolean insideDocComment = (bits & ASTNode.InsideJavadoc) != 0;
	SearchParticipant participant = getParticipant();
	IResource resource = this.currentPossibleMatch.resource;
	return new TypeParameterReferenceMatch(enclosingElement, accuracy, offset, length, insideDocComment, participant, resource);
}

public TypeReferenceMatch newTypeReferenceMatch(
		IJavaElement enclosingElement,
		Binding enclosingBinding,
		int accuracy,
		int offset,
		int length,
		ASTNode reference) {
	SearchParticipant participant = getParticipant();
	IResource resource = this.currentPossibleMatch.resource;
	boolean insideDocComment = reference != null && (reference.bits & ASTNode.InsideJavadoc) != 0;
	if (enclosingBinding != null)
		enclosingElement = ((JavaElement) enclosingElement).resolved(enclosingBinding);
	return new TypeReferenceMatch(enclosingElement, accuracy, offset, length, insideDocComment, participant, resource);
}

public TypeReferenceMatch newTypeReferenceMatch(
		IJavaElement enclosingElement,
		Binding enclosingBinding,
		int accuracy,
		ASTNode reference) {
	return newTypeReferenceMatch(enclosingElement, enclosingBinding, accuracy, reference.sourceStart, reference.sourceEnd-reference.sourceStart+1, reference);
}

public ModuleReferenceMatch newModuleReferenceMatch(
		IJavaElement enclosingElement,
		Binding enclosingBinding,
		int accuracy,
		int offset,
		int length,
		ASTNode reference) {
	SearchParticipant participant = getParticipant();
	IResource resource = this.currentPossibleMatch.resource;
	boolean insideDocComment = reference != null ? (reference.bits & ASTNode.InsideJavadoc) != 0 : false;
	if (enclosingBinding != null)
		enclosingElement = ((JavaElement) enclosingElement).resolved(enclosingBinding);
	return new ModuleReferenceMatch(enclosingElement, accuracy, offset, length, insideDocComment, participant, resource);
}

public ModuleReferenceMatch newModuleReferenceMatch(
		IJavaElement enclosingElement,
		Binding enclosingBinding,
		int accuracy,
		ASTNode reference) {
	return newModuleReferenceMatch(enclosingElement, enclosingBinding, accuracy, reference.sourceStart, reference.sourceEnd-reference.sourceStart+1, reference);
}
/**
 * Add the possibleMatch to the loop
 *  ->  build compilation unit declarations, their bindings and record their results.
 */
protected boolean parseAndBuildBindings(PossibleMatch possibleMatch, boolean mustResolve) throws CoreException {
	if (this.progressMonitor != null && this.progressMonitor.isCanceled())
		throw new OperationCanceledException();

//{ObjectTeams: LookupEnvironment.buildTypeBindings needs this context:
/* orig:
	try {
:giro */
	try (Config config = (   mustResolve 
						  || (this.patternLocator.mayBeGeneric && possibleMatch.nodeSet.mustResolve))
		? Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true)
		: null) 
	{
//SH}
	
		if (BasicSearchEngine.VERBOSE)
			System.out.println("Parsing " + possibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$

		this.parser.nodeSet = possibleMatch.nodeSet;
		CompilationResult unitResult = new CompilationResult(possibleMatch, 1, 1, this.options.maxProblemsPerUnit);
		CompilationUnitDeclaration parsedUnit = this.parser.dietParse(possibleMatch, unitResult);
		if (parsedUnit != null) {
			if (parsedUnit.isModuleInfo()) {
				if (mustResolve) {
					this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
				}				
			} else if (!parsedUnit.isEmpty()) {
				if (mustResolve) {
					this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
				}
				if (hasAlreadyDefinedType(parsedUnit)) return false; // skip type has it is hidden so not visible
//{ObjectTeams: Note(SH):
//   Do not use Dependencies here as not to trigger completeTypeBindings.
//   This way we avoid triggering accept which in turn processed the CU to the point that
//   we found "duplicate type" which then caused hasAlreadyDefinedType() above to bail out.				
// SH}			
				getMethodBodies(parsedUnit, possibleMatch.nodeSet);
				if (this.patternLocator.mayBeGeneric && !mustResolve && possibleMatch.nodeSet.mustResolve) {
					// special case: possible match node set force resolution although pattern does not
					// => we need to build types for this compilation unit
					this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
				}
			}

			// add the possibleMatch with its parsedUnit to matchesToProcess
			possibleMatch.parsedUnit = parsedUnit;
			int size = this.matchesToProcess.length;
			if (this.numberOfMatches == size)
				System.arraycopy(this.matchesToProcess, 0, this.matchesToProcess = new PossibleMatch[size == 0 ? 1 : size * 2], 0, this.numberOfMatches);
			this.matchesToProcess[this.numberOfMatches++] = possibleMatch;
		}
	} finally {
		this.parser.nodeSet = null;
	}
	return true;
}
/*
 * Process a compilation unit already parsed and build.
 */
protected void process(PossibleMatch possibleMatch, boolean bindingsWereCreated) throws CoreException {
	this.currentPossibleMatch = possibleMatch;
	CompilationUnitDeclaration unit = possibleMatch.parsedUnit;
//{ObjectTeams: guard with setup/release
/* orig:
	try {
  :giro */
	try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true))
	{
		// is strictDiet correct here?
		if (bindingsWereCreated && unit.state.getState() < ITranslationStates.STATE_BINDINGS_BUILT)
		    StateHelper.setStateRecursive(unit, ITranslationStates.STATE_BINDINGS_BUILT, true);
//carp}
		if (unit.isEmpty()) {
			if (this.currentPossibleMatch.openable instanceof ClassFile) {
				ClassFile classFile = (ClassFile) this.currentPossibleMatch.openable;
				IBinaryType info = null;
				try {
					info = getBinaryInfo(classFile, classFile.resource());
				}
				catch (CoreException ce) {
					// Do nothing
				}
				if (info != null) {
					boolean mayBeGeneric = this.patternLocator.mayBeGeneric;
					this.patternLocator.mayBeGeneric = false; // there's no longer generic in class files
					try {
						new ClassFileMatchLocator().locateMatches(this, classFile, info);
					}
					finally {
						this.patternLocator.mayBeGeneric = mayBeGeneric;
					}
				}
			} else if (this.currentPossibleMatch.openable instanceof ModularClassFile &&
					unit.moduleDeclaration == null) { // no source
				boolean mayBeGeneric = this.patternLocator.mayBeGeneric;
				this.patternLocator.mayBeGeneric = false; // there's no longer generic in class files
				try {
					new ModularClassFileMatchLocator().locateMatches(this, (ModularClassFile) this.currentPossibleMatch.openable);
				}
				finally {
					this.patternLocator.mayBeGeneric = mayBeGeneric;
				}
				return;
			}
			if (!unit.isModuleInfo())
				return;
		}
		if (hasAlreadyDefinedType(unit)) return; // skip type has it is hidden so not visible

		// Move getMethodBodies to #parseAndBuildings(...) method to allow possible match resolution management
		//getMethodBodies(unit);

		boolean mustResolve = (this.pattern.mustResolve || possibleMatch.nodeSet.mustResolve);
		if (bindingsWereCreated && mustResolve) {
			if (unit.types != null) {
				if (BasicSearchEngine.VERBOSE)
					System.out.println("Resolving " + this.currentPossibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$

				this.lookupEnvironment.unitBeingCompleted = unit;
				reduceParseTree(unit);
//{ObjectTeams:
/* orig:
				if (unit.scope != null) {
					// fault in fields & methods
					unit.scope.faultInTypes();
				}
				unit.resolve();
 :giro */
				Dependencies.ensureState(unit, ITranslationStates.STATE_LATE_ELEMENTS_COPIED);
// SH,carp}	
			} else if (unit.isPackageInfo()) {
				if (BasicSearchEngine.VERBOSE)
					System.out.println("Resolving " + this.currentPossibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
//{ObjectTeams:
/* orig:
				unit.resolve();
  :giro */
				Dependencies.ensureState(unit, ITranslationStates.STATE_LATE_ELEMENTS_COPIED);
// km (based on SH,carp)}
			} else if (unit.isModuleInfo()) {
				if (BasicSearchEngine.VERBOSE)
					System.out.println("Resolving " + this.currentPossibleMatch.openable.toStringWithAncestors()); //$NON-NLS-1$
				this.lookupEnvironment.unitBeingCompleted = unit;
				if (unit.scope != null && unit.moduleDeclaration != null) {
					unit.moduleDeclaration.resolveTypeDirectives(unit.scope);
				}
			}
		}
		reportMatching(unit, mustResolve);
	} catch (AbortCompilation e) {
		if (BasicSearchEngine.VERBOSE) {
			System.out.println("AbortCompilation while resolving unit " + String.valueOf(unit.getFileName())); //$NON-NLS-1$
			e.printStackTrace();
		}
		// could not resolve: report inaccurate matches
		reportMatching(unit, false); // do not resolve when cu has errors
		if (!(e instanceof AbortCompilationUnit)) {
			// problem with class path
			throw e;
		}
	} finally {
		this.lookupEnvironment.unitBeingCompleted = null;
		this.currentPossibleMatch = null;
	}
}
protected void purgeMethodStatements(TypeDeclaration type, boolean checkEachMethod) {
	checkEachMethod = checkEachMethod
		&& this.currentPossibleMatch.nodeSet.hasPossibleNodes(type.declarationSourceStart, type.declarationSourceEnd);
	AbstractMethodDeclaration[] methods = type.methods;
	if (methods != null) {
		if (checkEachMethod) {
			for (int j = 0, length = methods.length; j < length; j++) {
				AbstractMethodDeclaration method = methods[j];
				if (!this.currentPossibleMatch.nodeSet.hasPossibleNodes(method.declarationSourceStart, method.declarationSourceEnd)) {
					if (this.sourceStartOfMethodToRetain != method.declarationSourceStart || this.sourceEndOfMethodToRetain != method.declarationSourceEnd) { // approximate, but no big deal
						method.statements = null;
						method.javadoc = null;
					}
				}
			}
		} else {
			for (int j = 0, length = methods.length; j < length; j++) {
				AbstractMethodDeclaration method = methods[j];
				if (this.sourceStartOfMethodToRetain != method.declarationSourceStart || this.sourceEndOfMethodToRetain != method.declarationSourceEnd) { // approximate, but no big deal
					method.statements = null;
					method.javadoc = null;
				}
			}
		}
	}

	TypeDeclaration[] memberTypes = type.memberTypes;
	if (memberTypes != null)
		for (int i = 0, l = memberTypes.length; i < l; i++)
//{ObjectTeams: don't purge role files via their containing team 
//              (need to traverse them via their own CompilationUnitDeclaration).
		  if (!memberTypes[i].isRoleFile())
// SH}
			purgeMethodStatements(memberTypes[i], checkEachMethod);
}
/**
 * Called prior to the unit being resolved. Reduce the parse tree where possible.
 */
protected void reduceParseTree(CompilationUnitDeclaration unit) {
	// remove statements from methods that have no possible matching nodes
	TypeDeclaration[] types = unit.types;
	for (int i = 0, l = types.length; i < l; i++)
		purgeMethodStatements(types[i], true);
}
public SearchParticipant getParticipant() {
	return this.currentPossibleMatch.document.getParticipant();
}

//{ObjectTeams: accessible for ReferenceToTeamLocator:
/* orig:
protected void report(SearchMatch match) throws CoreException {
  :giro */
public void report(SearchMatch match) throws CoreException {
// SH}
	if (match == null) {
		if (BasicSearchEngine.VERBOSE) {
			System.out.println("Cannot report a null match!!!"); //$NON-NLS-1$
		}
		return;
	}
	if (filterEnum(match)){
		if (BasicSearchEngine.VERBOSE) {
			System.out.println("Filtered package with name enum"); //$NON-NLS-1$
		}
		return;
	}
	long start = -1;
	if (BasicSearchEngine.VERBOSE) {
		start = System.currentTimeMillis();
		System.out.println("Reporting match"); //$NON-NLS-1$
		System.out.println("\tResource: " + match.getResource());//$NON-NLS-1$
		System.out.println("\tPositions: [offset=" + match.getOffset() + ", length=" + match.getLength() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		try {
			if (this.parser != null && match.getOffset() > 0 && match.getLength() > 0 && !(match.getElement() instanceof BinaryMember)) {
				String selection = new String(this.parser.scanner.source, match.getOffset(), match.getLength());
				System.out.println("\tSelection: -->" + selection + "<--"); //$NON-NLS-1$ //$NON-NLS-2$
			}
		} catch (Exception e) {
			// it's just for debug purposes... ignore all exceptions in this area
		}
		try {
			JavaElement javaElement = (JavaElement)match.getElement();
			System.out.println("\tJava element: "+ javaElement.toStringWithAncestors()); //$NON-NLS-1$
			if (!javaElement.exists()) {
				System.out.println("\t\tWARNING: this element does NOT exist!"); //$NON-NLS-1$
			}
		} catch (Exception e) {
			// it's just for debug purposes... ignore all exceptions in this area
		}
		if (match instanceof ReferenceMatch) {
			try {
				ReferenceMatch refMatch = (ReferenceMatch) match;
				JavaElement local = (JavaElement) refMatch.getLocalElement();
				if (local != null) {
					System.out.println("\tLocal element: "+ local.toStringWithAncestors()); //$NON-NLS-1$
				}
				if (match instanceof TypeReferenceMatch) {
					IJavaElement[] others = ((TypeReferenceMatch) refMatch).getOtherElements();
					if (others != null) {
						int length = others.length;
						if (length > 0) {
							System.out.println("\tOther elements:"); //$NON-NLS-1$
							for (int i=0; i<length; i++) {
								JavaElement other = (JavaElement) others[i];
								System.out.println("\t\t- "+ other.toStringWithAncestors()); //$NON-NLS-1$
							}
						}
					}
				}
			} catch (Exception e) {
				// it's just for debug purposes... ignore all exceptions in this area
			}
		}
		System.out.println(match.getAccuracy() == SearchMatch.A_ACCURATE
			? "\tAccuracy: EXACT_MATCH" //$NON-NLS-1$
			: "\tAccuracy: POTENTIAL_MATCH"); //$NON-NLS-1$
		System.out.print("\tRule: "); //$NON-NLS-1$
		if (match.isExact()) {
			System.out.print("EXACT"); //$NON-NLS-1$
		} else if (match.isEquivalent()) {
			System.out.print("EQUIVALENT"); //$NON-NLS-1$
		} else if (match.isErasure()) {
			System.out.print("ERASURE"); //$NON-NLS-1$
		} else {
			System.out.print("INVALID RULE"); //$NON-NLS-1$
		}
		if (match instanceof MethodReferenceMatch) {
			MethodReferenceMatch methodReferenceMatch = (MethodReferenceMatch) match;
			if (methodReferenceMatch.isSuperInvocation()) {
				System.out.print("+SUPER INVOCATION"); //$NON-NLS-1$
			}
			if (methodReferenceMatch.isImplicit()) {
				System.out.print("+IMPLICIT"); //$NON-NLS-1$
			}
			if (methodReferenceMatch.isSynthetic()) {
				System.out.print("+SYNTHETIC"); //$NON-NLS-1$
			}
		}
		System.out.println("\n\tRaw: "+match.isRaw()); //$NON-NLS-1$
	}
	this.requestor.acceptSearchMatch(match);
	if (BasicSearchEngine.VERBOSE)
		this.resultCollectorTime += System.currentTimeMillis()-start;
}
/**
 * Finds the accurate positions of the sequence of tokens given by qualifiedName
 * in the source and reports a reference to this this qualified name
 * to the search requestor.
 */
protected void reportAccurateTypeReference(SearchMatch match, ASTNode typeRef, char[] name) throws CoreException {
	if (match.getRule() == 0) return;
	if (!encloses((IJavaElement)match.getElement())) return;

	int sourceStart = typeRef.sourceStart;
	int sourceEnd = typeRef.sourceEnd;

	// Compute source positions of the qualified reference
	if (name != null) {
		Scanner scanner = this.parser.scanner;
		scanner.setSource(this.currentPossibleMatch.getContents());
		scanner.resetTo(sourceStart, sourceEnd);

		int token = -1;
		int currentPosition;
		do {
			currentPosition = scanner.currentPosition;
			try {
				token = scanner.getNextToken();
			} catch (InvalidInputException e) {
				// ignore
			}
			if (token == TerminalTokens.TokenNameIdentifier && this.pattern.matchesName(name, scanner.getCurrentTokenSource())) {
				int length = scanner.currentPosition-currentPosition;
				match.setOffset(currentPosition);
				match.setLength(length);
				report(match);
				return;
			}
		} while (token != TerminalTokens.TokenNameEOF);
	}

	//	Report match
	match.setOffset(sourceStart);
	match.setLength(sourceEnd-sourceStart+1);
	report(match);
}

/**
 * Finds the accurate positions of the sequence of tokens given by qualifiedName
 * in the source and reports a reference to this parameterized type name
 * to the search requestor.
 * @since 3.1
 */
protected void reportAccurateParameterizedMethodReference(SearchMatch match, ASTNode statement, TypeReference[] typeArguments) throws CoreException {
	if (match.getRule() == 0) return;
	if (!encloses((IJavaElement)match.getElement())) return;

	// If there's type arguments, look for end (i.e. char '>') of last one.
	int start = match.getOffset();
	if (typeArguments != null && typeArguments.length > 0) {
		boolean isErasureMatch= (this.pattern instanceof OrPattern) ? ((OrPattern)this.pattern).isErasureMatch() : ((JavaSearchPattern)this.pattern).isErasureMatch();
		if (!isErasureMatch) {

			// Initialize scanner
			Scanner scanner = this.parser.scanner;
			char[] source = this.currentPossibleMatch.getContents();
			scanner.setSource(source);

			// Search previous opening '<'
			start = typeArguments[0].sourceStart;
			int end = statement.sourceEnd;
			scanner.resetTo(start, end);
			int lineStart = start;
			try {
				linesUp: while (true) {
					while (scanner.source[scanner.currentPosition] != '\n') {
						scanner.currentPosition--;
						if (scanner.currentPosition == 0) break linesUp;
					}
					lineStart = scanner.currentPosition+1;
					scanner.resetTo(lineStart, end);
					while (!scanner.atEnd()) {
						if (scanner.getNextToken() == TerminalTokens.TokenNameLESS) {
							start = scanner.getCurrentTokenStartPosition();
							break linesUp;
						}
					}
					end = lineStart - 2;
					scanner.currentPosition = end;
				}
			}
			catch (InvalidInputException ex) {
				// give up
			}
	 	}
	}

	// Report match
	match.setOffset(start);
	match.setLength(statement.sourceEnd-start+1);
	report(match);
}

/**
 * Finds the accurate positions of the sequence of tokens given by qualifiedName
 * in the source and reports a reference to this parameterized type name
 * to the search requestor.
 * @since 3.1
 */
protected void reportAccurateParameterizedTypeReference(SearchMatch match, TypeReference typeRef, int index, TypeReference[] typeArguments) throws CoreException {
	if (match.getRule() == 0) return;
	if (!encloses((IJavaElement)match.getElement())) return;

	// If there's type arguments, look for end (i.e. char '>') of last one.
	int end = typeRef.sourceEnd;
	if (typeArguments != null) {

		boolean shouldMatchErasure= (this.pattern instanceof OrPattern) ? ((OrPattern)this.pattern).isErasureMatch() : ((JavaSearchPattern)this.pattern).isErasureMatch();
		boolean hasSignatures = (this.pattern instanceof OrPattern) ? ((OrPattern)this.pattern).hasSignatures() : ((JavaSearchPattern)this.pattern).hasSignatures();
		if (shouldMatchErasure || !hasSignatures) {
			// if pattern is erasure only, then select the end of the reference
			if (typeRef instanceof QualifiedTypeReference && index >= 0) {
				long[] positions = ((QualifiedTypeReference) typeRef).sourcePositions;
				end = (int) positions[index];
			} else if (typeRef instanceof ArrayTypeReference) {
				end = ((ArrayTypeReference) typeRef).originalSourceEnd;
			}
		}  else {
			// Initialize scanner
			Scanner scanner = this.parser.scanner;
			char[] source = this.currentPossibleMatch.getContents();
			scanner.setSource(source);

			// Set scanner position at end of last type argument
			scanner.resetTo(end, source.length-1);
			int depth = 0;
			for (int i=typeArguments.length-1; i>=0; i--) {
				if (typeArguments[i] != null) {
					long lastTypeArgInfo = findLastTypeArgumentInfo(typeArguments[i]);
					depth = (int) (lastTypeArgInfo >>> 32)+1;
					scanner.resetTo(((int)lastTypeArgInfo)+1, scanner.eofPosition-1);
					break;
				}
			}

			// Now, scan to search next closing '>'
			while (depth-- > 0) {
				while (!scanner.atEnd()) {
					if (scanner.getNextChar() == '>') {
						end = scanner.currentPosition - 1;
						break;
					}
				}
			}
	 	}
	}

	// Report match
	match.setLength(end-match.getOffset()+1);
	report(match);
}
/**
 * Finds the accurate positions of each valid token in the source and
 * reports a reference to this token to the search requestor.
 * A token is valid if it has an accuracy which is not -1.
 */
protected void reportAccurateEnumConstructorReference(SearchMatch match, FieldDeclaration field, AllocationExpression allocation) throws CoreException {
	// Verify that field declaration is really an enum constant
	if (allocation == null || allocation.enumConstant == null) {
		report(match);
		return;
	}

	// Get scan area
	int sourceStart = match.getOffset()+match.getLength();
	if (allocation.arguments != null && allocation.arguments.length > 0) {
		sourceStart = allocation.arguments[allocation.arguments.length-1].sourceEnd+1;
	}
	int sourceEnd = field.declarationSourceEnd;
	if (allocation instanceof QualifiedAllocationExpression) {
		QualifiedAllocationExpression qualifiedAllocation = (QualifiedAllocationExpression) allocation;
		if (qualifiedAllocation.anonymousType != null) {
			sourceEnd = qualifiedAllocation.anonymousType.sourceStart - 1;
		}
	}

	// Scan to find last closing parenthesis
	Scanner scanner = this.parser.scanner;
	scanner.setSource(this.currentPossibleMatch.getContents());
	scanner.resetTo(sourceStart, sourceEnd);
	try {
		int token = scanner.getNextToken();
		while (token != TerminalTokens.TokenNameEOF) {
			if (token == TerminalTokens.TokenNameRPAREN) {
				sourceEnd = scanner.getCurrentTokenEndPosition();
			}
			token = scanner.getNextToken();
		}
	}
	catch (InvalidInputException iie) {
		// give up
	}

	// Report match
	match.setLength(sourceEnd-match.getOffset()+1);
	report(match);
}
/**
 * Finds the accurate positions of each valid token in the source and
 * reports a reference to this token to the search requestor.
 * A token is valid if it has an accuracy which is not -1.
 */
protected void reportAccurateFieldReference(SearchMatch[] matches, QualifiedNameReference qNameRef) throws CoreException {
	if (matches == null) return; // there's nothing to accurate in this case
	int matchesLength = matches.length;

	int sourceStart = qNameRef.sourceStart;
	int sourceEnd = qNameRef.sourceEnd;
	char[][] tokens = qNameRef.tokens;

	// compute source positions of the qualified reference
	Scanner scanner = this.parser.scanner;
	scanner.setSource(this.currentPossibleMatch.getContents());
	scanner.resetTo(sourceStart, sourceEnd);
	int sourceLength = sourceEnd-sourceStart+1;

	int refSourceStart = -1, refSourceEnd = -1;
	int length = tokens.length;
	int token = -1;
	int previousValid = -1;
	int i = 0;
	int index = 0;
	do {
		int currentPosition = scanner.currentPosition;
		// read token
		try {
			token = scanner.getNextToken();
		} catch (InvalidInputException e) {
			//ignore
		}
		if (token != TerminalTokens.TokenNameEOF) {
			char[] currentTokenSource = scanner.getCurrentTokenSource();
			boolean equals = false;
			while (i < length && !(equals = this.pattern.matchesName(tokens[i++], currentTokenSource))){/*empty*/}
			if (equals && (previousValid == -1 || previousValid == i - 2)) {
				previousValid = i - 1;
				if (refSourceStart == -1)
					refSourceStart = currentPosition;
				refSourceEnd = scanner.currentPosition - 1;
			} else {
				i = 0;
				refSourceStart = -1;
				previousValid = -1;
			}
			// read '.'
			try {
				token = scanner.getNextToken();
			} catch (InvalidInputException e) {
				// ignore
			}
		}
		SearchMatch match = matches[index];
		if (match != null && match.getRule() != 0) {
			if (!encloses((IJavaElement)match.getElement())) return;
			// accept reference
			if (refSourceStart != -1) {
				match.setOffset(refSourceStart);
				match.setLength(refSourceEnd-refSourceStart+1);
				report(match);
			} else {
				match.setOffset(sourceStart);
				match.setLength(sourceLength);
				report(match);
			}
			i = 0;
		}
		refSourceStart = -1;
		previousValid = -1;
		if (index < matchesLength - 1) {
			index++;
		}
	} while (token != TerminalTokens.TokenNameEOF);

}
protected void reportBinaryMemberDeclaration(IResource resource, IMember binaryMember, Binding binaryMemberBinding, IBinaryType info, int accuracy) throws CoreException {
	ClassFile classFile = (ClassFile) binaryMember.getClassFile();
	ISourceRange range = classFile.isOpen() ? binaryMember.getNameRange() : SourceMapper.UNKNOWN_RANGE;
	if (range.getOffset() == -1) {
		BinaryType type = (BinaryType) classFile.getType();
		String sourceFileName = type.sourceFileName(info);
		if (sourceFileName != null) {
			SourceMapper mapper = classFile.getSourceMapper();
			if (mapper != null) {
				char[] contents = mapper.findSource(type, sourceFileName);
				if (contents != null)
					range = mapper.mapSource(type, contents, info, binaryMember);
			}
		}
	}
	if (resource == null) resource =  this.currentPossibleMatch.resource;
	SearchMatch match = newDeclarationMatch(binaryMember, binaryMemberBinding, accuracy, range.getOffset(), range.getLength(), getParticipant(), resource);
	report(match);
}
protected void reportMatching(LambdaExpression lambdaExpression,  IJavaElement parent, int accuracy, MatchingNodeSet nodeSet, boolean typeInHierarchy) throws CoreException {
	IJavaElement enclosingElement = null;
	// Report the lambda declaration itself.
	if (accuracy > -1) {
		enclosingElement = createHandle(lambdaExpression, parent);
		if (enclosingElement != null) { // skip if unable to find method
			// compute source positions of the selector
			int nameSourceStart = lambdaExpression.sourceStart;
			if (encloses(enclosingElement)) {
				SearchMatch match = null;
				int length = lambdaExpression.arrowPosition() + 1 - nameSourceStart;
				match = this.patternLocator.newDeclarationMatch(lambdaExpression, enclosingElement, null, accuracy, length, this);
				if (match != null) {
					report(match);
				}
			}
		}
	}
	if (enclosingElement == null) {
		enclosingElement = createHandle(lambdaExpression, parent);
	}
	// Traverse the lambda declaration to report matches inside, these matches if any should see the present lambda as the parent model element.
	ASTNode[] nodes = typeInHierarchy ? nodeSet.matchingNodes(lambdaExpression.sourceStart, lambdaExpression.sourceEnd) : null;
	boolean report = (this.matchContainer & PatternLocator.METHOD_CONTAINER) != 0 && encloses(enclosingElement);
	MemberDeclarationVisitor declarationVisitor = new MemberDeclarationVisitor(enclosingElement, report ? nodes : null, nodeSet, this, typeInHierarchy);
	
	if (lambdaExpression.arguments != null) {
		int argumentsLength = lambdaExpression.arguments.length;
		for (int i = 0; i < argumentsLength; i++)
			lambdaExpression.arguments[i].traverse(declarationVisitor, (BlockScope) null);
	}

	if (lambdaExpression.body != null) {
		lambdaExpression.body.traverse(declarationVisitor, (BlockScope) null);
	}
	
	// Report all nodes and remove them
	if (nodes != null) {
		int length = nodes.length;
		for (int i = 0; i < length; i++) {
			Integer level = (Integer) nodeSet.matchingNodes.removeKey(nodes[i]);
			if (report && level != null) {
				this.patternLocator.matchReportReference(nodes[i], enclosingElement, declarationVisitor.getLocalElement(i), declarationVisitor.getOtherElements(i), lambdaExpression.binding, level.intValue(), this);
			}
		}
	}
}
/**
 * Visit the given method declaration and report the nodes that match exactly the
 * search pattern (i.e. the ones in the matching nodes set)
 * Note that the method declaration has already been checked.
 */
protected void reportMatching(AbstractMethodDeclaration method, TypeDeclaration type, IJavaElement parent, int accuracy, boolean typeInHierarchy, MatchingNodeSet nodeSet) throws CoreException {
	IJavaElement enclosingElement = null;

	// report method declaration itself
	if (accuracy > -1) {
		enclosingElement = createHandle(method, parent);
		if (enclosingElement != null) { // skip if unable to find method
			// compute source positions of the selector
			Scanner scanner = this.parser.scanner;
			int nameSourceStart = method.sourceStart;
			scanner.setSource(this.currentPossibleMatch.getContents());
			scanner.resetTo(nameSourceStart, method.sourceEnd);
			try {
				scanner.getNextToken();
			} catch (InvalidInputException e) {
				// ignore
			}
			if (encloses(enclosingElement)) {
				SearchMatch match = null;
				if (method.isDefaultConstructor()) {
					// Use type for match associated element as default constructor does not exist in source
					int offset = type.sourceStart;
					match = this.patternLocator.newDeclarationMatch(type, parent, type.binding, accuracy, type.sourceEnd-offset+1, this);
				} else {
					int length = scanner.currentPosition - nameSourceStart;
					match = this.patternLocator.newDeclarationMatch(method, enclosingElement, method.binding, accuracy, length, this);
				}
				if (match != null) {
					report(match);
				}
			}
		}
	}

	// handle nodes for the local type first
	if ((method.bits & ASTNode.HasLocalType) != 0) {
		if (enclosingElement == null) {
			enclosingElement = createHandle(method, parent);
		}
		if (enclosingElement != null) {
			// Traverse method declaration to report matches both in local types declaration
			// and in local variables declaration
			ASTNode[] nodes = typeInHierarchy ? nodeSet.matchingNodes(method.declarationSourceStart, method.declarationSourceEnd) : null;
			boolean report = (this.matchContainer & PatternLocator.METHOD_CONTAINER) != 0 && encloses(enclosingElement);
			MemberDeclarationVisitor declarationVisitor = new MemberDeclarationVisitor(enclosingElement, report ? nodes : null, nodeSet, this, typeInHierarchy);
			try {
				method.traverse(declarationVisitor, (ClassScope) null);
			} catch (WrappedCoreException e) {
				throw e.coreException;
			}
			// Report all nodes and remove them
			if (nodes != null) {
				int length = nodes.length;
				for (int i = 0; i < length; i++) {
					Integer level = (Integer) nodeSet.matchingNodes.removeKey(nodes[i]);
					if (report && level != null) {
						this.patternLocator.matchReportReference(nodes[i], enclosingElement, declarationVisitor.getLocalElement(i), declarationVisitor.getOtherElements(i), method.binding, level.intValue(), this);
					}
				}
			}
		}
	}

	// report the type parameters
	TypeParameter[] typeParameters = method.typeParameters();
	if (typeParameters != null) {
		if (enclosingElement == null) {
			enclosingElement = createHandle(method, parent);
		}
		if (enclosingElement != null) {
			reportMatching(typeParameters, enclosingElement, parent, method.binding, nodeSet);
		}
	}

	// report annotations
	if (method.annotations != null) {
		if (enclosingElement == null) {
			enclosingElement = createHandle(method, parent);
		}
		if (enclosingElement != null) {
			reportMatching(method.annotations, enclosingElement, null, method.binding, nodeSet, true, true);
		}
	}

	// references in this method
	if (typeInHierarchy) {
		ASTNode[] nodes = nodeSet.matchingNodes(method.declarationSourceStart, method.declarationSourceEnd);
		if (nodes != null) {
			if ((this.matchContainer & PatternLocator.METHOD_CONTAINER) != 0) {
				if (enclosingElement == null) {
					enclosingElement = createHandle(method, parent);
				}
				if (encloses(enclosingElement)) {
					if (this.pattern.mustResolve) {
						// Visit only if the pattern must resolve
						MemberDeclarationVisitor declarationVisitor = new MemberDeclarationVisitor(enclosingElement, nodes, nodeSet, this, typeInHierarchy);
						method.traverse(declarationVisitor, (ClassScope) null);
						int length = nodes.length;
						for (int i = 0; i < length; i++) {
							Integer level = (Integer) nodeSet.matchingNodes.removeKey(nodes[i]);
							if (level != null) { // ensure that the reference has not been already reported while visiting
				    	        this.patternLocator.matchReportReference(nodes[i], enclosingElement, declarationVisitor.getLocalElement(i), declarationVisitor.getOtherElements(i), method.binding, level.intValue(), this);
							}
						}
					} else {
						for (int i = 0, l = nodes.length; i < l; i++) {
							ASTNode node = nodes[i];
							Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
							if (level != null) { // ensure that the reference has not been already reported while visiting
								this.patternLocator.matchReportReference(node, enclosingElement, null, null, method.binding, level.intValue(), this);
							}
						}
					}
					return;
				}
			}
			// Remove all remaining nodes
			for (int i = 0, l = nodes.length; i < l; i++) {
				nodeSet.matchingNodes.removeKey(nodes[i]);
			}
		}
	}
}
/**
 * Report matching in annotations.
 * @param otherElements TODO
 */
protected void reportMatching(Annotation[] annotations, IJavaElement enclosingElement, IJavaElement[] otherElements, Binding elementBinding, MatchingNodeSet nodeSet, boolean matchedContainer, boolean enclosesElement) throws CoreException {
	if (annotations == null)
		return;
	for (int i=0, al=annotations.length; i<al; i++) {
		Annotation annotationType = annotations[i];
		IJavaElement localAnnotation = null;
		IJavaElement[] otherAnnotations = null;
		int length = otherElements == null ? 0 : otherElements.length;
		boolean handlesCreated = false;

		// Look for annotation type ref
		TypeReference typeRef = annotationType.type;
		Integer level = (Integer) nodeSet.matchingNodes.removeKey(typeRef);
		if (level != null && enclosesElement && matchedContainer) {
			localAnnotation = createHandle(annotationType, (IAnnotatable) enclosingElement);
			if (length > 0) {
				otherAnnotations = new IJavaElement[length];
				for (int o=0; o<length; o++) {
					otherAnnotations[o] = createHandle(annotationType, (IAnnotatable) otherElements[o]);
				}
			}
			handlesCreated = true;
			this.patternLocator.matchReportReference(typeRef, enclosingElement, localAnnotation, otherAnnotations, elementBinding, level.intValue(), this);
		}

		// Look for attribute ref
		MemberValuePair[] pairs = annotationType.memberValuePairs();
		for (int j = 0, pl = pairs.length; j < pl; j++) {
			MemberValuePair pair = pairs[j];
			level = (Integer) nodeSet.matchingNodes.removeKey(pair);
			if (level != null && enclosesElement) {
				ASTNode reference = (annotationType instanceof SingleMemberAnnotation) ? (ASTNode) annotationType: pair;
				if (!handlesCreated) {
					localAnnotation = createHandle(annotationType, (IAnnotatable) enclosingElement);
					if (length > 0) {
						otherAnnotations = new IJavaElement[length];
						for (int o=0; o<length; o++) {
							otherAnnotations[o] = createHandle(annotationType, (IAnnotatable) otherElements[o]);
						}
					}
					handlesCreated = true;
				}
				this.patternLocator.matchReportReference(reference, enclosingElement, localAnnotation, otherAnnotations, pair.binding, level.intValue(), this);
			}
		}

		// Look for reference inside annotation
		ASTNode[] nodes = nodeSet.matchingNodes(annotationType.sourceStart, annotationType.declarationSourceEnd);
		if (nodes != null) {
			if (!matchedContainer) {
				for (int j = 0, nl = nodes.length; j < nl; j++) {
					nodeSet.matchingNodes.removeKey(nodes[j]);
				}
			} else {
				for (int j = 0, nl = nodes.length; j < nl; j++) {
					ASTNode node = nodes[j];
					level = (Integer) nodeSet.matchingNodes.removeKey(node);
					if (enclosesElement) {
						if (!handlesCreated) {
							localAnnotation = createHandle(annotationType, (IAnnotatable) enclosingElement);
							if (length > 0) {
								otherAnnotations = new IJavaElement[length];
								for (int o=0; o<length; o++) {
									otherAnnotations[o] = createHandle(annotationType, (IAnnotatable) otherElements[o]);
								}
							}
							handlesCreated = true;
						}
						this.patternLocator.matchReportReference(node, enclosingElement, localAnnotation, otherAnnotations, elementBinding, level.intValue(), this);
					}
				}
			}
		}
	}
}
private void reportMatching(Annotation[][] annotationsList, IJavaElement enclosingElement, Binding binding,
		MatchingNodeSet nodeSet, boolean matchedClassContainer) throws CoreException {
	if (annotationsList != null) {
		for (int i = 0, length = annotationsList.length; i < length; ++i) {
			Annotation[] annotations = annotationsList[i];
			if (annotations != null) 
				reportMatching(annotations, enclosingElement, null, binding, nodeSet, matchedClassContainer, encloses(enclosingElement));	
		}
	}
}
/**
 * Visit the given resolved parse tree and report the nodes that match the search pattern.
 */
protected void reportMatching(CompilationUnitDeclaration unit, boolean mustResolve) throws CoreException {
	MatchingNodeSet nodeSet = this.currentPossibleMatch.nodeSet;
	boolean locatorMustResolve = this.patternLocator.mustResolve;
	if (nodeSet.mustResolve) this.patternLocator.mustResolve = true;
	if (BasicSearchEngine.VERBOSE) {
		System.out.println("Report matching: "); //$NON-NLS-1$
		int size = nodeSet.matchingNodes==null ? 0 : nodeSet.matchingNodes.elementSize;
		System.out.print("	- node set: accurate="+ size); //$NON-NLS-1$
		size = nodeSet.possibleMatchingNodesSet==null ? 0 : nodeSet.possibleMatchingNodesSet.elementSize;
		System.out.println(", possible="+size); //$NON-NLS-1$
		System.out.print("	- must resolve: "+mustResolve); //$NON-NLS-1$
		System.out.print(" (locator: "+this.patternLocator.mustResolve); //$NON-NLS-1$
		System.out.println(", nodeSet: "+nodeSet.mustResolve+')'); //$NON-NLS-1$
		System.out.println("	- fine grain flags="+ JavaSearchPattern.getFineGrainFlagString(this.patternLocator.fineGrain())); //$NON-NLS-1$
	}
	if (mustResolve) {
		this.unitScope= unit.scope.compilationUnitScope();
		// move the possible matching nodes that exactly match the search pattern to the matching nodes set
		Object[] nodes = nodeSet.possibleMatchingNodesSet.values;
		for (int i = 0, l = nodes.length; i < l; i++) {
			ASTNode node = (ASTNode) nodes[i];
			if (node == null) continue;
			if (node instanceof ImportReference) {
				// special case for import refs: they don't know their binding
				// import ref cannot be in the hierarchy of a type
				if (this.hierarchyResolver != null) continue;

				ImportReference importRef = (ImportReference) node;
				boolean inModule = (importRef.bits & ASTNode.inModule) != 0;
				boolean getOnDemand = (importRef.bits & ASTNode.OnDemand) != 0 || inModule;
				Binding binding = getOnDemand
					? this.unitScope.getImport(CharOperation.subarray(importRef.tokens, 0, importRef.tokens.length), true, importRef.isStatic())
					: this.unitScope.getImport(importRef.tokens, false, importRef.isStatic());
				if (inModule) {
					nodeSet.addMatch(node, this.patternLocator.resolveLevel(binding)); // report all module-info together
				} else {
					this.patternLocator.matchLevelAndReportImportRef(importRef, binding, this);
				}
			} else {
				nodeSet.addMatch(node, this.patternLocator.resolveLevel(node));
			}
		}
		nodeSet.possibleMatchingNodesSet = new SimpleSet(3);
		if (BasicSearchEngine.VERBOSE) {
			int size = nodeSet.matchingNodes==null ? 0 : nodeSet.matchingNodes.elementSize;
			System.out.print("	- node set: accurate="+size); //$NON-NLS-1$
			size = nodeSet.possibleMatchingNodesSet==null ? 0 : nodeSet.possibleMatchingNodesSet.elementSize;
			System.out.println(", possible="+size); //$NON-NLS-1$
		}
	} else {
		this.unitScope = null;
	}

	if (nodeSet.matchingNodes.elementSize == 0) return; // no matching nodes were found
	this.methodHandles = new HashSet();

	boolean matchedUnitContainer = (this.matchContainer & PatternLocator.COMPILATION_UNIT_CONTAINER) != 0;

	// report references in javadoc
	if (unit.javadoc != null) {
		ASTNode[] nodes = nodeSet.matchingNodes(unit.javadoc.sourceStart, unit.javadoc.sourceEnd);
		if (nodes != null) {
			if (!matchedUnitContainer) {
				for (int i = 0, l = nodes.length; i < l; i++)
					nodeSet.matchingNodes.removeKey(nodes[i]);
			} else {
				IJavaElement element = createPackageDeclarationHandle(unit);
				for (int i = 0, l = nodes.length; i < l; i++) {
					ASTNode node = nodes[i];
					Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
					if (encloses(element)) {
						this.patternLocator.matchReportReference(node, element, null, null, null/*no binding*/, level.intValue(), this);
					}
				}
			}
		}
	}

	if (matchedUnitContainer) {
		ImportReference pkg = unit.currentPackage;
		if (pkg != null && pkg.annotations != null) {
			IJavaElement element = createPackageDeclarationHandle(unit);
			if (element != null) {
				reportMatching(pkg.annotations, element, null, null, nodeSet, true, encloses(element));
			}
		}

		ImportReference[] imports = unit.imports;
		if (imports != null) {
			for (int i = 0, l = imports.length; i < l; i++) {
				ImportReference importRef = imports[i];
				Integer level = (Integer) nodeSet.matchingNodes.removeKey(importRef);
				if (level != null) {
					this.patternLocator.matchReportImportRef(importRef, null /*no binding*/, createImportHandle(importRef), level.intValue(), this);
				}
			}
		}
//{ObjectTeams: ROFI: special node: the package declaration interpreted as a type reference 		
		if (pkg != null  && (pkg.modifiers & ExtraCompilerModifiers.AccTeam) != 0) {
			Integer level = (Integer) nodeSet.matchingNodes.removeKey(pkg);
			if (level != null)
				this.patternLocator.matchReportImportRef(pkg, null/*no binding*/, createImportHandle(pkg), level.intValue(), this);
		}
// SH}		
	}

	TypeDeclaration[] types = unit.types;
	if (types != null) {
		for (int i = 0, l = types.length; i < l; i++) {
			if (nodeSet.matchingNodes.elementSize == 0) return; // reported all the matching nodes
			TypeDeclaration type = types[i];
			Integer level = (Integer) nodeSet.matchingNodes.removeKey(type);
			int accuracy = (level != null && matchedUnitContainer) ? level.intValue() : -1;
			this.inTypeOccurrencesCounts = new HashtableOfIntValues();
			reportMatching(type, null, accuracy, nodeSet, 1);
		}
	} else if (unit.moduleDeclaration != null) {
		ModuleDeclaration mod = unit.moduleDeclaration;
		Integer level = (Integer) nodeSet.matchingNodes.removeKey(mod);
		int accuracy = (level != null && matchedUnitContainer) ? level.intValue() : -1;
		reportMatching(mod, null, accuracy, nodeSet, 1);
	}

	// Clear handle cache
	this.methodHandles = null;
	this.bindings.removeKey(this.pattern);
	this.patternLocator.mustResolve = locatorMustResolve;
}
/**
 * Visit the given field declaration and report the nodes that match exactly the
 * search pattern (i.e. the ones in the matching nodes set)
 */
protected void reportMatching(FieldDeclaration field, FieldDeclaration[] otherFields, TypeDeclaration type, IJavaElement parent, int accuracy, boolean typeInHierarchy, MatchingNodeSet nodeSet) throws CoreException {
	IJavaElement enclosingElement = null;
	if (accuracy > -1) {
		enclosingElement = createHandle(field, type, parent);
		if (encloses(enclosingElement)) {
			int offset = field.sourceStart;
			SearchMatch match = newDeclarationMatch(enclosingElement, field.binding, accuracy, offset, field.sourceEnd-offset+1);
			if (field.initialization instanceof AllocationExpression) {
				reportAccurateEnumConstructorReference(match, field, (AllocationExpression) field.initialization);
			} else {
				report(match);
			}
		}
	}

	// handle the nodes for the local type first
	if ((field.bits & ASTNode.HasLocalType) != 0) {
		if (enclosingElement == null) {
			enclosingElement = createHandle(field, type, parent);
		}
		// Traverse field declaration(s) to report matches both in local types declaration
		// and in local variables declaration
		int fieldEnd = field.endPart2Position == 0 ? field.declarationSourceEnd : field.endPart2Position;
		ASTNode[] nodes = typeInHierarchy ? nodeSet.matchingNodes(field.sourceStart, fieldEnd) : null;
		boolean report = (this.matchContainer & PatternLocator.FIELD_CONTAINER) != 0 && encloses(enclosingElement);
		MemberDeclarationVisitor declarationVisitor = new MemberDeclarationVisitor(enclosingElement, report ? nodes : null, nodeSet, this, typeInHierarchy);
		try {
			field.traverse(declarationVisitor, (MethodScope) null);
		} catch (WrappedCoreException e) {
			throw e.coreException;
		}
		// Report all nodes and remove them
		if (nodes != null) {
			int length = nodes.length;
			for (int i = 0; i < length; i++) {
				ASTNode node = nodes[i];
				Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
				if (report && level != null) {
					if (node instanceof TypeDeclaration) {
						// use field declaration to report match (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=88174)
						AllocationExpression allocation = ((TypeDeclaration)node).allocation;
						if (allocation != null && allocation.enumConstant != null) {
							node = field;
						}
					}
	    	        this.patternLocator.matchReportReference(node, enclosingElement, declarationVisitor.getLocalElement(i), declarationVisitor.getOtherElements(i), field.binding, level.intValue(), this);
				}
			}
		}
	}

	// report annotations
	IJavaElement[] otherElements = null;
	if (field.annotations != null) {
		if (enclosingElement == null) {
			enclosingElement = createHandle(field, type, parent);
		}
		if (otherFields != null) {
			otherElements = createHandles(otherFields, type, parent);
		}
		reportMatching(field.annotations, enclosingElement, otherElements, field.binding, nodeSet, true, true);
	}

	if (typeInHierarchy) {
		// Look at field declaration
		if (field.endPart1Position != 0) { // not necessary if field is an initializer
			ASTNode[] nodes = nodeSet.matchingNodes(field.declarationSourceStart, field.endPart1Position);
			if (nodes != null) {
				if ((this.matchContainer & PatternLocator.FIELD_CONTAINER) == 0) {
					for (int i = 0, l = nodes.length; i < l; i++)
						nodeSet.matchingNodes.removeKey(nodes[i]);
				} else {
					if (enclosingElement == null)
						enclosingElement = createHandle(field, type, parent);
					if (encloses(enclosingElement)) {
						for (int i = 0, l = nodes.length; i < l; i++) {
							ASTNode node = nodes[i];
							Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
							if (otherFields != null && otherElements == null) {
								otherElements = createHandles(otherFields, type, parent);
							}
							this.patternLocator.matchReportReference(node, enclosingElement, null, otherElements, field.binding, level.intValue(), this);
						}
					}
				}
			}
		}

		// Look in initializer
		int fieldEnd = field.endPart2Position == 0 ? field.declarationSourceEnd : field.endPart2Position;
		ASTNode[] nodes = nodeSet.matchingNodes(field.sourceStart, fieldEnd);
		if (nodes != null) {
			if ((this.matchContainer & PatternLocator.FIELD_CONTAINER) == 0) {
				for (int i = 0, l = nodes.length; i < l; i++) {
					nodeSet.matchingNodes.removeKey(nodes[i]);
				}
			} else {
				if (enclosingElement == null) {
					enclosingElement = createHandle(field, type, parent);
				}
				if (encloses(enclosingElement)) {
					MemberDeclarationVisitor declarationVisitor = new MemberDeclarationVisitor(enclosingElement, nodes, nodeSet, this, typeInHierarchy);
					field.traverse(declarationVisitor, (MethodScope) null);
					int length = nodes.length;
					for (int i = 0; i < length; i++) {
						ASTNode node = nodes[i];
						Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
						if (level != null) { // ensure that the reference has not been already reported while visiting
							if (node instanceof TypeDeclaration) {
								// use field declaration to report match (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=88174)
								AllocationExpression allocation = ((TypeDeclaration)node).allocation;
								if (allocation != null && allocation.enumConstant != null) {
									node = field;
								}
							}
			    	        this.patternLocator.matchReportReference(node, enclosingElement, declarationVisitor.getLocalElement(i), declarationVisitor.getOtherElements(i), field.binding, level.intValue(), this);
						}
					}
					return;
				}
			}
		}
	}
}
/**
 * Visit the given module declaration and report the nodes that match exactly the
 * search pattern (i.e. the ones in the matching nodes set)
 */
protected void reportMatching(ModuleDeclaration module, IJavaElement parent, int accuracy, MatchingNodeSet nodeSet, int occurrenceCount) throws CoreException {
	if (this.currentPossibleMatch.autoModuleName != null && accuracy > -1) {
		reportMatchingAutoModule(module, parent, accuracy);
		return;
	}
	IModuleDescription moduleDesc =  null;
	Openable openable = this.currentPossibleMatch.openable;
	if (openable instanceof ITypeRoot) {
		ITypeRoot typeRoot = (ITypeRoot) openable;
		try {
			moduleDesc =  typeRoot.getModule();
		} catch (JavaModelException e) {
			// do nothing
		}
	}
	if (moduleDesc == null) // could theoretically happen if openable is ICompilationUnit, but logically having a module should prevent this from happening
		return;
	reportMatching(module.annotations, moduleDesc, null, module.binding, nodeSet, true, true);
	if (accuracy > -1) { // report module declaration
		SearchMatch match = this.patternLocator.newDeclarationMatch(module, moduleDesc, module.binding, accuracy, module.moduleName.length, this);
		report(match);
	}
	reportMatching(module.requires, module,  nodeSet, moduleDesc);
	reportMatching(module.exports, nodeSet, moduleDesc);
	reportMatching(module.opens, nodeSet, moduleDesc);
	reportMatching(module.services, module, nodeSet, moduleDesc);
	reportMatching(module.uses, module, nodeSet, moduleDesc);
}
private void reportMatchingAutoModule(ModuleDeclaration module, IJavaElement parent, int accuracy) throws CoreException {
	IModuleDescription autoModule = new AbstractModule.AutoModule( this.currentPossibleMatch.openable, this.currentPossibleMatch.autoModuleName, true);
	SearchMatch match = this.patternLocator.newDeclarationMatch(module, autoModule, module.binding, accuracy, module.moduleName.length, this);
	report(match);
}

private void reportMatching(RequiresStatement[] reqs, ModuleDeclaration module, MatchingNodeSet nodeSet, IModuleDescription moduleDesc) {
	if (reqs == null || reqs.length == 0)
		return;
	try {
		for (RequiresStatement req : reqs) {
			Integer level = (Integer) nodeSet.matchingNodes.removeKey(req.module);
			if (level != null) {
				this.patternLocator.matchReportReference(req.module, moduleDesc, req.resolvedBinding, level.intValue(), this);
			}
		}
	} catch (CoreException e) {
		// do nothing
	}
}

private void reportMatching(PackageVisibilityStatement[] psvs, MatchingNodeSet nodeSet, IModuleDescription moduleDesc)
		throws JavaModelException, CoreException {
	if (psvs != null && psvs.length > 0) {
		for (PackageVisibilityStatement psv : psvs) {
			ImportReference importRef = psv.pkgRef;
			Integer level = (Integer) nodeSet.matchingNodes.removeKey(importRef);
			if (level != null) {
				Binding binding = this.unitScope.getImport(CharOperation.subarray(importRef.tokens, 0, importRef.tokens.length), true, false);
				this.patternLocator.matchReportImportRef(importRef, binding, moduleDesc, level.intValue(), this);
			}
			ModuleReference[] tgts = psv.targets;
			if (tgts == null || tgts.length == 0) continue;
			for (ModuleReference tgt : tgts) {
				level = (Integer) nodeSet.matchingNodes.removeKey(tgt);
				if (level != null) {
					this.patternLocator.matchReportReference(tgt, moduleDesc, tgt.resolve(this.unitScope), level.intValue(), this);
				}
			}
		}
	}
}
private void reportMatching(ProvidesStatement[] provides, ModuleDeclaration module, MatchingNodeSet nodeSet, IModuleDescription moduleDesc) throws JavaModelException, CoreException {
	if (provides != null && provides.length > 0) {
		for (ProvidesStatement service : provides) {
			TypeReference intf = service.serviceInterface;
			if (intf != null) {
				Integer level = (Integer) nodeSet.matchingNodes.removeKey(intf);
				if (level != null)
					this.patternLocator.matchReportReference(intf, moduleDesc, null, null, module.binding, level.intValue(), this);
			}
			TypeReference[] impls = service.implementations;
			for (TypeReference impl : impls) {
				if (impl != null) {
					Integer level = (Integer) nodeSet.matchingNodes.removeKey(impl);
					if (level != null)
						this.patternLocator.matchReportReference(impl, moduleDesc, null, null, module.binding, level.intValue(), this);
				}
			}
		}
	}
}
private void reportMatching(UsesStatement[] uses, ModuleDeclaration module, MatchingNodeSet nodeSet, IModuleDescription moduleDesc) {
	if (uses != null && uses.length > 0) {
		try {
			for (UsesStatement service : uses) {
				TypeReference intf = service.serviceInterface;
				if (intf != null) {
					Integer level = (Integer) nodeSet.matchingNodes.removeKey(intf);
					if (level != null) {
						this.patternLocator.matchReportReference(intf, moduleDesc, null, null, module.binding, level.intValue(), this);
					}
				}
			}
		} catch (CoreException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

/**
 * Visit the given type declaration and report the nodes that match exactly the
 * search pattern (i.e. the ones in the matching nodes set)
 */
protected void reportMatching(TypeDeclaration type, IJavaElement parent, int accuracy, MatchingNodeSet nodeSet, int occurrenceCount) throws CoreException {
	// create type handle
	IJavaElement enclosingElement = parent;

//{ObjectTeams: strip role class name:
	// Note(SH): this version works independent of the order of superinterfaces and even
	//           in case, role splitting had not taken place:
	String typeName = new String(type.name);
	boolean isRole = false;
	if (   type.isRole() 
		&& !type.isInterface() 
		&& typeName.startsWith(IOTConstants.OT_DELIM))
	{
		typeName = typeName.substring(IOTConstants.OT_DELIM_LEN);
		isRole = true;
	}
/*orig:
	if (enclosingElement == null) {
		enclosingElement = createTypeHandle(new String(type.name));
	} else if (enclosingElement instanceof IType) {
		enclosingElement = ((IType) parent).getType(new String(type.name));
 :giro */	
	if (enclosingElement == null) {
		enclosingElement = createTypeHandle(typeName);
	} else if (enclosingElement instanceof IType) {
		if (isRole) 
	        enclosingElement = TypeHelper.findRoleType((IType)parent, typeName); // FIXME(SH): avoid heavy weight operation here!
		else 
		    enclosingElement = ((IType) parent).getType(new String(type.name));
// jsv,gbr,SH}
	} else if (enclosingElement instanceof IMember) {
	    IMember member = (IMember) parent;
		if (member.isBinary())  {
			IOpenable openable = enclosingElement.getOpenable();
			IJavaElement anonType = null;
			if (openable instanceof ClassFile) {
				BinaryType binaryType = (BinaryType)((ClassFile) openable).getType();
				String fileName = binaryType.getPath().toOSString();
				if ((type.bits & ASTNode.IsAnonymousType) != 0) {
					if (fileName != null) {
						if (fileName.endsWith("jar") || fileName.endsWith(SuffixConstants.SUFFIX_STRING_class)) { //$NON-NLS-1$
							IOrdinaryClassFile classFile= binaryType.getPackageFragment().getOrdinaryClassFile(binaryType.getTypeQualifiedName() + 
									"$" + Integer.toString(occurrenceCount) + SuffixConstants.SUFFIX_STRING_class);//$NON-NLS-1$
							anonType =  classFile.getType();
						}
					} else {
						// TODO: JAVA 9 - JIMAGE to be included later - currently assuming that only .class files will be dealt here.
					}
				}
			}
			enclosingElement = anonType != null ? anonType : ((IOrdinaryClassFile)this.currentPossibleMatch.openable).getType() ;
		} else {
			enclosingElement = member.getType(new String(type.name), occurrenceCount);
		}
	}
	if (enclosingElement == null) return;
	boolean enclosesElement = encloses(enclosingElement);

	// report the type declaration
	if (accuracy > -1 && enclosesElement) {
		int offset = type.sourceStart;
		SearchMatch match = this.patternLocator.newDeclarationMatch(type, enclosingElement, type.binding, accuracy, type.sourceEnd-offset+1, this);
		report(match);
	}

	boolean matchedClassContainer = (this.matchContainer & PatternLocator.CLASS_CONTAINER) != 0;

	// report the type parameters
	if (type.typeParameters != null) {
		reportMatching(type.typeParameters, enclosingElement, parent, type.binding, nodeSet);
	}

	// report annotations
	if (type.annotations != null) {
		reportMatching(type.annotations, enclosingElement, null, type.binding, nodeSet, matchedClassContainer, enclosesElement);
	}

	// report references in javadoc
	if (type.javadoc != null) {
		ASTNode[] nodes = nodeSet.matchingNodes(type.declarationSourceStart, type.sourceStart);
		if (nodes != null) {
			if (!matchedClassContainer) {
				for (int i = 0, l = nodes.length; i < l; i++)
					nodeSet.matchingNodes.removeKey(nodes[i]);
			} else {
				for (int i = 0, l = nodes.length; i < l; i++) {
					ASTNode node = nodes[i];
					Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
					if (enclosesElement) {
						this.patternLocator.matchReportReference(node, enclosingElement, null, null, type.binding, level.intValue(), this);
					}
				}
			}
		}
	}

	// super types
	if ((type.bits & ASTNode.IsAnonymousType) != 0) {
		TypeReference superType = type.allocation.type;
		if (superType != null) {
			Integer level = (Integer) nodeSet.matchingNodes.removeKey(superType);
			if (level != null && matchedClassContainer)
				this.patternLocator.matchReportReference(superType, enclosingElement, null, null, type.binding, level.intValue(), this);
		}
	} else {
		TypeReference superClass = type.superclass;
		if (superClass != null) {
			reportMatchingSuper(superClass, enclosingElement, type.binding, nodeSet, matchedClassContainer);
			for (int i = 0, length = superClass.annotations == null ? 0 : superClass.annotations.length; i < length; i++) {
				Annotation[] annotations = superClass.annotations[i];
				if (annotations == null) continue;
				reportMatching(annotations, enclosingElement, null, type.binding, nodeSet, matchedClassContainer, enclosesElement);	
			}
		}
		TypeReference[] superInterfaces = type.superInterfaces;
		if (superInterfaces != null) {
			for (int i = 0, l = superInterfaces.length; i < l; i++) {
				reportMatchingSuper(superInterfaces[i], enclosingElement, type.binding, nodeSet, matchedClassContainer);
				TypeReference typeReference  = type.superInterfaces[i];
				Annotation[][] annotations = typeReference != null ? typeReference.annotations : null;
				if (annotations != null) {
					for (int j = 0, length = annotations.length; j < length; j++) {
						if (annotations[j] == null) continue;
						reportMatching(annotations[j], enclosingElement, null, type.binding, nodeSet, matchedClassContainer, enclosesElement);	
					}
				}			
			}
		}
	}

//ObjectTeams: report base class reference, precedences:
	TypeReference baseClass = type.baseclass;
	if (baseClass != null) {
		Integer level = (Integer) nodeSet.matchingNodes.removeKey(baseClass);
		if (level != null && matchedClassContainer)
			this.patternLocator.matchReportPlayedByReference(baseClass, enclosingElement, type.binding, level.intValue(), this);

	}
	if (type.precedences != null) {
		for(int i=0; i<type.precedences.length; i++) {
			PrecedenceDeclaration precDecl= type.precedences[i];
			if (precDecl == null) continue;
			for (NameReference nameRef : precDecl.bindingNames) {
				if (nameRef == null) continue;
				Integer level = (Integer) nodeSet.matchingNodes.removeKey(nameRef);
				if (level != null && matchedClassContainer)
					this.patternLocator.matchReportReference(nameRef, enclosingElement, type.binding, level.intValue(), this);					
			}
		}
	}
//jsv,gbr}	
	
	// filter out element not in hierarchy scope
	boolean typeInHierarchy = type.binding == null || typeInHierarchy(type.binding);
	matchedClassContainer = matchedClassContainer && typeInHierarchy;

	// Visit fields
	FieldDeclaration[] fields = type.fields;
	if (fields != null) {
		if (nodeSet.matchingNodes.elementSize == 0) return;	// end as all matching nodes were reported
		FieldDeclaration[] otherFields = null;
		int first = -1;
		int length = fields.length;
		for (int i = 0; i < length; i++) {
			FieldDeclaration field = fields[i];
//{ObjectTeams: filter all generated fields
			if (field.copyInheritanceSrc != null || 
			        Flags.isSynthetic(field.modifiers))
			{
			    continue;
			}
//jsv,gbr}				
			boolean last = field.endPart2Position == 0 || field.declarationEnd == field.endPart2Position;
			// Store first index of multiple field declaration
			if (!last) {
				if (first == -1) {
					first = i;
				}
			}
			if (first >= 0) {
				// Store all multiple fields but first one for other elements
				if (i > first) {
					if (otherFields == null) {
						otherFields = new FieldDeclaration[length-i];
					}
					otherFields[i-1-first] = field;
				}
				// On last field, report match with all other elements
				if (last) {
					for (int j=first; j<=i; j++) {
						Integer level = (Integer) nodeSet.matchingNodes.removeKey(fields[j]);
						int value = (level != null && matchedClassContainer) ? level.intValue() : -1;
						reportMatching(fields[j], otherFields, type, enclosingElement, value, typeInHierarchy, nodeSet);
					}
					first = -1;
					otherFields = null;
				}
			} else {
				// Single field, report normally
				Integer level = (Integer) nodeSet.matchingNodes.removeKey(field);
				int value = (level != null && matchedClassContainer) ? level.intValue() : -1;
				reportMatching(field, null, type, enclosingElement, value, typeInHierarchy, nodeSet);
			}
		}
	}

	// Visit methods
	AbstractMethodDeclaration[] methods = type.methods;
	if (methods != null) {
		if (nodeSet.matchingNodes.elementSize == 0) return;	// end as all matching nodes were reported
		for (int i = 0, l = methods.length; i < l; i++) {
			AbstractMethodDeclaration method = methods[i];
//{ObjectTeams: filter generated methods:			
		  if (isRelevantMethod(method)) {
// orig:
			Integer level = (Integer) nodeSet.matchingNodes.removeKey(method);
// :giro				
			// if method was not found in nodeSet also check its interface part
			// (yet reporting the class part method):
			if (level == null && method.interfacePartMethod != null) 
				level = (Integer) nodeSet.matchingNodes.removeKey(method.interfacePartMethod);
// orig:
			int value = (level != null && matchedClassContainer) ? level.intValue() : -1;
			reportMatching(method, type, enclosingElement, value, typeInHierarchy, nodeSet);
// :giro
		  }
// SH}
		}
	}

//{ObjectTeams: report matching nodes in method mapping declarations
	AbstractMethodMappingDeclaration[] mappings = type.callinCallouts;
	if (mappings != null)
	{
		if (nodeSet.matchingNodes.elementSize == 0)
	    {
		    return; // reported all the matching nodes
	    }
		for (int idx = 0; idx < mappings.length; idx++)
        {
		    AbstractMethodMappingDeclaration mapping = mappings[idx];
		    Integer level = (Integer) nodeSet.matchingNodes.removeKey(mapping);
		    int value = (level != null && matchedClassContainer) ? level.intValue() : -1;
		    reportMatching(mappings[idx], enclosingElement, mapping.binding, value, typeInHierarchy, nodeSet);		    
        }
	}
//gbr}
	
	// Visit types
	TypeDeclaration[] memberTypes = type.memberTypes;
	if (memberTypes != null) {
		for (int i = 0, l = memberTypes.length; i < l; i++) {
			if (nodeSet.matchingNodes.elementSize == 0) return;	// end as all matching nodes were reported
			TypeDeclaration memberType = memberTypes[i];
//Note (SH): should now work, callin markers are now created without role splitting.
//{ObjectTeams: filter all generated member classes (explicit interface implementations will be translated
//			into RoleIface (extends ExplicitInterface), so we need to report those.
			if (!memberType.isInterface() && (memberType.isPurelyCopied || Flags.isSynthetic(memberType.modifiers)))
			{
			    continue;
			}
			if (memberType.isRoleFile())
				continue; // role files are traversed from their CUD, not as member of the team
//jsv,gbr}			
			Integer level = (Integer) nodeSet.matchingNodes.removeKey(memberType);
			int value = (level != null && matchedClassContainer) ? level.intValue() : -1;
			reportMatching(memberType, enclosingElement, value, nodeSet, 1);
		}
	}
}

//{ObjectTeams: report method mapping declaration or references in this method mapping declaration             
/**
 * Visit the given method mapping declaration and report the nodes in its range that match exactly the
 * search pattern (i.e. the ones in the matching nodes set)
 */
protected void reportMatching(
        AbstractMethodMappingDeclaration methodMapping,
        IJavaElement parent,
        Binding binding,
        int accuracy,
        boolean typeInHierarchy,
        MatchingNodeSet nodeSet) throws CoreException 
{
    IJavaElement enclosingElement = createHandle(methodMapping, parent);

    if (accuracy > -1)
    {
        System.out.println("FIXME: MatchLocator.reportMatching(): accuracy: " + accuracy);
        //TODO(gbr,jsv) handle declaration of method mapping if it is searched 
	}
    
//    boolean matchedMethodContainer = (this.matchContainer & PatternLocator.METHOD_CONTAINER) != 0;
//    //TODO(gbr) The role method spec in a callout binding is always a declaration.
//    //The following code always returns a reference match for a method spec, even if
//    //declarations of a method are searched. The reason is that a "MethodSpec" doesn' t contain
//    //the information, if it is a reference (message send) or a (method) declaration.
//    if (methodMapping instanceof CalloutMappingDeclaration)
//    {    
//        MethodSpec roleMethodSpec = methodMapping.roleMethodSpec;
//        Integer level = (Integer) nodeSet.matchingNodes.removeKey(roleMethodSpec);
//	    int value = (level != null && matchedMethodContainer) ? level.intValue() : -1;
//        
//        if (value > -1) {
//    		enclosingElement = createHandle(roleMethodSpec, parent);
//    		if (enclosingElement != null) { // skip if unable to find method
//    			// compute source positions of the selector 
//    			Scanner scanner = parser.scanner;
//    			int nameSourceStart = roleMethodSpec.sourceStart;
//    			scanner.setSource(this.currentPossibleMatch.getContents());
//    			scanner.resetTo(nameSourceStart, roleMethodSpec.sourceEnd);
//    			try {
//    				scanner.getNextToken();
//    			} catch (InvalidInputException e) {
//    				// ignore
//    			}
//    			if (encloses(enclosingElement)) {
//    				int length = scanner.currentPosition - nameSourceStart;
//    				SearchMatch match = newDeclarationMatch(enclosingElement, accuracy, nameSourceStart, length);
//    				report(match);
//    			}
//    		}        
//        }
//    }
    
	if (typeInHierarchy) {
		int start = methodMapping.declarationSourceStart;
		int end = methodMapping.declarationSourceEnd;
		// when restricted to class instance creation search roleMethodSpec for occurrences of lifting:
		if ((this.patternLocator.fineGrain() & IJavaSearchConstants.CLASS_INSTANCE_CREATION_TYPE_REFERENCE) != 0) {
			if (methodMapping.isCallin()) {
				// callin: search role args:
				if (methodMapping.hasSignature) {
					Argument[] roleArgs = methodMapping.roleMethodSpec.arguments;
					if (roleArgs != null) {
						for (int i=0; i<roleArgs.length; i++) {
							TypeReference argType = roleArgs[i].type;
							if (   argType.resolvedType != null
								&& argType.resolvedType.isRole() 
								&& methodMapping.roleMethodSpec.argNeedsTranslation(i)) 
							{
								Integer level = (Integer) nodeSet.matchingNodes.removeKey(argType);
								if (level != null)
									this.patternLocator.matchReportReference(argType, enclosingElement, binding, level.intValue()|SearchMatch.A_CHECKED, this);
							}
						}
					}
				}
			} else {
				// callout: search role return:
				if (methodMapping.hasSignature) {
					TypeReference returnType = methodMapping.roleMethodSpec.returnType;
					if (   returnType.resolvedType != null
					    && returnType.resolvedType.isRole()
						&& methodMapping.roleMethodSpec.returnNeedsTranslation)
					{
						Integer level = (Integer) nodeSet.matchingNodes.removeKey(returnType);
						if (level != null)
							this.patternLocator.matchReportReference(returnType, enclosingElement, binding, level.intValue()|SearchMatch.A_CHECKED, this);						
					}
				}
			}
			// continue looking into parameter mappings
			start = methodMapping.bodyStart;
			start = methodMapping.bodyEnd;
		}
		ASTNode[] nodes = nodeSet.matchingNodes(start, end);
		if (nodes != null)
		{
			if ((this.matchContainer & PatternLocator.METHOD_MAPPING_CONTAINER) != 0)
			{
				if (encloses(enclosingElement))
				{
					for (int idx = 0, l = nodes.length; idx < l; idx++)
					{
						ASTNode node = nodes[idx];
						Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
						this.patternLocator.matchReportReference(node, enclosingElement, binding, level.intValue(), this);
					}
					return;
				}
			}
			for (int i = 0, l = nodes.length; i < l; i++)
				nodeSet.matchingNodes.removeKey(nodes[i]);
		}
	}
}

//{ObjectTeams: filter all generated methods
private boolean isRelevantMethod(AbstractMethodDeclaration method) {
	if (   method.isCopied 
		|| Flags.isSynthetic(method.modifiers))
	{
	    return false;
	}
	if (method.isGenerated) 
		return method.isReusingSourceMethod; // callout or guard: generated but declaration is present in src
	return true;
}
//jsv,gbr moved by SH}				

//{ObjectTeams: new method
/**
 * Creates an IJavaElement from the given method mapping declaration and type. 
 */
protected IJavaElement createHandle(
        AbstractMethodMappingDeclaration mappingDecl,
        IJavaElement parent) throws JavaModelException
{   
    if (!(parent instanceof IType))
    {
        return parent;
    }
    
    IType parentType = (IType) parent;
//    if (!parentType.exists()) // if necessary, create elementInfo FIXME (carp)
//        return null;
    
    RoleType roleType = (RoleType)OTModelManager.getOTElement(parentType);
    
    if (roleType != null)
    {
	    if (mappingDecl instanceof CalloutMappingDeclaration)
	    {
	        CalloutMappingDeclaration calloutMappingDecl = (CalloutMappingDeclaration)mappingDecl;
	        int calloutDeclSrcStart = calloutMappingDecl.sourceStart();
	        IMethodMapping[] calloutMethodMappings = roleType.getMethodMappings(IRoleType.CALLOUTS);
	        for (int idx = 0; idx < calloutMethodMappings.length; idx++)
	        {
	            IMethodMapping calloutMethodMapping = calloutMethodMappings[idx];
	            ISourceRange calloutMappingSrcRange = calloutMethodMapping.getNameRange();
	            int calloutMappingSrcStart = calloutMappingSrcRange.getOffset();
	            if (calloutMappingSrcStart == calloutDeclSrcStart)
	            {
	                return calloutMethodMapping;
	            }
	        }
	    }
	    else if (mappingDecl instanceof CallinMappingDeclaration)
	    {
	        CallinMappingDeclaration callinMappingDecl = (CallinMappingDeclaration)mappingDecl;
	        int callinDeclSrcStart = callinMappingDecl.sourceStart();
	        IMethodMapping[] callinMethodMappings = roleType.getMethodMappings(IRoleType.CALLINS);
	        for (int idx = 0; idx < callinMethodMappings.length; idx++)
	        {
	            IMethodMapping callinMethodMapping = callinMethodMappings[idx];
	            ISourceRange callinMappingSrcRange = callinMethodMapping.getNameRange();
	            int callinMappingSrcStart = callinMappingSrcRange.getOffset();
	            if (callinMappingSrcStart == callinDeclSrcStart)
	            {
	                return callinMethodMapping;
	            }
	        }
	    }
    }
    return null;
}
// who?}

/**
 * Report matches in type parameters.
 */
protected void reportMatching(TypeParameter[] typeParameters, IJavaElement enclosingElement, IJavaElement parent, Binding binding, MatchingNodeSet nodeSet) throws CoreException {
	if (typeParameters == null) return;
	for (int i=0, l=typeParameters.length; i<l; i++) {
		TypeParameter typeParameter = typeParameters[i];
		if (typeParameter != null) {
			Integer level = (Integer) nodeSet.matchingNodes.removeKey(typeParameter);
			if (level != null) {
				if (level.intValue() > -1 && encloses(enclosingElement)) {
					int offset = typeParameter.sourceStart;
					SearchMatch match = this.patternLocator.newDeclarationMatch(typeParameter, enclosingElement, binding, level.intValue(), typeParameter.sourceEnd-offset+1, this);
					report(match);
				}
			}
			boolean matchedClassContainer = (this.matchContainer & PatternLocator.ALL_CONTAINER) != 0;
			if (typeParameter.annotations != null) {
				reportMatching(typeParameter.annotations, enclosingElement, null, typeParameter.binding, nodeSet, matchedClassContainer, encloses(enclosingElement));	
			}
			if (typeParameter.type != null) {
				reportMatching(typeParameter.type.annotations, enclosingElement, typeParameter.binding, nodeSet, matchedClassContainer);
				level = (Integer) nodeSet.matchingNodes.removeKey(typeParameter.type);
				if (level != null) {
					IJavaElement localElement = createHandle(typeParameter, enclosingElement);
					this.patternLocator.matchReportReference(typeParameter.type, enclosingElement, localElement, null, binding, level.intValue(), this);
				}
				if (typeParameter.type instanceof ParameterizedSingleTypeReference) {
                    ParameterizedSingleTypeReference paramSTR = (ParameterizedSingleTypeReference) typeParameter.type;
                    if (paramSTR.typeArguments != null) {
                    	int length = paramSTR.typeArguments.length;
                    	for (int k=0; k<length; k++) {
							TypeReference typeArgument = paramSTR.typeArguments[k];
							reportMatching(typeArgument.annotations, enclosingElement, typeArgument.resolvedType, nodeSet, matchedClassContainer);
							level = (Integer) nodeSet.matchingNodes.removeKey(typeArgument);
							if (level != null) {
								IJavaElement localElement = createHandle(typeParameter, enclosingElement);
								this.patternLocator.matchReportReference(typeArgument, enclosingElement, localElement, null, binding, level.intValue(), this);
							}
							if (typeArgument instanceof Wildcard) {
	                            TypeReference wildcardBound = ((Wildcard) typeArgument).bound;
	                            if (wildcardBound != null) {
		            				reportMatching(wildcardBound.annotations, enclosingElement, wildcardBound.resolvedType, nodeSet, matchedClassContainer);
									level = (Integer) nodeSet.matchingNodes.removeKey(wildcardBound);
									if (level != null) {
										IJavaElement localElement = createHandle(typeParameter, enclosingElement);
										this.patternLocator.matchReportReference(wildcardBound, enclosingElement, localElement, null, binding, level.intValue(), this);
									}
	                            }
                            }
                    	}
                    }
				}
			}
			if (typeParameter.bounds != null) {
				for (int j=0, b=typeParameter.bounds.length; j<b; j++) {
					TypeReference typeParameterBound = typeParameter.bounds[j];
					if (typeParameterBound.annotations != null) {
						reportMatching(typeParameterBound.annotations, enclosingElement, binding,nodeSet, matchedClassContainer);
					}
					level = (Integer) nodeSet.matchingNodes.removeKey(typeParameterBound);
					if (level != null) {
						IJavaElement localElement = createHandle(typeParameter, enclosingElement);
						this.patternLocator.matchReportReference(typeParameterBound, enclosingElement, localElement, null, binding, level.intValue(), this);
					}
					if (typeParameterBound instanceof ParameterizedSingleTypeReference) {
	                    ParameterizedSingleTypeReference paramSTR = (ParameterizedSingleTypeReference) typeParameterBound;
	                    if (paramSTR.typeArguments != null) {
	                    	int length = paramSTR.typeArguments.length;
	                    	for (int k=0; k<length; k++) {
								TypeReference typeArgument = paramSTR.typeArguments[k];
								if (typeArgument.annotations != null) {
									reportMatching(typeArgument.annotations, enclosingElement, binding,nodeSet, matchedClassContainer);
								}
								level = (Integer) nodeSet.matchingNodes.removeKey(typeArgument);
								if (level != null) {
									IJavaElement localElement = createHandle(typeParameter, enclosingElement);
									this.patternLocator.matchReportReference(typeArgument, enclosingElement, localElement, null, binding, level.intValue(), this);
								}
								if (typeArgument instanceof Wildcard) {
		                            TypeReference wildcardBound = ((Wildcard) typeArgument).bound;
		                            if (wildcardBound != null) {
		            					if (wildcardBound.annotations != null) {
		            						reportMatching(wildcardBound.annotations, enclosingElement, binding,nodeSet, matchedClassContainer);
		            					}
										level = (Integer) nodeSet.matchingNodes.removeKey(wildcardBound);
										if (level != null) {
											IJavaElement localElement = createHandle(typeParameter, enclosingElement);
											this.patternLocator.matchReportReference(wildcardBound, enclosingElement, localElement, null, binding, level.intValue(), this);
										}
		                            }
	                            }
	                    	}
	                    }
                    }
				}
			}
		}
	}
}
protected void reportMatchingSuper(TypeReference superReference, IJavaElement enclosingElement, Binding elementBinding, MatchingNodeSet nodeSet, boolean matchedClassContainer) throws CoreException {
	ASTNode[] nodes = null;
	if (superReference instanceof ParameterizedSingleTypeReference || superReference instanceof ParameterizedQualifiedTypeReference) {
		long lastTypeArgumentInfo = findLastTypeArgumentInfo(superReference);
		nodes = nodeSet.matchingNodes(superReference.sourceStart, (int)lastTypeArgumentInfo);
	}
	if (nodes != null) {
		if ((this.matchContainer & PatternLocator.CLASS_CONTAINER) == 0) {
			for (int i = 0, l = nodes.length; i < l; i++)
				nodeSet.matchingNodes.removeKey(nodes[i]);
		} else {
			if (encloses(enclosingElement))
				for (int i = 0, l = nodes.length; i < l; i++) {
					ASTNode node = nodes[i];
					Integer level = (Integer) nodeSet.matchingNodes.removeKey(node);
					this.patternLocator.matchReportReference(node, enclosingElement, null, null, elementBinding, level.intValue(), this);
				}
		}
	} else if (encloses(enclosingElement)) {
		Integer level = (Integer) nodeSet.matchingNodes.removeKey(superReference);
		if (level != null && matchedClassContainer)
			this.patternLocator.matchReportReference(superReference, enclosingElement, null, null, elementBinding, level.intValue(), this);
	}
}
protected boolean typeInHierarchy(ReferenceBinding binding) {
	if (this.hierarchyResolver == null) return true; // not a hierarchy scope
	if (this.hierarchyResolver.subOrSuperOfFocus(binding)) return true;

	if (this.allSuperTypeNames != null) {
		char[][] compoundName = binding.compoundName;
		for (int i = 0, length = this.allSuperTypeNames.length; i < length; i++)
			if (CharOperation.equals(compoundName, this.allSuperTypeNames[i]))
				return true;
	}
	return false;
}
//{ObjectTeams: function needed by Config:
@Override
public Parser getPlainParser() {
	return new Parser(this.parser.internalGetProblemReporter(), true);
}
// SH}
}
