/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Stephan Herrmann - Contribution for
 *								bug 363858 - [dom] early throwing of AbortCompilation causes NPE in CompilationUnitResolver
 *								Bug 466279 - [hovering] IAE on hover when annotation-based null analysis is enabled
 *******************************************************************************/
package org.eclipse.jdt.core.dom;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
import org.eclipse.jdt.internal.compiler.IProblemFactory;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
import org.eclipse.jdt.internal.compiler.env.INameEnvironment;
import org.eclipse.jdt.internal.compiler.env.ISourceType;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt;
import org.eclipse.jdt.internal.compiler.util.Messages;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.jdt.internal.core.BinaryMember;
import org.eclipse.jdt.internal.core.CancelableNameEnvironment;
import org.eclipse.jdt.internal.core.CancelableProblemFactory;
import org.eclipse.jdt.internal.core.INameEnvironmentWithProgress;
import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.internal.core.LocalVariable;
import org.eclipse.jdt.internal.core.NameLookup;
import org.eclipse.jdt.internal.core.SourceRefElement;
import org.eclipse.jdt.internal.core.SourceTypeElementInfo;
import org.eclipse.jdt.internal.core.util.BindingKeyResolver;
import org.eclipse.jdt.internal.core.util.CommentRecorderParser;
import org.eclipse.jdt.internal.core.util.DOMFinder;

@SuppressWarnings({ "rawtypes", "unchecked" })
class CompilationUnitResolver extends Compiler {
	public static final int RESOLVE_BINDING = 0x1;
	public static final int PARTIAL = 0x2;
	public static final int STATEMENT_RECOVERY = 0x4;
	public static final int IGNORE_METHOD_BODIES = 0x8;
	public static final int BINDING_RECOVERY = 0x10;
	public static final int INCLUDE_RUNNING_VM_BOOTCLASSPATH = 0x20;

	/* A list of int */
	static class IntArrayList {
		public int[] list = new int[5];
		public int length = 0;
		public void add(int i) {
			if (this.list.length == this.length) {
				System.arraycopy(this.list, 0, this.list = new int[this.length*2], 0, this.length);
			}
				this.list[this.length++] = i;
			}
		}

	/*
	 * The sources that were requested.
	 * Map from file name (char[]) to org.eclipse.jdt.internal.compiler.env.ICompilationUnit.
	 */
	HashtableOfObject requestedSources;

	/*
	 * The binding keys that were requested.
	 * Map from file name (char[]) to BindingKey (or ArrayList if multiple keys in the same file).
	 */
	HashtableOfObject requestedKeys;

	DefaultBindingResolver.BindingTables bindingTables;

	boolean hasCompilationAborted;
	CategorizedProblem abortProblem;

	private IProgressMonitor monitor;
	
	/**
	 * Set to <code>true</code> if the receiver was initialized using a java project name environment
	 */
	boolean fromJavaProject;

	/**
	 * Answer a new CompilationUnitVisitor using the given name environment and compiler options.
	 * The environment and options will be in effect for the lifetime of the compiler.
	 * When the compiler is run, compilation results are sent to the given requestor.
	 *
	 *  @param environment org.eclipse.jdt.internal.compiler.api.env.INameEnvironment
	 *      Environment used by the compiler in order to resolve type and package
	 *      names. The name environment implements the actual connection of the compiler
	 *      to the outside world (for example, in batch mode the name environment is performing
	 *      pure file accesses, reuse previous build state or connection to repositories).
	 *      Note: the name environment is responsible for implementing the actual classpath
	 *            rules.
	 *
	 *  @param policy org.eclipse.jdt.internal.compiler.api.problem.IErrorHandlingPolicy
	 *      Configurable part for problem handling, allowing the compiler client to
	 *      specify the rules for handling problems (stop on first error or accumulate
	 *      them all) and at the same time perform some actions such as opening a dialog
	 *      in UI when compiling interactively.
	 *      @see org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies
	 *
	 *	@param compilerOptions The compiler options to use for the resolution.
	 *
	 *  @param requestor org.eclipse.jdt.internal.compiler.api.ICompilerRequestor
	 *      Component which will receive and persist all compilation results and is intended
	 *      to consume them as they are produced. Typically, in a batch compiler, it is
	 *      responsible for writing out the actual .class files to the file system.
	 *      @see org.eclipse.jdt.internal.compiler.CompilationResult
	 *
	 *  @param problemFactory org.eclipse.jdt.internal.compiler.api.problem.IProblemFactory
	 *      Factory used inside the compiler to create problem descriptors. It allows the
	 *      compiler client to supply its own representation of compilation problems in
	 *      order to avoid object conversions. Note that the factory is not supposed
	 *      to accumulate the created problems, the compiler will gather them all and hand
	 *      them back as part of the compilation unit result.
	 */
	public CompilationUnitResolver(
		INameEnvironment environment,
		IErrorHandlingPolicy policy,
		CompilerOptions compilerOptions,
		ICompilerRequestor requestor,
		IProblemFactory problemFactory,
		IProgressMonitor monitor,
		boolean fromJavaProject) {

		super(environment, policy, compilerOptions, requestor, problemFactory);
		this.hasCompilationAborted = false;
		this.monitor =monitor;
		this.fromJavaProject = fromJavaProject;
	}

	/*
	 * Add additional source types
	 */
	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
		// Need to reparse the entire source of the compilation unit so as to get source positions
		// (case of processing a source that was not known by beginToCompile (e.g. when asking to createBinding))
		SourceTypeElementInfo sourceType = (SourceTypeElementInfo) sourceTypes[0];
		accept((org.eclipse.jdt.internal.compiler.env.ICompilationUnit) sourceType.getHandle().getCompilationUnit(), accessRestriction);
	}
	
	public synchronized void accept(org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit, AccessRestriction accessRestriction) {
		super.accept(sourceUnit, accessRestriction);
	}

	/**
	 * Add the initial set of compilation units into the loop
	 *  ->  build compilation unit declarations, their bindings and record their results.
	 */
	protected void beginToCompile(org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits, String[] bindingKeys) {
		int sourceLength = sourceUnits.length;
		int keyLength = bindingKeys.length;
		int maxUnits = sourceLength + keyLength;
		this.totalUnits = 0;
		this.unitsToProcess = new CompilationUnitDeclaration[maxUnits];
		int index = 0;

		// walks the source units
		this.requestedSources = new HashtableOfObject();
		for (int i = 0; i < sourceLength; i++) {
			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = sourceUnits[i];
			CompilationUnitDeclaration parsedUnit;
			CompilationResult unitResult =
				new CompilationResult(sourceUnit, index++, maxUnits, this.options.maxProblemsPerUnit);
			try {
				if (this.options.verbose) {
					this.out.println(
						Messages.bind(Messages.compilation_request,
						new String[] {
							String.valueOf(index++ + 1),
							String.valueOf(maxUnits),
							new String(sourceUnit.getFileName())
						}));
				}
				// diet parsing for large collection of units
				if (this.totalUnits < this.parseThreshold) {
					parsedUnit = this.parser.parse(sourceUnit, unitResult);
				} else {
					parsedUnit = this.parser.dietParse(sourceUnit, unitResult);
				}
				// initial type binding creation
				this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
				addCompilationUnit(sourceUnit, parsedUnit);
				this.requestedSources.put(unitResult.getFileName(), sourceUnit);
				worked(1);
			} finally {
				sourceUnits[i] = null; // no longer hold onto the unit
			}
		}

		// walk the binding keys
		this.requestedKeys = new HashtableOfObject();
		for (int i = 0; i < keyLength; i++) {
			BindingKeyResolver resolver = new BindingKeyResolver(bindingKeys[i], this, this.lookupEnvironment);
			resolver.parse(true/*pause after fully qualified name*/);
			// If it doesn't have a type name, then it is either an array type, package or base type, which will definitely not have a compilation unit.
			// Skipping it will speed up performance because the call will open jars. (theodora)
			CompilationUnitDeclaration parsedUnit = resolver.hasTypeName() ? resolver.getCompilationUnitDeclaration() : null;
			if (parsedUnit != null) {
				char[] fileName = parsedUnit.compilationResult.getFileName();
				Object existing = this.requestedKeys.get(fileName);
				if (existing == null)
					this.requestedKeys.put(fileName, resolver);
				else if (existing instanceof ArrayList)
					((ArrayList) existing).add(resolver);
				else {
					ArrayList list = new ArrayList();
					list.add(existing);
					list.add(resolver);
					this.requestedKeys.put(fileName, list);
				}

			} else {
				char[] key = resolver.hasTypeName()
					? resolver.getKey().toCharArray() // binary binding
					: CharOperation.concatWith(resolver.compoundName(), '.'); // package binding or base type binding
				this.requestedKeys.put(key, resolver);
			}
			worked(1);
		}

		// binding resolution
		this.lookupEnvironment.completeTypeBindings();
	}

	IBinding createBinding(String key) {
		if (this.bindingTables == null)
			throw new RuntimeException("Cannot be called outside ASTParser#createASTs(...)"); //$NON-NLS-1$
		BindingKeyResolver keyResolver = new BindingKeyResolver(key, this, this.lookupEnvironment);
		Binding compilerBinding = keyResolver.getCompilerBinding();
		if (compilerBinding == null) return null;
		DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, null/*no owner*/, this.bindingTables, false, this.fromJavaProject);
		return resolver.getBinding(compilerBinding);
	}

	public static CompilationUnit convert(
			CompilationUnitDeclaration compilationUnitDeclaration,
			char[] source,
			int apiLevel,
			Map options,
			boolean needToResolveBindings,
			WorkingCopyOwner owner,
			DefaultBindingResolver.BindingTables bindingTables,
			int flags,
			IProgressMonitor monitor,
			boolean fromJavaProject) {
		BindingResolver resolver = null;
		AST ast = AST.newAST(apiLevel);
		ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
		CompilationUnit compilationUnit = null;
		ASTConverter converter = new ASTConverter(options, needToResolveBindings, monitor);
		if (needToResolveBindings) {
			resolver = new DefaultBindingResolver(compilationUnitDeclaration.scope, owner, bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0, fromJavaProject);
			ast.setFlag(flags | AST.RESOLVED_BINDINGS);
		} else {
			resolver = new BindingResolver();
			ast.setFlag(flags);
		}
		ast.setBindingResolver(resolver);
		converter.setAST(ast);
		compilationUnit = converter.convert(compilationUnitDeclaration, source);
		compilationUnit.setLineEndTable(compilationUnitDeclaration.compilationResult.getLineSeparatorPositions());
		ast.setDefaultNodeFlag(0);
		ast.setOriginalModificationCount(ast.modificationCount());
		return compilationUnit;
	}

	protected static CompilerOptions getCompilerOptions(Map options, boolean statementsRecovery) {
		CompilerOptions compilerOptions = new CompilerOptions(options);
		compilerOptions.performMethodsFullRecovery = statementsRecovery;
		compilerOptions.performStatementsRecovery = statementsRecovery;
		compilerOptions.parseLiteralExpressionsAsConstants = false;
		compilerOptions.storeAnnotations = true /*store annotations in the bindings*/;
		compilerOptions.ignoreSourceFolderWarningOption = true;
		return compilerOptions;
	}
	/*
	 *  Low-level API performing the actual compilation
	 */
	protected static IErrorHandlingPolicy getHandlingPolicy() {

		// passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)
		return new IErrorHandlingPolicy() {
			public boolean stopOnFirstError() {
				return false;
			}
			public boolean proceedOnErrors() {
				return false; // stop if there are some errors
			}
			public boolean ignoreAllErrors() {
				return false;
			}
		};
	}

	/*
	 * Answer the component to which will be handed back compilation results from the compiler
	 */
	protected static ICompilerRequestor getRequestor() {
		return new ICompilerRequestor() {
			public void acceptResult(CompilationResult compilationResult) {
				// do nothing
			}
		};
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.internal.compiler.Compiler#initializeParser()
	 */
	public void initializeParser() {
		this.parser = new CommentRecorderParser(this.problemReporter, false);
	}
	public void process(CompilationUnitDeclaration unit, int i) {
		// don't resolve a second time the same unit (this would create the same binding twice)
		char[] fileName = unit.compilationResult.getFileName();
		if (this.requestedKeys.get(fileName) == null && this.requestedSources.get(fileName) == null)
			super.process(unit, i);
	}
	/*
	 * Compiler crash recovery in case of unexpected runtime exceptions
	 */
	protected void handleInternalException(
			Throwable internalException,
			CompilationUnitDeclaration unit,
			CompilationResult result) {
		super.handleInternalException(internalException, unit, result);
		if (unit != null) {
			removeUnresolvedBindings(unit);
		}
	}

	/*
	 * Compiler recovery in case of internal AbortCompilation event
	 */
	protected void handleInternalException(
			AbortCompilation abortException,
			CompilationUnitDeclaration unit) {
		super.handleInternalException(abortException, unit);
		if (unit != null) {
			removeUnresolvedBindings(unit);
		}
		this.hasCompilationAborted = true;
		this.abortProblem = abortException.problem;
	}

	public static void parse(ICompilationUnit[] compilationUnits, ASTRequestor astRequestor, int apiLevel, Map options, int flags, IProgressMonitor monitor) {
		CompilerOptions compilerOptions = new CompilerOptions(options);
		compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
		Parser parser = new CommentRecorderParser(
			new ProblemReporter(
					DefaultErrorHandlingPolicies.proceedWithAllProblems(),
					compilerOptions,
					new DefaultProblemFactory()),
			false);
		int unitLength = compilationUnits.length;
		SubMonitor subMonitor = SubMonitor.convert(monitor);
		for (int i = 0; i < unitLength; i++) {
			subMonitor.setWorkRemaining(unitLength - i);
			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) compilationUnits[i];
			CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0,
					compilerOptions.maxProblemsPerUnit);
			CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);

			if (compilationUnitDeclaration.ignoreMethodBodies) {
				compilationUnitDeclaration.ignoreFurtherInvestigation = true;
				// if initial diet parse did not work, no need to dig into method bodies.
				continue;
			}

			//fill the methods bodies in order for the code to be generated
			//real parse of the method....
			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
			if (types != null) {
				for (int j = 0, typeLength = types.length; j < typeLength; j++) {
					types[j].parseMethods(parser, compilationUnitDeclaration);
				}
			}

			// convert AST
			CompilationUnit node = convert(compilationUnitDeclaration, parser.scanner.getSource(), apiLevel, options,
					false/* don't resolve binding */, null/* no owner needed */, null/* no binding table needed */,
					flags /* flags */, subMonitor.split(1), true);
			node.setTypeRoot(compilationUnits[i]);

			// accept AST
			astRequestor.acceptAST(compilationUnits[i], node);
		}
	}
	public static void parse(
			String[] sourceUnits,
			String[] encodings,
			FileASTRequestor astRequestor,
			int apiLevel,
			Map options,
			int flags,
			IProgressMonitor monitor) {
		CompilerOptions compilerOptions = new CompilerOptions(options);
		compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
		Parser parser = new CommentRecorderParser(
			new ProblemReporter(
					DefaultErrorHandlingPolicies.proceedWithAllProblems(),
					compilerOptions,
					new DefaultProblemFactory()),
			false);
		int unitLength = sourceUnits.length;
		SubMonitor subMonitor = SubMonitor.convert(monitor, unitLength);
		for (int i = 0; i < unitLength; i++) {
			SubMonitor iterationMonitor = subMonitor.split(1);
			char[] contents = null;
			String encoding = encodings != null ? encodings[i] : null;
			try {
				contents = Util.getFileCharContent(new File(sourceUnits[i]), encoding);
			} catch(IOException e) {
				// go to the next unit
				continue;
			}
			if (contents == null) {
				// go to the next unit
				continue;
			}
			org.eclipse.jdt.internal.compiler.batch.CompilationUnit compilationUnit = new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(contents, sourceUnits[i], encoding);
			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationUnit;
			CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
			CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);

			if (compilationUnitDeclaration.ignoreMethodBodies) {
				compilationUnitDeclaration.ignoreFurtherInvestigation = true;
				// if initial diet parse did not work, no need to dig into method bodies.
				continue;
			}

			//fill the methods bodies in order for the code to be generated
			//real parse of the method....
			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
			if (types != null) {
				for (int j = 0, typeLength = types.length; j < typeLength; j++) {
					types[j].parseMethods(parser, compilationUnitDeclaration);
				}
			}

			// convert AST
			CompilationUnit node = convert(compilationUnitDeclaration, parser.scanner.getSource(), apiLevel, options,
					false/* don't resolve binding */, null/* no owner needed */, null/* no binding table needed */,
					flags /* flags */, iterationMonitor, true);
			node.setTypeRoot(null);

			// accept AST
			astRequestor.acceptAST(sourceUnits[i], node);
		}
	}
	public static CompilationUnitDeclaration parse(
			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
			NodeSearcher nodeSearcher,
			Map settings,
			int flags) {
		if (sourceUnit == null) {
			throw new IllegalStateException();
		}
		CompilerOptions compilerOptions = new CompilerOptions(settings);
		boolean statementsRecovery = (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0;
		compilerOptions.performMethodsFullRecovery = statementsRecovery;
		compilerOptions.performStatementsRecovery = statementsRecovery;
		compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
		Parser parser = new CommentRecorderParser(
			new ProblemReporter(
					DefaultErrorHandlingPolicies.proceedWithAllProblems(),
					compilerOptions,
					new DefaultProblemFactory()),
			false);
		CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, compilerOptions.maxProblemsPerUnit);
		CompilationUnitDeclaration compilationUnitDeclaration = parser.dietParse(sourceUnit, compilationResult);

		if (compilationUnitDeclaration.ignoreMethodBodies) {
			compilationUnitDeclaration.ignoreFurtherInvestigation = true;
			// if initial diet parse did not work, no need to dig into method bodies.
			return compilationUnitDeclaration;
		}

		if (nodeSearcher != null) {
			char[] source = parser.scanner.getSource();
			int searchPosition = nodeSearcher.position;
			if (searchPosition < 0 || searchPosition > source.length) {
				// the position is out of range. There is no need to search for a node.
				return compilationUnitDeclaration;
			}

			compilationUnitDeclaration.traverse(nodeSearcher, compilationUnitDeclaration.scope);

			org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;
			if (node == null) {
				return compilationUnitDeclaration;
			}

			org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;

			if (node instanceof AbstractMethodDeclaration) {
				((AbstractMethodDeclaration)node).parseStatements(parser, compilationUnitDeclaration);
			} else if (enclosingTypeDeclaration != null) {
				if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
					((org.eclipse.jdt.internal.compiler.ast.Initializer) node).parseStatements(parser, enclosingTypeDeclaration, compilationUnitDeclaration);
				} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
					((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)node).parseMethods(parser, compilationUnitDeclaration);
				}
			}
		} else {
				//fill the methods bodies in order for the code to be generated
				//real parse of the method....			
				org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
				if (types != null) {
					for (int j = 0, typeLength = types.length; j < typeLength; j++) {
						types[j].parseMethods(parser, compilationUnitDeclaration);
					}
				}
		}
		return compilationUnitDeclaration;
	}

	public static void resolve(
		ICompilationUnit[] compilationUnits,
		String[] bindingKeys,
		ASTRequestor requestor,
		int apiLevel,
		Map options,
		IJavaProject javaProject,
		WorkingCopyOwner owner,
		int flags,
		IProgressMonitor monitor) {

		CancelableNameEnvironment environment = null;
		CancelableProblemFactory problemFactory = null;
		try {
			int amountOfWork = (compilationUnits.length + bindingKeys.length) * 2; // 1 for beginToCompile, 1 for resolve
			SubMonitor subMonitor = SubMonitor.convert(monitor, amountOfWork);
			environment = new CancelableNameEnvironment(((JavaProject) javaProject), owner, subMonitor);
			problemFactory = new CancelableProblemFactory(subMonitor);
			CompilerOptions compilerOptions = getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
			compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
			CompilationUnitResolver resolver =
				new CompilationUnitResolver(
					environment,
					getHandlingPolicy(),
					compilerOptions,
					getRequestor(),
					problemFactory,
					subMonitor,
					javaProject != null);
			resolver.resolve(compilationUnits, bindingKeys, requestor, apiLevel, options, owner, flags);
			if (NameLookup.VERBOSE) {
				System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + environment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
				System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + environment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
			}
		} catch (JavaModelException e) {
			// project doesn't exist -> simple parse without resolving
			parse(compilationUnits, requestor, apiLevel, options, flags, monitor);
		} finally {
			if (environment != null) {
				environment.setMonitor(null); // don't hold a reference to this external object
			}
			if (problemFactory != null) {
				problemFactory.monitor = null; // don't hold a reference to this external object
			}
		}
	}
	public static void resolve(
			String[] sourceUnits,
			String[] encodings,
			String[] bindingKeys,
			FileASTRequestor requestor,
			int apiLevel,
			Map options,
			List classpaths,
			int flags,
			IProgressMonitor monitor) {

			INameEnvironmentWithProgress environment = null;
			CancelableProblemFactory problemFactory = null;
			try {
				int amountOfWork = (sourceUnits.length + bindingKeys.length) * 2; // 1 for beginToCompile, 1 for resolve
				SubMonitor subMonitor = SubMonitor.convert(monitor, amountOfWork);
				Classpath[] allEntries = new Classpath[classpaths.size()];
				classpaths.toArray(allEntries);
				environment = new NameEnvironmentWithProgress(allEntries, null, subMonitor);
				problemFactory = new CancelableProblemFactory(subMonitor);
				CompilerOptions compilerOptions = getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
				compilerOptions.ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
				CompilationUnitResolver resolver =
					new CompilationUnitResolver(
						environment,
						getHandlingPolicy(),
						compilerOptions,
						getRequestor(),
						problemFactory,
						subMonitor,
						false);
				resolver.resolve(sourceUnits, encodings, bindingKeys, requestor, apiLevel, options, flags);
				if (NameLookup.VERBOSE && (environment instanceof CancelableNameEnvironment)) {
					CancelableNameEnvironment cancelableNameEnvironment = (CancelableNameEnvironment) environment;
					System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + cancelableNameEnvironment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
					System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + cancelableNameEnvironment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
				}
			} finally {
				if (environment != null) {
					environment.setMonitor(null); // don't hold a reference to this external object
				}
				if (problemFactory != null) {
					problemFactory.monitor = null; // don't hold a reference to this external object
				}
			}
		}
	public static CompilationUnitDeclaration resolve(
			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
			IJavaProject javaProject,
			List classpaths,
			NodeSearcher nodeSearcher,
			Map options,
			WorkingCopyOwner owner,
			int flags,
			IProgressMonitor monitor) throws JavaModelException {

		CompilationUnitDeclaration unit = null;
		INameEnvironmentWithProgress environment = null;
		CancelableProblemFactory problemFactory = null;
		CompilationUnitResolver resolver = null;
		try {
			if (javaProject == null) {
				Classpath[] allEntries = new Classpath[classpaths.size()];
				classpaths.toArray(allEntries);
				environment = new NameEnvironmentWithProgress(allEntries, null, monitor);
			} else {
				environment = new CancelableNameEnvironment((JavaProject) javaProject, owner, monitor);
			}
			problemFactory = new CancelableProblemFactory(monitor);
			CompilerOptions compilerOptions = getCompilerOptions(options, (flags & ICompilationUnit.ENABLE_STATEMENTS_RECOVERY) != 0);
			boolean ignoreMethodBodies = (flags & ICompilationUnit.IGNORE_METHOD_BODIES) != 0;
			compilerOptions.ignoreMethodBodies = ignoreMethodBodies;
			resolver =
				new CompilationUnitResolver(
					environment,
					getHandlingPolicy(),
					compilerOptions,
					getRequestor(),
					problemFactory,
					monitor,
					javaProject != null);
			boolean analyzeAndGenerateCode = !ignoreMethodBodies;
			unit =
				resolver.resolve(
					null, // no existing compilation unit declaration
					sourceUnit,
					nodeSearcher,
					true, // method verification
					analyzeAndGenerateCode, // analyze code
					analyzeAndGenerateCode); // generate code
			if (resolver.hasCompilationAborted) {
				// the bindings could not be resolved due to missing types in name environment
				// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=86541
				CompilationUnitDeclaration unitDeclaration = parse(sourceUnit, nodeSearcher, options, flags);
				if (unit != null) {
					final int problemCount = unit.compilationResult.problemCount;
					if (problemCount != 0) {
						unitDeclaration.compilationResult.problems = new CategorizedProblem[problemCount];
						System.arraycopy(unit.compilationResult.problems, 0, unitDeclaration.compilationResult.problems, 0, problemCount);
						unitDeclaration.compilationResult.problemCount = problemCount;
					}
				} else if (resolver.abortProblem != null) {
					unitDeclaration.compilationResult.problemCount = 1;
					unitDeclaration.compilationResult.problems = new CategorizedProblem[] { resolver.abortProblem };
				}
				return unitDeclaration;
			}
			if (NameLookup.VERBOSE && environment instanceof CancelableNameEnvironment) {
				CancelableNameEnvironment cancelableNameEnvironment = (CancelableNameEnvironment) environment;
				System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInSourcePackage: " + cancelableNameEnvironment.nameLookup.timeSpentInSeekTypesInSourcePackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
				System.out.println(Thread.currentThread() + " TIME SPENT in NameLoopkup#seekTypesInBinaryPackage: " + cancelableNameEnvironment.nameLookup.timeSpentInSeekTypesInBinaryPackage + "ms");  //$NON-NLS-1$ //$NON-NLS-2$
			}
			return unit;
		} finally {
			if (environment != null) {
				// don't hold a reference to this external object
				environment.setMonitor(null);
			}
			if (problemFactory != null) {
				problemFactory.monitor = null; // don't hold a reference to this external object
			}
		}
	}
	public static IBinding[] resolve(
		final IJavaElement[] elements,
		int apiLevel,
		Map compilerOptions,
		IJavaProject javaProject,
		WorkingCopyOwner owner,
		int flags,
		IProgressMonitor monitor) {

		final int length = elements.length;
		final HashMap sourceElementPositions = new HashMap(); // a map from ICompilationUnit to int[] (positions in elements)
		int cuNumber = 0;
		final HashtableOfObjectToInt binaryElementPositions = new HashtableOfObjectToInt(); // a map from String (binding key) to int (position in elements)
		for (int i = 0; i < length; i++) {
			IJavaElement element = elements[i];
			if (!(element instanceof SourceRefElement))
				throw new IllegalStateException(element + " is not part of a compilation unit or class file"); //$NON-NLS-1$
			Object cu = element.getAncestor(IJavaElement.COMPILATION_UNIT);
			if (cu != null) {
				// source member
				IntArrayList intList = (IntArrayList) sourceElementPositions.get(cu);
				if (intList == null) {
					sourceElementPositions.put(cu, intList = new IntArrayList());
					cuNumber++;
				}
				intList.add(i);
			} else {
				// binary member or method argument
				try {
					String key;
					if (element instanceof BinaryMember)
						key = ((BinaryMember) element).getKey(true/*open to get resolved info*/);
					else if (element instanceof LocalVariable)
						key = ((LocalVariable) element).getKey(true/*open to get resolved info*/);
					else if (element instanceof org.eclipse.jdt.internal.core.TypeParameter)
						key = ((org.eclipse.jdt.internal.core.TypeParameter) element).getKey(true/*open to get resolved info*/);
					else
						throw new IllegalArgumentException(element + " has an unexpected type"); //$NON-NLS-1$
					binaryElementPositions.put(key, i);
				} catch (JavaModelException e) {
					throw new IllegalArgumentException(element + " does not exist", e); //$NON-NLS-1$
				}
			}
		}
		ICompilationUnit[] cus = new ICompilationUnit[cuNumber];
		sourceElementPositions.keySet().toArray(cus);

		int bindingKeyNumber = binaryElementPositions.size();
		String[] bindingKeys = new String[bindingKeyNumber];
		binaryElementPositions.keysToArray(bindingKeys);

		class Requestor extends ASTRequestor {
			IBinding[] bindings = new IBinding[length];
			public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
				// TODO (jerome) optimize to visit the AST only once
				IntArrayList intList = (IntArrayList) sourceElementPositions.get(source);
				for (int i = 0; i < intList.length; i++) {
					final int index = intList.list[i];
					SourceRefElement element = (SourceRefElement) elements[index];
					DOMFinder finder = new DOMFinder(ast, element, true/*resolve binding*/);
					try {
						finder.search();
					} catch (JavaModelException e) {
						throw new IllegalArgumentException(element + " does not exist", e); //$NON-NLS-1$
					}
					this.bindings[index] = finder.foundBinding;
				}
			}
			public void acceptBinding(String bindingKey, IBinding binding) {
				int index = binaryElementPositions.get(bindingKey);
				this.bindings[index] = binding;
			}
		}
		Requestor requestor = new Requestor();
		resolve(cus, bindingKeys, requestor, apiLevel, compilerOptions, javaProject, owner, flags, monitor);
		return requestor.bindings;
	}
	/*
	 * When unit result is about to be accepted, removed back pointers
	 * to unresolved bindings
	 */
	public void removeUnresolvedBindings(CompilationUnitDeclaration compilationUnitDeclaration) {
		final org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] types = compilationUnitDeclaration.types;
		if (types != null) {
			for (int i = 0, max = types.length; i < max; i++) {
				removeUnresolvedBindings(types[i]);
			}
		}
	}
	private void removeUnresolvedBindings(org.eclipse.jdt.internal.compiler.ast.TypeDeclaration type) {
		final org.eclipse.jdt.internal.compiler.ast.TypeDeclaration[] memberTypes = type.memberTypes;
		if (memberTypes != null) {
			for (int i = 0, max = memberTypes.length; i < max; i++){
				removeUnresolvedBindings(memberTypes[i]);
			}
		}
		if (type.binding != null && (type.binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
			type.binding = null;
		}

		final org.eclipse.jdt.internal.compiler.ast.FieldDeclaration[] fields = type.fields;
		if (fields != null) {
			for (int i = 0, max = fields.length; i < max; i++){
				if (fields[i].binding != null && (fields[i].binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
					fields[i].binding = null;
				}
			}
		}

		final AbstractMethodDeclaration[] methods = type.methods;
		if (methods != null) {
			for (int i = 0, max = methods.length; i < max; i++){
				if (methods[i].binding !=  null && (methods[i].binding.modifiers & ExtraCompilerModifiers.AccUnresolved) != 0) {
					methods[i].binding = null;
				}
			}
		}
	}

	private void resolve(
			ICompilationUnit[] compilationUnits,
			String[] bindingKeys,
			ASTRequestor astRequestor,
			int apiLevel,
			Map compilerOptions,
			WorkingCopyOwner owner,
			int flags) {

		// temporarily connect ourselves to the ASTResolver - must disconnect when done
		astRequestor.compilationUnitResolver = this;
		this.bindingTables = new DefaultBindingResolver.BindingTables();
		CompilationUnitDeclaration unit = null;
		try {
			int length = compilationUnits.length;
			org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[length];
			System.arraycopy(compilationUnits, 0, sourceUnits, 0, length);
			beginToCompile(sourceUnits, bindingKeys);
			// process all units (some more could be injected in the loop by the lookup environment)
			for (int i = 0; i < this.totalUnits; i++) {
				if (resolvedRequestedSourcesAndKeys(i)) {
					// no need to keep resolving if no more ASTs and no more binding keys are needed
					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=114935
					// cleanup remaining units
					for (; i < this.totalUnits; i++) {
						this.unitsToProcess[i].cleanUp();
						this.unitsToProcess[i] = null;
					}
					break;
				}
				unit = this.unitsToProcess[i];
				try {
					super.process(unit, i); // this.process(...) is optimized to not process already known units

					// requested AST
					char[] fileName = unit.compilationResult.getFileName();
					ICompilationUnit source = (ICompilationUnit) this.requestedSources.get(fileName);
					if (source != null) {
						// convert AST
						CompilationResult compilationResult = unit.compilationResult;
						org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationResult.compilationUnit;
						char[] contents = sourceUnit.getContents();
						AST ast = AST.newAST(apiLevel);
						ast.setFlag(flags | AST.RESOLVED_BINDINGS);
						ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
						ASTConverter converter = new ASTConverter(compilerOptions, true/*need to resolve bindings*/, this.monitor);
						BindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0, this.fromJavaProject);
						ast.setBindingResolver(resolver);
						converter.setAST(ast);
						CompilationUnit compilationUnit = converter.convert(unit, contents);
						compilationUnit.setTypeRoot(source);
						compilationUnit.setLineEndTable(compilationResult.getLineSeparatorPositions());
						ast.setDefaultNodeFlag(0);
						ast.setOriginalModificationCount(ast.modificationCount());

						// pass it to requestor
						astRequestor.acceptAST(source, compilationUnit);

						worked(1);

						// remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
						this.requestedSources.put(fileName, null); // mark it as removed
					}

					// requested binding
					Object key = this.requestedKeys.get(fileName);
					if (key != null) {
						if (key instanceof BindingKeyResolver) {
							reportBinding(key, astRequestor, owner, unit);
							worked(1);
						} else if (key instanceof ArrayList) {
							Iterator iterator = ((ArrayList) key).iterator();
							while (iterator.hasNext()) {
								reportBinding(iterator.next(), astRequestor, owner, unit);
								worked(1);
							}
						}

						// remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
						this.requestedKeys.put(fileName, null); // mark it as removed
					}
				} finally {
					// cleanup compilation unit result
					unit.cleanUp();
				}
				this.unitsToProcess[i] = null; // release reference to processed unit declaration
				this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
			}

			// remaining binding keys
			DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, owner, this.bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0, true);
			Object[] keys = this.requestedKeys.valueTable;
			for (int j = 0, keysLength = keys.length; j < keysLength; j++) {
				BindingKeyResolver keyResolver = (BindingKeyResolver) keys[j];
				if (keyResolver == null) continue;
				Binding compilerBinding = keyResolver.getCompilerBinding();
				IBinding binding = compilerBinding == null ? null : resolver.getBinding(compilerBinding);
				// pass it to requestor
				astRequestor.acceptBinding(((BindingKeyResolver) this.requestedKeys.valueTable[j]).getKey(), binding);
				worked(1);
			}
		} catch (OperationCanceledException e) {
			throw e;
		} catch (AbortCompilation e) {
			this.handleInternalException(e, unit);
		} catch (Error e) {
			this.handleInternalException(e, unit, null);
			throw e; // rethrow
		} catch (RuntimeException e) {
			this.handleInternalException(e, unit, null);
			throw e; // rethrow
		} finally {
			// disconnect ourselves from ast requestor
			astRequestor.compilationUnitResolver = null;
		}
	}

	private void resolve(
			String[] sourceCompilationUnits,
			String[] encodings,
			String[] bindingKeys,
			FileASTRequestor astRequestor,
			int apiLevel,
			Map compilerOptions,
			int flags) {

		// temporarily connect ourselves to the ASTResolver - must disconnect when done
		astRequestor.compilationUnitResolver = this;
		this.bindingTables = new DefaultBindingResolver.BindingTables();
		CompilationUnitDeclaration unit = null;
		try {
			int length = sourceCompilationUnits.length;
			org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] sourceUnits = new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[length];
			int count = 0;
			for (int i = 0; i < length; i++) {
				char[] contents = null;
				String encoding = encodings != null ? encodings[i] : null;
				String sourceUnitPath = sourceCompilationUnits[i];
				try {
					contents = Util.getFileCharContent(new File(sourceUnitPath), encoding);
				} catch(IOException e) {
					// go to the next unit
					continue;
				}
				if (contents == null) {
					// go to the next unit
					continue;
				}
				sourceUnits[count++] = new org.eclipse.jdt.internal.compiler.batch.CompilationUnit(contents, sourceUnitPath, encoding);
			}
			beginToCompile(sourceUnits, bindingKeys);
			// process all units (some more could be injected in the loop by the lookup environment)
			for (int i = 0; i < this.totalUnits; i++) {
				if (resolvedRequestedSourcesAndKeys(i)) {
					// no need to keep resolving if no more ASTs and no more binding keys are needed
					// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=114935
					// cleanup remaining units
					for (; i < this.totalUnits; i++) {
						this.unitsToProcess[i].cleanUp();
						this.unitsToProcess[i] = null;
					}
					break;
				}
				unit = this.unitsToProcess[i];
				try {
					super.process(unit, i); // this.process(...) is optimized to not process already known units

					// requested AST
					char[] fileName = unit.compilationResult.getFileName();
					org.eclipse.jdt.internal.compiler.env.ICompilationUnit source = (org.eclipse.jdt.internal.compiler.env.ICompilationUnit) this.requestedSources.get(fileName);
					if (source != null) {
						// convert AST
						CompilationResult compilationResult = unit.compilationResult;
						org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit = compilationResult.compilationUnit;
						char[] contents = sourceUnit.getContents();
						AST ast = AST.newAST(apiLevel);
						ast.setFlag(flags | AST.RESOLVED_BINDINGS);
						ast.setDefaultNodeFlag(ASTNode.ORIGINAL);
						ASTConverter converter = new ASTConverter(compilerOptions, true/*need to resolve bindings*/, this.monitor);
						BindingResolver resolver = new DefaultBindingResolver(unit.scope, null, this.bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0, this.fromJavaProject);
						ast.setBindingResolver(resolver);
						converter.setAST(ast);
						CompilationUnit compilationUnit = converter.convert(unit, contents);
						compilationUnit.setTypeRoot(null);
						compilationUnit.setLineEndTable(compilationResult.getLineSeparatorPositions());
						ast.setDefaultNodeFlag(0);
						ast.setOriginalModificationCount(ast.modificationCount());

						// pass it to requestor
						astRequestor.acceptAST(new String(source.getFileName()), compilationUnit);

						worked(1);

						// remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
						this.requestedSources.put(fileName, null); // mark it as removed
					}

					// requested binding
					Object key = this.requestedKeys.get(fileName);
					if (key != null) {
						if (key instanceof BindingKeyResolver) {
							reportBinding(key, astRequestor, unit);
							worked(1);
						} else if (key instanceof ArrayList) {
							Iterator iterator = ((ArrayList) key).iterator();
							while (iterator.hasNext()) {
								reportBinding(iterator.next(), astRequestor, unit);
								worked(1);
							}
						}

						// remove at the end so that we don't resolve twice if a source and a key for the same file name have been requested
						this.requestedKeys.put(fileName, null); // mark it as removed
					}
				} finally {
					// cleanup compilation unit result
					unit.cleanUp();
				}
				this.unitsToProcess[i] = null; // release reference to processed unit declaration
				this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
			}

			// remaining binding keys
			DefaultBindingResolver resolver = new DefaultBindingResolver(this.lookupEnvironment, null, this.bindingTables, (flags & ICompilationUnit.ENABLE_BINDINGS_RECOVERY) != 0, true);
			Object[] keys = this.requestedKeys.valueTable;
			for (int j = 0, keysLength = keys.length; j < keysLength; j++) {
				BindingKeyResolver keyResolver = (BindingKeyResolver) keys[j];
				if (keyResolver == null) continue;
				Binding compilerBinding = keyResolver.getCompilerBinding();
				IBinding binding = compilerBinding == null ? null : resolver.getBinding(compilerBinding);
				// pass it to requestor
				astRequestor.acceptBinding(((BindingKeyResolver) this.requestedKeys.valueTable[j]).getKey(), binding);
				worked(1);
			}
		} catch (OperationCanceledException e) {
			throw e;
		} catch (AbortCompilation e) {
			this.handleInternalException(e, unit);
		} catch (Error e) {
			this.handleInternalException(e, unit, null);
			throw e; // rethrow
		} catch (RuntimeException e) {
			this.handleInternalException(e, unit, null);
			throw e; // rethrow
		} finally {
			// disconnect ourselves from ast requestor
			astRequestor.compilationUnitResolver = null;
		}
	}

	private void reportBinding(Object key, ASTRequestor astRequestor, WorkingCopyOwner owner, CompilationUnitDeclaration unit) {
		BindingKeyResolver keyResolver = (BindingKeyResolver) key;
		Binding compilerBinding = keyResolver.getCompilerBinding();
		if (compilerBinding != null) {
			DefaultBindingResolver resolver = new DefaultBindingResolver(unit.scope, owner, this.bindingTables, false, this.fromJavaProject);
			AnnotationBinding annotationBinding = keyResolver.getAnnotationBinding();
			IBinding binding;
			if (annotationBinding != null) {
				binding = resolver.getAnnotationInstance(annotationBinding);
			} else {
				binding = resolver.getBinding(compilerBinding);
			}
			if (binding != null)
				astRequestor.acceptBinding(keyResolver.getKey(), binding);
		}
	}

	private void reportBinding(Object key, FileASTRequestor astRequestor, CompilationUnitDeclaration unit) {
		BindingKeyResolver keyResolver = (BindingKeyResolver) key;
		Binding compilerBinding = keyResolver.getCompilerBinding();
		if (compilerBinding != null) {
			DefaultBindingResolver resolver = new DefaultBindingResolver(unit.scope, null, this.bindingTables, false, this.fromJavaProject);
			AnnotationBinding annotationBinding = keyResolver.getAnnotationBinding();
			IBinding binding;
			if (annotationBinding != null) {
				binding = resolver.getAnnotationInstance(annotationBinding);
			} else {
				binding = resolver.getBinding(compilerBinding);
			}
			if (binding != null)
				astRequestor.acceptBinding(keyResolver.getKey(), binding);
		}
	}

	private CompilationUnitDeclaration resolve(
			CompilationUnitDeclaration unit,
			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
			NodeSearcher nodeSearcher,
			boolean verifyMethods,
			boolean analyzeCode,
			boolean generateCode) {

		try {

			if (unit == null) {
				// build and record parsed units
				this.parseThreshold = 0; // will request a full parse
				beginToCompile(new org.eclipse.jdt.internal.compiler.env.ICompilationUnit[] { sourceUnit });
				// find the right unit from what was injected via accept(ICompilationUnit,..):
				for (int i=0, max = this.totalUnits; i < max; i++) {
					CompilationUnitDeclaration currentCompilationUnitDeclaration = this.unitsToProcess[i];
					if (currentCompilationUnitDeclaration != null
							&& currentCompilationUnitDeclaration.compilationResult.compilationUnit == sourceUnit) {
						unit = currentCompilationUnitDeclaration;
						break;
					}
				}
				if (unit == null) {
					unit = this.unitsToProcess[0]; // fall back to old behavior
				}
			} else {
				// initial type binding creation
				this.lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/);

				// binding resolution
				this.lookupEnvironment.completeTypeBindings();
			}

			if (nodeSearcher == null) {
				this.parser.getMethodBodies(unit); // no-op if method bodies have already been parsed
			} else {
				int searchPosition = nodeSearcher.position;
				char[] source = sourceUnit.getContents();
				int length = source.length;
				if (searchPosition >= 0 && searchPosition <= length) {
					unit.traverse(nodeSearcher, unit.scope);

					org.eclipse.jdt.internal.compiler.ast.ASTNode node = nodeSearcher.found;

		 			if (node != null) {
						// 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;

						this.parser.scanner.setSource(source, unit.compilationResult);

						org.eclipse.jdt.internal.compiler.ast.TypeDeclaration enclosingTypeDeclaration = nodeSearcher.enclosingType;
						if (node instanceof AbstractMethodDeclaration) {
							((AbstractMethodDeclaration)node).parseStatements(this.parser, unit);
						} else if (enclosingTypeDeclaration != null) {
							if (node instanceof org.eclipse.jdt.internal.compiler.ast.Initializer) {
								((org.eclipse.jdt.internal.compiler.ast.Initializer) node).parseStatements(this.parser, enclosingTypeDeclaration, unit);
							} else if (node instanceof org.eclipse.jdt.internal.compiler.ast.TypeDeclaration) {
								((org.eclipse.jdt.internal.compiler.ast.TypeDeclaration)node).parseMethods(this.parser, unit);
							}
						}
						// 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;
					}
				}
			}

			if (unit.scope != null) {
				CompilationUnitDeclaration previousUnit = this.lookupEnvironment.unitBeingCompleted;
				this.lookupEnvironment.unitBeingCompleted = unit;
				try {
					// fault in fields & methods
					unit.scope.faultInTypes();
					if (unit.scope != null && verifyMethods) {
						// http://dev.eclipse.org/bugs/show_bug.cgi?id=23117
	 					// verify inherited methods
						unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier());
					}
					// type checking
					unit.resolve();
	
					// flow analysis
					if (analyzeCode) unit.analyseCode();
	
					// code generation
					if (generateCode) unit.generateCode();
	
					// finalize problems (suppressWarnings)
					unit.finalizeProblems();
				} finally {
					this.lookupEnvironment.unitBeingCompleted = previousUnit; // paranoia, always null in org.eclipse.jdt.core.tests.dom.RunAllTests
				}
			}
			if (this.unitsToProcess != null) this.unitsToProcess[0] = null; // release reference to processed unit declaration
			this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
			return unit;
		} catch (AbortCompilation e) {
			this.handleInternalException(e, unit);
			return unit == null ? this.unitsToProcess[0] : unit;
		} catch (Error e) {
			this.handleInternalException(e, unit, null);
			throw e; // rethrow
		} catch (RuntimeException e) {
			this.handleInternalException(e, unit, null);
			throw e; // rethrow
		} finally {
			// No reset is performed there anymore since,
			// within the CodeAssist (or related tools),
			// the compiler may be called *after* a call
			// to this resolve(...) method. And such a call
			// needs to have a compiler with a non-empty
			// environment.
			// this.reset();
		}
	}
	/*
	 * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
	 */
	public CompilationUnitDeclaration resolve(
			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
			boolean verifyMethods,
			boolean analyzeCode,
			boolean generateCode) {

		return resolve(
			null, /* no existing compilation unit declaration*/
			sourceUnit,
			null/*no node searcher*/,
			verifyMethods,
			analyzeCode,
			generateCode);
	}

	boolean resolvedRequestedSourcesAndKeys(int unitIndexToProcess) {
		if (unitIndexToProcess < this.requestedSources.size() && unitIndexToProcess < this.requestedKeys.size())
			return false; // must process at least this many units before checking to see if all are done

		Object[] sources = this.requestedSources.valueTable;
		for (int i = 0, l = sources.length; i < l; i++)
			if (sources[i] != null) return false;
		Object[] keys = this.requestedKeys.valueTable;
		for (int i = 0, l = keys.length; i < l; i++)
			if (keys[i] != null) return false;
		return true;
	}

	/*
	 * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
	 */
	public CompilationUnitDeclaration resolve(
			CompilationUnitDeclaration unit,
			org.eclipse.jdt.internal.compiler.env.ICompilationUnit sourceUnit,
			boolean verifyMethods,
			boolean analyzeCode,
			boolean generateCode) {

		return resolve(
			unit,
			sourceUnit,
			null/*no node searcher*/,
			verifyMethods,
			analyzeCode,
			generateCode);
	}

	private void worked(int work) {
		if (this.monitor != null) {
			if (this.monitor.isCanceled())
				throw new OperationCanceledException();
			this.monitor.worked(work);
		}
	}
}
