/*******************************************************************************
 * Copyright (c) 2000, 2017 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 - contributions for
 *     							bug 337868 - [compiler][model] incomplete support for package-info.java when using SearchableEnvironment
 *     							bug 186342 - [compiler][null] Using annotations for null checking
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.compiler.CompilationProgress;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
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.Messages;
import org.eclipse.jdt.internal.compiler.util.Util;
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;

/**
 * OTDT changes:
 * ( MANY ;-).
 *
 * DEPENDENCIES:
 * What: extracted most of the control to Dependencies.
 * How:  use Dependencies.{setup,release} and Dependencies.ensureState(unit, state).
 * Where:beginToCompiler, accept(....)
 * Why:  we need to control compilation steps on a much more fine-grained level than the plain JDT.
 *
 * What: allow invocation of getMethodBodies from Dependencies.
 *
 * ROLE FILES:
 *
 * What: When requesting the team type from a role file's team package request source types only.
 * How:  Uses so far unused flag ClasspathDirectory.mode
 *
 * OTHER TOOLS:
 * What: give a chance to use a JavaDocParser
 * Why:  support for documentation generator
 *
 */
@SuppressWarnings("rawtypes")
public class Compiler implements ITypeRequestor, ProblemSeverities {
	public Parser parser;
	public ICompilerRequestor requestor;
	public CompilerOptions options;
	public ProblemReporter problemReporter;
	protected PrintWriter out; // output for messages that are not sent to problemReporter
	public CompilerStats stats;
	public CompilationProgress progress;
	public int remainingIterations = 1;
//{ObjectTeams: mark kind of compiler:
	public boolean isBatchCompiler = false;
	public boolean sortCompilationUnits = true; // only JDT-tests set to false to maintain original error output
// SH}

	// management of unit to be processed
	//public CompilationUnitResult currentCompilationUnitResult;
	public CompilationUnitDeclaration[] unitsToProcess;
	public int totalUnits; // (totalUnits-1) gives the last unit in unitToProcess

	private Map<String, APTProblem[]> aptProblems;

	// name lookup
	public LookupEnvironment lookupEnvironment;

	// ONCE STABILIZED, THESE SHOULD RETURN TO A FINAL FIELD
	public static boolean DEBUG = false;
	public int parseThreshold = -1;

	public AbstractAnnotationProcessorManager annotationProcessorManager;
	public int annotationProcessorStartIndex = 0;
	public ReferenceBinding[] referenceBindings;
	public boolean useSingleThread = true; // by default the compiler will not use worker threads to read/process/write

	// number of initial units parsed at once (-1: none)

	/*
	 * Static requestor reserved to listening compilation results in debug mode,
	 * so as for example to monitor compiler activity independantly from a particular
	 * builder implementation. It is reset at the end of compilation, and should not
	 * persist any information after having been reset.
	 */
	public static IDebugRequestor DebugRequestor = null;

	/**
	 * Answer a new compiler 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 (e.g. 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 settings java.util.Map
	 *      The settings that control the compiler behavior.
	 *
	 *  @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.
	 *
	 *  @deprecated this constructor is kept to preserve 3.1 and 3.2M4 compatibility
	 */
	public Compiler(
			INameEnvironment environment,
			IErrorHandlingPolicy policy,
			Map<String, String> settings,
			final ICompilerRequestor requestor,
			IProblemFactory problemFactory) {
		this(environment, policy, new CompilerOptions(settings), requestor, problemFactory, null /* printwriter */, null /* progress */);
	}

	/**
	 * Answer a new compiler 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 (e.g. 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 settings java.util.Map
	 *      The settings that control the compiler behavior.
	 *
	 *  @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.
	 *
	 *  @param parseLiteralExpressionsAsConstants <code>boolean</code>
	 *		This parameter is used to optimize the literals or leave them as they are in the source.
	 * 		If you put true, "Hello" + " world" will be converted to "Hello world".
	 *
	 *  @deprecated this constructor is kept to preserve 3.1 and 3.2M4 compatibility
	 */
	public Compiler(
			INameEnvironment environment,
			IErrorHandlingPolicy policy,
			Map settings,
			final ICompilerRequestor requestor,
			IProblemFactory problemFactory,
			boolean parseLiteralExpressionsAsConstants) {
		this(environment, policy, new CompilerOptions(settings, parseLiteralExpressionsAsConstants), requestor, problemFactory, null /* printwriter */, null /* progress */);
	}

	/**
	 * Answer a new compiler 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 (e.g. 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 options org.eclipse.jdt.internal.compiler.impl.CompilerOptions
	 *      The options that control the compiler behavior.
	 *
	 *  @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 Compiler(
		INameEnvironment environment,
		IErrorHandlingPolicy policy,
		CompilerOptions options,
		final ICompilerRequestor requestor,
		IProblemFactory problemFactory) {
		this(environment, policy, options, requestor, problemFactory, null /* printwriter */, null /* progress */);
	}

	/**
	 * Answer a new compiler 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 (e.g. 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 options org.eclipse.jdt.internal.compiler.impl.CompilerOptions
	 *      The options that control the compiler behavior.
	 *
	 *  @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.
	 * @deprecated
	 */
	public Compiler(
			INameEnvironment environment,
			IErrorHandlingPolicy policy,
			CompilerOptions options,
			final ICompilerRequestor requestor,
			IProblemFactory problemFactory,
			PrintWriter out) {
		this(environment, policy, options, requestor, problemFactory, out, null /* progress */);
	}

	public Compiler(
			INameEnvironment environment,
			IErrorHandlingPolicy policy,
			CompilerOptions options,
			final ICompilerRequestor requestor,
			IProblemFactory problemFactory,
			PrintWriter out,
			CompilationProgress progress) {

		this.options = options;
		this.progress = progress;

		// wrap requestor in DebugRequestor if one is specified
		if(DebugRequestor == null) {
			this.requestor = requestor;
		} else {
			this.requestor = new ICompilerRequestor(){
				@Override
				public void acceptResult(CompilationResult result){
					if (DebugRequestor.isActive()){
						DebugRequestor.acceptDebugResult(result);
					}
					requestor.acceptResult(result);
				}
			};
		}
		this.problemReporter = new ProblemReporter(policy, this.options, problemFactory);
//{ObjectTeams: swapped order to allow overriding default problemReporter:
/* orig:
		this.lookupEnvironment = new LookupEnvironment(this, this.options, this.problemReporter, environment);
  :giro */
		this.out = out == null ? new PrintWriter(System.out, true) : out;
		this.stats = new CompilerStats();
		initializeParser();
		this.lookupEnvironment = new LookupEnvironment(this, this.options, this.problemReporter, environment);
// SH}
	}

	/**
	 * Add an additional binary type
	 */
	@Override
	public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
		if (this.options.verbose) {
			this.out.println(
				Messages.bind(Messages.compilation_loadBinary, new String(binaryType.getName())));
//			new Exception("TRACE BINARY").printStackTrace(System.out);
//		    System.out.println();
		}
		LookupEnvironment env = packageBinding.environment;
		env.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, this.totalUnits, this.totalUnits, this.options.maxProblemsPerUnit);
		unitResult.checkSecondaryTypes = true;
		try {
			if (this.options.verbose) {
				String count = String.valueOf(this.totalUnits + 1);
				this.out.println(
					Messages.bind(Messages.compilation_request,
						new String[] {
							count,
							count,
							new String(sourceUnit.getFileName())
						}));
			}
			// diet parsing for large collection of unit
			CompilationUnitDeclaration parsedUnit;
			if (this.totalUnits < this.parseThreshold) {
				parsedUnit = this.parser.parse(sourceUnit, unitResult);
			} else {
				parsedUnit = this.parser.dietParse(sourceUnit, unitResult);
			}
//{ObjectTeams: unchanged but redirected to  Dependencies: (Dependencies.setup must be called before).
			// initial type binding creation
			this.lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction);
			addCompilationUnit(sourceUnit, parsedUnit);

			// binding resolution
			this.lookupEnvironment.completeTypeBindings(parsedUnit);
// SH}
		} 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
				this.requestor.acceptResult(unitResult.tagAsAccepted());
			} else {
				throw e; // want to abort enclosing request to compile
			}
		}
	}

	/**
	 * Add additional source types
	 */
	@Override
	public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding, AccessRestriction accessRestriction) {
		this.problemReporter.abortDueToInternalError(
			Messages.bind(Messages.abort_againstSourceModel, new String[] { String.valueOf(sourceTypes[0].getName()), String.valueOf(sourceTypes[0].getFileName()) }));
	}

	protected synchronized void addCompilationUnit(
		ICompilationUnit sourceUnit,
		CompilationUnitDeclaration parsedUnit) {

		if (this.unitsToProcess == null)
			return; // not collecting units

		// append the unit to the list of ones to process later on
		int size = this.unitsToProcess.length;
		if (this.totalUnits == size)
			// when growing reposition units starting at position 0
			System.arraycopy(
				this.unitsToProcess,
				0,
				(this.unitsToProcess = new CompilationUnitDeclaration[size * 2]),
				0,
				this.totalUnits);
//{ObjectTeams: record 'place' for external invocation of getMethodBodies:
        parsedUnit.place = this.totalUnits;
        if (parsedUnit.scope != null)
        	parsedUnit.scope.parser = this.parser;
// SH}
		this.unitsToProcess[this.totalUnits++] = parsedUnit;
	}

	/**
	 * Add the initial set of compilation units into the loop
	 *  ->  build compilation unit declarations, their bindings and record their results.
	 */
	protected void beginToCompile(ICompilationUnit[] sourceUnits) {
		int maxUnits = sourceUnits.length;
		this.totalUnits = 0;
		this.unitsToProcess = new CompilationUnitDeclaration[maxUnits];

		internalBeginToCompile(sourceUnits, maxUnits);
	}

	/**
	 * Checks whether the compilation has been canceled and reports the given progress to the compiler progress.
	 */
	protected void reportProgress(String taskDecription) {
		if (this.progress != null) {
			if (this.progress.isCanceled()) {
				// Only AbortCompilation can stop the compiler cleanly.
				// We check cancellation again following the call to compile.
				throw new AbortCompilation(true, null);
			}
			this.progress.setTaskName(taskDecription);
		}
	}

	/**
	 * Checks whether the compilation has been canceled and reports the given work increment to the compiler progress.
	 */
	protected void reportWorked(int workIncrement, int currentUnitIndex) {
		if (this.progress != null) {
			if (this.progress.isCanceled()) {
				// Only AbortCompilation can stop the compiler cleanly.
				// We check cancellation again following the call to compile.
				throw new AbortCompilation(true, null);
			}
			this.progress.worked(workIncrement, (this.totalUnits* this.remainingIterations) - currentUnitIndex - 1);
		}
	}

	public void compile(ICompilationUnit[] sourceUnits) {
		compile(sourceUnits, false);
	}
	/**
	 * General API
	 * -> compile each of supplied files
	 * -> recompile any required types for which we have an incomplete principle structure
	 */
	private void compile(ICompilationUnit[] sourceUnits, boolean lastRound) {
		this.stats.startTime = System.currentTimeMillis();
//{ObjectTeams:
/* orig:
		try {
  :giro */
		try (Config config = Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true, false))
		{
//carp}
			// build and record parsed units
			reportProgress(Messages.compilation_beginningToCompile);

//{ObjectTeams: OT/J code always needs CU sorting:
/* orig:
			if (this.options.complianceLevel >= ClassFileConstants.JDK9) {
  :giro */
			if (this.options.complianceLevel >= ClassFileConstants.JDK9 || !this.options.isPureJava) {
// SH}
				// in Java 9 the compiler must never ask the oracle for a module that is contained in the input units:
				sortModuleDeclarationsFirst(sourceUnits);
			}
			if (this.annotationProcessorManager == null) {
				beginToCompile(sourceUnits);
			} else {
				ICompilationUnit[] originalUnits = sourceUnits.clone(); // remember source units in case a source type collision occurs
				try {
					beginToCompile(sourceUnits);
					if (!lastRound) {
						processAnnotations();
					}
					if (!this.options.generateClassFiles) {
						// -proc:only was set on the command line
						return;
					}
				} catch (SourceTypeCollisionException e) {
					backupAptProblems();
					reset();
					// a generated type was referenced before it was created
					// the compiler either created a MissingType or found a BinaryType for it
					// so add the processor's generated files & start over,
					// but remember to only pass the generated files to the annotation processor
					int originalLength = originalUnits.length;
					int newProcessedLength = e.newAnnotationProcessorUnits.length;
					ICompilationUnit[] combinedUnits = new ICompilationUnit[originalLength + newProcessedLength];
					System.arraycopy(originalUnits, 0, combinedUnits, 0, originalLength);
					System.arraycopy(e.newAnnotationProcessorUnits, 0, combinedUnits, originalLength, newProcessedLength);
					this.annotationProcessorStartIndex  = originalLength;
					compile(combinedUnits, e.isLastRound);
					return;
				}
			}
			// Restore the problems before the results are processed and cleaned up.
			restoreAptProblems();
			processCompiledUnits(0, lastRound);
		} catch (AbortCompilation e) {
			this.handleInternalException(e, null);
		}
		if (this.options.verbose) {
			if (this.totalUnits > 1) {
				this.out.println(
					Messages.bind(Messages.compilation_units, String.valueOf(this.totalUnits)));
			} else {
				this.out.println(
					Messages.bind(Messages.compilation_unit, String.valueOf(this.totalUnits)));
			}
		}
	}

	private void sortModuleDeclarationsFirst(ICompilationUnit[] sourceUnits) {
		Arrays.sort(sourceUnits, (u1, u2) -> {
			char[] fn1 = u1.getFileName();
			char[] fn2 = u2.getFileName();
			boolean isMod1 = CharOperation.endsWith(fn1, TypeConstants.MODULE_INFO_FILE_NAME) || CharOperation.endsWith(fn1, TypeConstants.MODULE_INFO_CLASS_NAME);
			boolean isMod2 = CharOperation.endsWith(fn2, TypeConstants.MODULE_INFO_FILE_NAME) || CharOperation.endsWith(fn2, TypeConstants.MODULE_INFO_CLASS_NAME);
			if (isMod1 == isMod2)
//{ObjectTeams: ensure teams (short file name) come before their role files (longer file name):
			{
				if (this.sortCompilationUnits)
					return Integer.compare(fn1.length, fn2.length);
// orig:
				return 0;
// :giro
			}
// SH}
			return isMod1 ? -1 : 1;
		});
	}

	class APTProblem {
		CategorizedProblem problem;
		ReferenceContext context;
		APTProblem(CategorizedProblem problem, ReferenceContext context) {
			this.problem = problem;
			this.context = context;
		}
	}

	protected void backupAptProblems() {
		if (this.unitsToProcess == null) return;
		for (int i = 0; i < this.totalUnits; i++) {
			CompilationUnitDeclaration unitDecl = this.unitsToProcess[i];
			CompilationResult result = unitDecl.compilationResult;
			if (result != null && result.hasErrors()) {
				CategorizedProblem[] errors = result.getErrors();
				for (CategorizedProblem problem : errors) {
					if (problem.getCategoryID() == CategorizedProblem.CAT_UNSPECIFIED) {
						if (this.aptProblems == null) {
							this.aptProblems = new HashMap<>();
						}
						APTProblem[] problems = this.aptProblems.get(new String(unitDecl.getFileName()));
						if (problems == null) {
							this.aptProblems.put(
									new String(unitDecl.getFileName()),
									new APTProblem[] { new APTProblem(problem, result.getContext(problem)) });
						} else {
							APTProblem[] temp = new APTProblem[problems.length + 1];
							System.arraycopy(problems, 0, temp, 0, problems.length);
							temp[problems.length] = new APTProblem(problem, result.getContext(problem));
							this.aptProblems.put(new String(unitDecl.getFileName()), temp);
						}
					}
				}
			}
		}
	}

	protected void restoreAptProblems() {
		if (this.unitsToProcess != null && this.aptProblems!= null) {
			for (int i = 0; i < this.totalUnits; i++) {
				CompilationUnitDeclaration unitDecl = this.unitsToProcess[i];
				APTProblem[] problems = this.aptProblems.get(new String(unitDecl.getFileName()));
				if (problems != null) {
					for (APTProblem problem : problems) {
						unitDecl.compilationResult.record(problem.problem, problem.context);
					}
				}
			}
		}
		this.aptProblems = null; // No need for this.
	}

	protected void processCompiledUnits(int startingIndex, boolean lastRound) throws java.lang.Error {
		CompilationUnitDeclaration unit = null;
		ProcessTaskManager processingTask = null;
		try {
			if (this.useSingleThread) {
				// process all units (some more could be injected in the loop by the lookup environment)
				for (int i = startingIndex; i < this.totalUnits; i++) {
					unit = this.unitsToProcess[i];
					if (unit.compilationResult != null && unit.compilationResult.hasBeenAccepted)
						continue;
					reportProgress(Messages.bind(Messages.compilation_processing, new String(unit.getFileName())));
					try {
						if (this.options.verbose)
							this.out.println(
								Messages.bind(Messages.compilation_process,
								new String[] {
									String.valueOf(i + 1),
									String.valueOf(this.totalUnits),
									new String(this.unitsToProcess[i].getFileName())
								}));
						process(unit, i);
					} finally {
						// cleanup compilation unit result, but only if not annotation processed.
						if (this.annotationProcessorManager == null || shouldCleanup(i))
							unit.cleanUp();
					}
					if (this.annotationProcessorManager == null) {
						this.unitsToProcess[i] = null; // release reference to processed unit declaration
					}

					reportWorked(1, i);
					this.stats.lineCount += unit.compilationResult.lineSeparatorPositions.length;
					long acceptStart = System.currentTimeMillis();
					this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
					this.stats.generateTime += System.currentTimeMillis() - acceptStart; // record accept time as part of generation
					if (this.options.verbose)
						this.out.println(
							Messages.bind(Messages.compilation_done,
							new String[] {
								String.valueOf(i + 1),
								String.valueOf(this.totalUnits),
								new String(unit.getFileName())
							}));
				}
			} else {
				processingTask = new ProcessTaskManager(this, startingIndex);
				int acceptedCount = 0;
				// process all units (some more could be injected in the loop by the lookup environment)
				// the processTask can continue to process units until its fixed sized cache is full then it must wait
				// for this this thread to accept the units as they appear (it only waits if no units are available)
				while (true) {
					try {
						unit = processingTask.removeNextUnit(); // waits if no units are in the processed queue
					} catch (Error | RuntimeException e) {
						unit = processingTask.unitToProcess;
						throw e;
					}
					if (unit == null) break;
					reportWorked(1, acceptedCount++);
					this.stats.lineCount += unit.compilationResult.lineSeparatorPositions.length;
					this.requestor.acceptResult(unit.compilationResult.tagAsAccepted());
					if (this.options.verbose)
						this.out.println(
							Messages.bind(Messages.compilation_done,
							new String[] {
								String.valueOf(acceptedCount),
								String.valueOf(this.totalUnits),
								new String(unit.getFileName())
							}));
				}
			}
			if (!lastRound) {
				if (this.annotationProcessorManager != null && this.totalUnits > this.annotationProcessorStartIndex) {
					int backup = this.annotationProcessorStartIndex;
					int prevUnits = this.totalUnits;
					processAnnotations();
					// Clean up the units that were left out previously for annotation processing.
					for (int i = backup; i < prevUnits; i++) {
						this.unitsToProcess[i].cleanUp();
					}
					processCompiledUnits(backup, lastRound);
				}
			}
		} catch (AbortCompilation e) {
			this.handleInternalException(e, unit);
		} catch (Error | RuntimeException e) {
			this.handleInternalException(e, unit, null);
			throw e; // rethrow
		} finally {
			if (processingTask != null) {
				processingTask.shutdown();
				processingTask = null;
			}
			reset();
			this.annotationProcessorStartIndex  = 0;
			this.stats.endTime = System.currentTimeMillis();
			this.stats.overallTime += this.stats.endTime - this.stats.startTime;
		}
	}

	public synchronized CompilationUnitDeclaration getUnitToProcess(int next) {
		if (next < this.totalUnits) {
			CompilationUnitDeclaration unit = this.unitsToProcess[next];
			if (this.annotationProcessorManager == null || next < this.annotationProcessorStartIndex) {
				this.unitsToProcess[next] = null; // release reference to processed unit declaration
			}
			return unit;
		}
		return null;
	}

	/*
	 * Returns whether the compilation unit at the given index should be
	 * cleaned up after processing. This basically means whether or not
	 * the unit is still required for annotation processing.
	 */
	public boolean shouldCleanup(int index) {
		return index < this.annotationProcessorStartIndex;
	}

	public void setBinaryTypes(ReferenceBinding[] binaryTypes) {
		this.referenceBindings = binaryTypes;
	}
	/*
	 * Compiler crash recovery in case of unexpected runtime exceptions
	 */
	protected void handleInternalException(
		Throwable internalException,
		CompilationUnitDeclaration unit,
		CompilationResult result) {

		if (result == null && unit != null) {
			result = unit.compilationResult; // current unit being processed ?
		}
		// Lookup environment may be in middle of connecting types
		if (result == null && this.lookupEnvironment.unitBeingCompleted != null) {
		    result = this.lookupEnvironment.unitBeingCompleted.compilationResult;
		}
		if (result == null) {
			synchronized (this) {
				if (this.unitsToProcess != null && this.totalUnits > 0)
					result = this.unitsToProcess[this.totalUnits - 1].compilationResult;
			}
		}
		// last unit in beginToCompile ?

		boolean needToPrint = true;
		if (result != null) {
			/* create and record a compilation problem */
			// only keep leading portion of the trace
			String[] pbArguments = new String[] {
				Messages.bind(Messages.compilation_internalError, Util.getExceptionSummary(internalException)),
			};

			result
				.record(
					this.problemReporter
						.createProblem(
							result.getFileName(),
							IProblem.Unclassified,
							pbArguments,
							pbArguments,
							Error, // severity
							0, // source start
							0, // source end
							0, // line number
							0),// column number
					unit, true);

			/* hand back the compilation result */
			if (!result.hasBeenAccepted) {
				this.requestor.acceptResult(result.tagAsAccepted());
				needToPrint = false;
			}
		}
		if (needToPrint) {
			/* dump a stack trace to the console */
			internalException.printStackTrace();
		}
	}

	/*
	 * Compiler recovery in case of internal AbortCompilation event
	 */
	protected void handleInternalException(
		AbortCompilation abortException,
		CompilationUnitDeclaration unit) {

		/* special treatment for SilentAbort: silently cancelling the compilation process */
		if (abortException.isSilent) {
			if (abortException.silentException == null) {
				return;
			}
			throw abortException.silentException;
		}

		/* uncomment following line to see where the abort came from */
		// abortException.printStackTrace();

		// Exception may tell which compilation result it is related, and which problem caused it
		CompilationResult result = abortException.compilationResult;
		if (result == null && unit != null) {
			result = unit.compilationResult; // current unit being processed ?
		}
		// Lookup environment may be in middle of connecting types
		if (result == null && this.lookupEnvironment.unitBeingCompleted != null) {
		    result = this.lookupEnvironment.unitBeingCompleted.compilationResult;
		}
		if (result == null) {
			synchronized (this) {
				if (this.unitsToProcess != null && this.totalUnits > 0)
					result = this.unitsToProcess[this.totalUnits - 1].compilationResult;
			}
		}
		// last unit in beginToCompile ?
		if (result != null && !result.hasBeenAccepted) {
			/* distant problem which could not be reported back there? */
			if (abortException.problem != null) {
				recordDistantProblem: {
				CategorizedProblem distantProblem = abortException.problem;
				CategorizedProblem[] knownProblems = result.problems;
					for (int i = 0; i < result.problemCount; i++) {
						if (knownProblems[i] == distantProblem) { // already recorded
							break recordDistantProblem;
						}
					}
					if (distantProblem instanceof DefaultProblem) { // fixup filename TODO (philippe) should improve API to make this official
						((DefaultProblem) distantProblem).setOriginatingFileName(result.getFileName());
					}
					result.record(distantProblem, unit, true);
				}
			} else {
				/* distant internal exception which could not be reported back there */
				if (abortException.exception != null) {
					this.handleInternalException(abortException.exception, null, result);
					return;
				}
			}
			/* hand back the compilation result */
			if (!result.hasBeenAccepted) {
				this.requestor.acceptResult(result.tagAsAccepted());
			}
		} else {
			abortException.printStackTrace();
		}
	}

	public void initializeParser() {

		this.parser = new Parser(this.problemReporter, this.options.parseLiteralExpressionsAsConstants);
	}

	private  void abortIfPreviewNotAllowed(ICompilationUnit[] sourceUnits, int maxUnits) {
		if (!this.options.enablePreviewFeatures)
			return;
		try {
			if (this.options.sourceLevel != ClassFileConstants.getLatestJDKLevel()) {
				this.problemReporter.abortDueToPreviewEnablingNotAllowed(CompilerOptions.versionFromJdkLevel(this.options.sourceLevel), CompilerOptions.getLatestVersion());
			}
		} catch (AbortCompilation a) {
			// best effort to find a way for reporting this problem: report on the first source
			if (a.compilationResult == null) {
				a.compilationResult = new CompilationResult(sourceUnits[0], 0, maxUnits, this.options.maxProblemsPerUnit);
			}
			throw a;
		}
	}
	/**
	 * Add the initial set of compilation units into the loop
	 *  ->  build compilation unit declarations, their bindings and record their results.
	 */
	protected void internalBeginToCompile(ICompilationUnit[] sourceUnits, int maxUnits) {
		abortIfPreviewNotAllowed(sourceUnits,maxUnits);
		if (!this.useSingleThread && maxUnits >= ReadManager.THRESHOLD)
			this.parser.readManager = new ReadManager(sourceUnits, maxUnits);
		// Switch the current policy and compilation result for this unit to the requested one.
		for (int i = 0; i < maxUnits; i++) {
			CompilationResult unitResult = null;
			try {
				if (this.options.verbose) {
					this.out.println(
						Messages.bind(Messages.compilation_request,
						new String[] {
							String.valueOf(i + 1),
							String.valueOf(maxUnits),
							new String(sourceUnits[i].getFileName())
						}));
				}
				// diet parsing for large collection of units
				CompilationUnitDeclaration parsedUnit;
				unitResult = new CompilationResult(sourceUnits[i], i, maxUnits, this.options.maxProblemsPerUnit);
				long parseStart = System.currentTimeMillis();
				if (this.totalUnits < this.parseThreshold) {
					parsedUnit = this.parser.parse(sourceUnits[i], unitResult);
				} else {
					parsedUnit = this.parser.dietParse(sourceUnits[i], unitResult);
				}
//{ObjectTeams: new backpointer needed as "client" for Config:
				parsedUnit.compiler = this;
// SH}
				long resolveStart = System.currentTimeMillis();
				this.stats.parseTime += resolveStart - parseStart;
				// initial type binding creation
				this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/);
				this.stats.resolveTime += System.currentTimeMillis() - resolveStart;
				addCompilationUnit(sourceUnits[i], parsedUnit);
				ImportReference currentPackage = parsedUnit.currentPackage;
				if (currentPackage != null) {
					unitResult.recordPackageName(currentPackage.tokens);
				}
				//} catch (AbortCompilationUnit e) {
				//	requestor.acceptResult(unitResult.tagAsAccepted());
			} catch (AbortCompilation a) {
				// best effort to find a way for reporting this problem:
				if (a.compilationResult == null)
					a.compilationResult = unitResult;
				throw a;
			} finally {
				sourceUnits[i] = null; // no longer hold onto the unit
			}
		}
		if (this.parser.readManager != null) {
			this.parser.readManager.shutdown();
			this.parser.readManager = null;
		}
		// binding resolution
		this.lookupEnvironment.completeTypeBindings();
	}

	/**
	 * Process a compilation unit already parsed and build.
	 */
	public void process(CompilationUnitDeclaration unit, int i) {
		this.lookupEnvironment.unitBeingCompleted = unit;
		long parseStart = System.currentTimeMillis();

//{ObjectTeams: check the state of role(s) and team(s) contained in the CU and
//				perform necessary translations using Dependencies.
        Dependencies.ensureState(unit, ITranslationStates.STATE_METHODS_PARSED);
/* orig:
		this.parser.getMethodBodies(unit);
  */

		long resolveStart = System.currentTimeMillis();
		this.stats.parseTime += resolveStart - parseStart;
  /*

		// fault in fields & methods
		if (unit.scope != null)
			unit.scope.faultInTypes();

		// verify inherited methods
		if (unit.scope != null)
			unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier());

		// type checking
		unit.resolve();
	*/
		// Note(SH): we do mimic a translation in separate phases in order to capture times:
/*OT:*/ Dependencies.ensureState(unit, ITranslationStates.STATE_RESOLVED);

		long analyzeStart = System.currentTimeMillis();
		this.stats.resolveTime += analyzeStart - resolveStart;
	/*
		//No need of analysis or generation of code if statements are not required
		if (!this.options.ignoreMethodBodies) unit.analyseCode(); // flow analysis
	*/
/*OT:*/ Dependencies.ensureState(unit, ITranslationStates.STATE_BYTE_CODE_GENERATED-1);

		long generateStart = System.currentTimeMillis();
		this.stats.analyzeTime += generateStart - analyzeStart;
	/*
		if (!this.options.ignoreMethodBodies) unit.generateCode(); // code generation
  :giro */
        Dependencies.ensureState(unit, ITranslationStates.STATE_BYTE_CODE_GENERATED);
// SH}

		// reference info
		if (this.options.produceReferenceInfo && unit.scope != null)
			unit.scope.storeDependencyInfo();

		// finalize problems (suppressWarnings)
		unit.finalizeProblems();

		this.stats.generateTime += System.currentTimeMillis() - generateStart;

		// refresh the total number of units known at this stage
		unit.compilationResult.totalUnitsKnown = this.totalUnits;

		this.lookupEnvironment.unitBeingCompleted = null;
	}

	protected void processAnnotations() {
		int newUnitSize = 0;
		int newClassFilesSize = 0;
		int bottom = this.annotationProcessorStartIndex;
		int top = this.totalUnits;
		ReferenceBinding[] binaryTypeBindingsTemp = this.referenceBindings;
		if (top == 0 && binaryTypeBindingsTemp == null) return;
		this.referenceBindings = null;
		do {
			// extract units to process
			int length = top - bottom;
			CompilationUnitDeclaration[] currentUnits = new CompilationUnitDeclaration[length];
			int index = 0;
			for (int i = bottom; i < top; i++) {
				CompilationUnitDeclaration currentUnit = this.unitsToProcess[i];
				currentUnits[index++] = currentUnit;
			}
			if (index != length) {
				System.arraycopy(currentUnits, 0, (currentUnits = new CompilationUnitDeclaration[index]), 0, index);
			}
			this.annotationProcessorManager.processAnnotations(currentUnits, binaryTypeBindingsTemp, false);
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=407841
			// It is possible that during the #processAnnotations() call, some units in the next batch would have been
			// brought forward and compiled already. If there are any such, process them for annotations then and there.
			// This would avoid the complications of marking some units as compiled but not-annotation-processed-yet.
			if (top < this.totalUnits) {
				length = this.totalUnits - top; // NOTE: Reuse the same variable, but make sure it's not used after this point
				CompilationUnitDeclaration[] addedUnits = new CompilationUnitDeclaration[length];
				System.arraycopy(this.unitsToProcess, top, addedUnits, 0, length);
				this.annotationProcessorManager.processAnnotations(addedUnits, binaryTypeBindingsTemp, false);
			}
			this.annotationProcessorStartIndex = top;
			ICompilationUnit[] newUnits = this.annotationProcessorManager.getNewUnits();
			newUnitSize = newUnits.length;
			ReferenceBinding[] newClassFiles = this.annotationProcessorManager.getNewClassFiles();
			binaryTypeBindingsTemp = newClassFiles;
			newClassFilesSize = newClassFiles.length;
			if (newUnitSize != 0) {
				ICompilationUnit[] newProcessedUnits = newUnits.clone(); // remember new units in case a source type collision occurs
				try {
					this.lookupEnvironment.isProcessingAnnotations = true;
					internalBeginToCompile(newUnits, newUnitSize);
				} catch (SourceTypeCollisionException e) {
					e.newAnnotationProcessorUnits = newProcessedUnits;
					throw e;
				} finally {
					this.lookupEnvironment.isProcessingAnnotations = false;
					this.annotationProcessorManager.reset();
				}
				bottom = top;
				top = this.totalUnits; // last unit added
				this.annotationProcessorStartIndex = top;
			} else {
				bottom = top;
				this.annotationProcessorManager.reset();
			}
		} while (newUnitSize != 0 || newClassFilesSize != 0);

		this.annotationProcessorManager.processAnnotations(null, null, true);
		// process potential units added in the final round see 329156
		ICompilationUnit[] newUnits = this.annotationProcessorManager.getNewUnits();
		newUnitSize = newUnits.length;
		try {
			if (newUnitSize != 0) {
				ICompilationUnit[] newProcessedUnits = newUnits.clone(); // remember new units in case a source type collision occurs
				try {
					this.lookupEnvironment.isProcessingAnnotations = true;
					internalBeginToCompile(newUnits, newUnitSize);
				} catch (SourceTypeCollisionException e) {
					e.isLastRound = true;
					e.newAnnotationProcessorUnits = newProcessedUnits;
					throw e;
				}
			}
		} finally {
			this.lookupEnvironment.isProcessingAnnotations = false;
			this.annotationProcessorManager.reset();
			this.annotationProcessorManager.cleanUp();
		}
		// Units added in final round don't get annotation processed
		this.annotationProcessorStartIndex = this.totalUnits;
	}

	public void reset() {
		this.lookupEnvironment.reset();
		this.parser.scanner.source = null;
		this.unitsToProcess = null;
		if (DebugRequestor != null) DebugRequestor.reset();
		this.problemReporter.reset();
	}

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

//{ObjectTeams:
/* orig:
		try {
  :giro */
	    try (Config config = setupDependencies(verifyMethods, analyzeCode, generateCode))
	    {
//SH}
			if (unit == null) {
				// build and record parsed units
				this.parseThreshold = 0; // will request a full parse
				beginToCompile(new ICompilationUnit[] { sourceUnit });
				// find the right unit from what was injected via accept(ICompilationUnit,..):
				for (int i=0; i<this.totalUnits; i++) {
					if (   this.unitsToProcess[i] != null
						&& this.unitsToProcess[i].compilationResult.compilationUnit == sourceUnit)
					{
						unit = this.unitsToProcess[i];
						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();
			}
			this.lookupEnvironment.unitBeingCompleted = unit;
//{ObjectTeams: check the state of role(s) and team(s) contained in the CU and
//				perform necessary translations
/* original version:
			this.parser.getMethodBodies(unit);
			if (unit.scope != null) {
				// 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();

*/
// now completely under our control:
            if (unit.scope != null) {
                Dependencies.ensureState(unit, ITranslationStates.STATE_BYTE_CODE_GENERATED);
// orig:
                // finalize problems (suppressWarnings)
                unit.finalizeProblems();
            }
// :giro
            else {
                // moved here from above: do at least this:
                this.parser.getMethodBodies(unit);
			}
// SH}
			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 | RuntimeException e) {
			this.handleInternalException(e, unit, null);
			throw e; // rethrow
		} finally {
			// leave this.lookupEnvironment.unitBeingCompleted set to the unit, until another unit is resolved
			// other calls to dom can cause classpath errors to be detected, resulting in AbortCompilation exceptions

			// 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();
		}
	}
//{ObjectTeams: hook for subclasses needing more setting up:
	protected Config setupDependencies(boolean verifyMethods, boolean analyzeCode, boolean generateCode) {
		return Dependencies.setup(this, this.parser, this.lookupEnvironment,
								  verifyMethods,
								  analyzeCode && !this.options.ignoreMethodBodies,
								  generateCode && !this.options.ignoreMethodBodies,
								  true, true, false);
	}
// SH}
	/**
	 * Internal API used to resolve a given compilation unit. Can run a subset of the compilation process
	 */
	public CompilationUnitDeclaration resolve(
			ICompilationUnit sourceUnit,
			boolean verifyMethods,
			boolean analyzeCode,
			boolean generateCode) {

		return resolve(
			null,
			sourceUnit,
			verifyMethods,
			analyzeCode,
			generateCode);
	}
//{ObjectTeams: new function in ITypeRequester for use by Config:
	@Override
	public Parser getPlainParser() {
		return null;
	}
// SH}
}
