/*******************************************************************************
 * Copyright (c) 2000, 2019 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
 *     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
 *								bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
 *								bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
 *								bug 392862 - [1.8][compiler][null] Evaluate null annotations on array types
 *								bug 392384 - [1.8][compiler][null] Restore nullness info from type annotations in class files
 *								Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
 *								Bug 415291 - [1.8][null] differentiate type incompatibilities due to null annotations
 *								Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
 *								Bug 415850 - [1.8] Ensure RunJDTCoreTests can cope with null annotations enabled
 *								Bug 415043 - [1.8][null] Follow-up re null type annotations after bug 392099
 *								Bug 416183 - [1.8][compiler][null] Overload resolution fails with null annotations
 *								Bug 416307 - [1.8][compiler][null] subclass with type parameter substitution confuses null checking
 *								Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
 *								Bug 416190 - [1.8][null] detect incompatible overrides due to null type annotations
 *								Bug 424624 - [1.8][null] if a static-object with annotation @NonNull is used, a warning is shown
 *								Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables
 *								Bug 439516 - [1.8][null] NonNullByDefault wrongly applied to implicit type bound of binary type
 *								Bug 434602 - Possible error with inferred null annotations leading to contradictory null annotations
 *								Bug 435805 - [1.8][compiler][null] Java 8 compiler does not recognize declaration style null annotations
 *								Bug 453475 - [1.8][null] Contradictory null annotations (4.5 M3 edition)
 *								Bug 457079 - Regression: type inference
 *								Bug 440477 - [null] Infrastructure for feeding external annotations into compilation
 *								Bug 455180 - IllegalStateException in AnnotatableTypeSystem.getRawType
 *								Bug 470467 - [null] Nullness of special Enum methods not detected from .class file
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ClassFilePool;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.HashtableOfModule;
import org.eclipse.jdt.internal.compiler.util.HashtableOfPackage;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;

@SuppressWarnings({"rawtypes", "unchecked"})
public class LookupEnvironment implements ProblemReasons, TypeConstants {

	/**
	 * Map from typeBinding -> accessRestriction rule
	 */
	private Map accessRestrictions;
	ImportBinding[] defaultImports;				// ROOT_ONLY
	/**
	 * The root environment driving the current compilation.
	 * Other mutable fields in this class marked as ROOT_ONLY must always be accessed from the root environment.
	 * It is assumed that external clients only know the root environment, whereas calls internally in the compiler
	 * have to delegate to root where necessary.
	 * Immutable fields with "global" semantics are SHARED among environments via aliasing.
	 */
	public final LookupEnvironment root;
	public ModuleBinding UnNamedModule;
	public ModuleBinding JavaBaseModule;
	public ModuleBinding module;
	public PackageBinding defaultPackage;
	/** All visible toplevel packages, i.e. observable packages associated with modules read by the current module. */
	HashtableOfPackage knownPackages;
	private int lastCompletedUnitIndex = -1; 	// ROOT_ONLY
	private int lastUnitIndex = -1; 			// ROOT_ONLY

	TypeSystem typeSystem;					 	// SHARED
	
	public INameEnvironment nameEnvironment;	// SHARED
	public CompilerOptions globalOptions;		// SHARED

	public ProblemReporter problemReporter; 	// SHARED
	public ClassFilePool classFilePool; 		// SHARED
	// indicate in which step on the compilation we are.
	// step 1 : build the reference binding
	// step 2 : conect the hierarchy (connect bindings)
	// step 3 : build fields and method bindings.
	private int stepCompleted; 					// ROOT_ONLY
	public ITypeRequestor typeRequestor;		// SHARED

	private SimpleLookupTable uniqueParameterizedGenericMethodBindings;
	
	// key is a string with the method selector value is an array of method bindings
	private SimpleLookupTable uniquePolymorphicMethodBindings;
	private SimpleLookupTable uniqueGetClassMethodBinding; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300734

	boolean useModuleSystem;					// true when compliance >= 9 and nameEnvironment is module aware
	// key is a string with the module name value is a module binding
	public HashtableOfModule knownModules;		// SHARED

	public CompilationUnitDeclaration unitBeingCompleted = null; // only set while completing units -- ROOT_ONLY
	public Object missingClassFileLocation = null; // only set when resolving certain references, to help locating problems
	private CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[4]; // ROOT_ONLY
	private MethodVerifier verifier;

	private ArrayList missingTypes;
	Set<SourceTypeBinding> typesBeingConnected;	// SHARED
	public boolean isProcessingAnnotations = false; // ROOT_ONLY
	public boolean mayTolerateMissingType = false;

	PackageBinding nullableAnnotationPackage;			// the package supposed to contain the Nullable annotation type
	PackageBinding nonnullAnnotationPackage;			// the package supposed to contain the NonNull annotation type
	PackageBinding nonnullByDefaultAnnotationPackage;	// the package supposed to contain the NonNullByDefault annotation type

	AnnotationBinding nonNullAnnotation;
	AnnotationBinding nullableAnnotation;

	Map<String,Integer> allNullAnnotations = null;

	final List<MethodBinding> deferredEnumMethods; // SHARED: during early initialization we cannot mark Enum-methods as nonnull.

	/** Global access to the outermost active inference context as the universe for inference variable interning. */
	InferenceContext18 currentInferenceContext;

	final static int BUILD_FIELDS_AND_METHODS = 4;
	final static int BUILD_TYPE_HIERARCHY = 1;
	final static int CHECK_AND_SET_IMPORTS = 2;
	final static int CONNECT_TYPE_HIERARCHY = 3;

	static final ProblemPackageBinding TheNotFoundPackage = new ProblemPackageBinding(CharOperation.NO_CHAR, NotFound);
	static final ProblemReferenceBinding TheNotFoundType = new ProblemReferenceBinding(CharOperation.NO_CHAR_CHAR, null, NotFound);
	static final ModuleBinding TheNotFoundModule = new ModuleBinding(CharOperation.NO_CHAR);

/** Construct the root LookupEnvironment, corresponding to the UnNamedModule. */
public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOptions, ProblemReporter problemReporter, INameEnvironment nameEnvironment) {
	this.root = this;
	this.UnNamedModule = new ModuleBinding.UnNamedModule(this);
	this.module = this.UnNamedModule;
	this.typeRequestor = typeRequestor;
	this.globalOptions = globalOptions;
	this.problemReporter = problemReporter;
	this.defaultPackage = new PackageBinding(this); // assume the default package always exists
	this.defaultImports = null;
	this.nameEnvironment = nameEnvironment;
	this.knownPackages = new HashtableOfPackage();
	this.uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(3);
	this.uniquePolymorphicMethodBindings = new SimpleLookupTable(3);
	this.missingTypes = null;
	this.accessRestrictions = new HashMap(3);
	this.classFilePool = ClassFilePool.newInstance();
	this.typesBeingConnected = new HashSet<>();
	this.deferredEnumMethods = new ArrayList<>();
	this.typeSystem = this.globalOptions.sourceLevel >= ClassFileConstants.JDK1_8 && this.globalOptions.storeAnnotations ? new AnnotatableTypeSystem(this) : new TypeSystem(this);
	this.knownModules = new HashtableOfModule();
	this.useModuleSystem = nameEnvironment instanceof IModuleAwareNameEnvironment && globalOptions.complianceLevel >= ClassFileConstants.JDK9;
	this.resolutionListeners = new IQualifiedTypeResolutionListener[0];
}

/** Construct a specific LookupEnvironment, corresponding to the given module. */
LookupEnvironment(LookupEnvironment rootEnv, ModuleBinding module) {
	this.root = rootEnv;
	this.UnNamedModule = rootEnv.UnNamedModule;
	this.module = module;
	this.typeRequestor = rootEnv.typeRequestor;
	this.globalOptions = rootEnv.globalOptions;
	this.problemReporter = rootEnv.problemReporter;
	this.defaultPackage = new PackageBinding(this); // assume the default package always exists
	this.defaultImports = null;
	this.nameEnvironment = rootEnv.nameEnvironment;
	this.knownPackages = new HashtableOfPackage();
	this.uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(3);
	this.uniquePolymorphicMethodBindings = new SimpleLookupTable(3);
	this.missingTypes = null;
	this.accessRestrictions = new HashMap(3);
	this.classFilePool = rootEnv.classFilePool;
	this.typesBeingConnected = rootEnv.typesBeingConnected;
	this.deferredEnumMethods = rootEnv.deferredEnumMethods;
	this.typeSystem = rootEnv.typeSystem;
	// knownModules is unused in specific LookupEnvironments
	this.useModuleSystem = rootEnv.useModuleSystem;
}

// NOTE: only for resolving!
public ModuleBinding getModule(char[] name) {
	if (this.root != this)
		return this.root.getModule(name);
	if (name == null || name == ModuleBinding.UNNAMED || CharOperation.equals(name, ModuleBinding.ALL_UNNAMED))
		return this.UnNamedModule;
	ModuleBinding moduleBinding = this.knownModules.get(name);
	if (moduleBinding == null) {
		if (this.useModuleSystem) {
			IModule mod = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModule(name);
			if (mod != null) {
				this.typeRequestor.accept(mod, this);
				moduleBinding = this.root.knownModules.get(name);
			}
		} else 
			return this.UnNamedModule;
	}
	return moduleBinding;
}

/**
 * Ask the name environment for a type which corresponds to the compoundName.
 * Answer null if the name cannot be found.
 */

public ReferenceBinding askForType(char[][] compoundName, /*@NonNull*/ModuleBinding clientModule) {
	assert clientModule != null : "lookup needs a module"; //$NON-NLS-1$
	NameEnvironmentAnswer[] answers = null;
	if (this.useModuleSystem) {
		IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.nameEnvironment;
		answers = askForTypeFromModules(clientModule, clientModule.getAllRequiredModules(),
				mod -> moduleEnv.findType(compoundName, mod.nameForLookup()));
	} else {
		NameEnvironmentAnswer answer = this.nameEnvironment.findType(compoundName);
		if (answer != null) {
			answer.moduleBinding = this.module;
			answers = new NameEnvironmentAnswer[] { answer };
		}
	}
	if (answers == null)
		return null;

	ReferenceBinding candidate = null;
	for (NameEnvironmentAnswer answer : answers) {
		if (answer == null) continue;

		ModuleBinding answerModule = answer.moduleBinding != null ? answer.moduleBinding : this.UnNamedModule;
	
		if (answer.isBinaryType()) {
			// the type was found as a .class file
			PackageBinding pkg = answerModule.environment.computePackageFrom(compoundName, false /* valid pkg */);
			this.typeRequestor.accept(answer.getBinaryType(), pkg, answer.getAccessRestriction());
			ReferenceBinding binding = pkg.getType0(compoundName[compoundName.length - 1]);
			if (binding instanceof BinaryTypeBinding) {
				((BinaryTypeBinding) binding).module = answerModule;
				if (pkg.enclosingModule == null)
					pkg.enclosingModule = answerModule;
			}
		} else if (answer.isCompilationUnit()) {
			// the type was found as a .java file, try to build it then search the cache
			this.typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction());
		} else if (answer.isSourceType()) {
			// the type was found as a source model
			PackageBinding pkg = answerModule.environment.computePackageFrom(compoundName, false /* valid pkg */);
			this.typeRequestor.accept(answer.getSourceTypes(), pkg, answer.getAccessRestriction());
			ReferenceBinding binding = pkg.getType0(compoundName[compoundName.length - 1]);
			if (binding instanceof SourceTypeBinding) {
				((SourceTypeBinding) binding).module = answerModule;
				if (pkg.enclosingModule == null)
					pkg.enclosingModule = answerModule;
			}
		}
		candidate = combine(candidate, answerModule.environment.getCachedType(compoundName), clientModule);
	}
	return candidate;
}

/* Ask the oracle for a type named name in the packageBinding.
* Answer null if the name cannot be found.
*/
ReferenceBinding askForType(PackageBinding packageBinding, char[] name, ModuleBinding clientModule) {
	assert clientModule != null : "lookup needs a module"; //$NON-NLS-1$
	if (packageBinding == null) {
		packageBinding = this.defaultPackage;
	}
	NameEnvironmentAnswer[] answers = null;
	if (this.useModuleSystem) {
		IModuleAwareNameEnvironment moduleEnv = (IModuleAwareNameEnvironment) this.nameEnvironment;
		final PackageBinding pack = packageBinding;
		// leverage module information from the (split?) package as to prefer NotAccessible over NotFound:
		answers = askForTypeFromModules(null, packageBinding.getDeclaringModules(),
				mod -> fromSplitPackageOrOracle(moduleEnv, mod, pack, name));
	} else {
		NameEnvironmentAnswer answer = this.nameEnvironment.findType(name, packageBinding.compoundName);
		if (answer != null) {
			answer.moduleBinding = this.module;
			answers = new NameEnvironmentAnswer[] { answer };
		}
	}
	if (answers == null)
		return null;

	ReferenceBinding candidate = null;
	for (NameEnvironmentAnswer answer : answers) {
		if (answer == null) continue;
		if (candidate != null && candidate.problemId() == ProblemReasons.Ambiguous)
			return candidate; // saw enough
		ModuleBinding answerModule = answer.moduleBinding != null ? answer.moduleBinding : this.UnNamedModule;
		PackageBinding answerPackage = packageBinding;
		
		if (answerModule != null) {
			if (!answerPackage.isDeclaredIn(answerModule))
				continue; // this answer is not reachable via the packageBinding
			if (answerPackage instanceof SplitPackageBinding)
				answerPackage = ((SplitPackageBinding) answerPackage).getIncarnation(answerModule);
		}
		if (answer.isResolvedBinding()) {
			candidate = combine(candidate, answer.getResolvedBinding(), clientModule);
			continue;
		} else if (answer.isBinaryType()) {
			// the type was found as a .class file
			this.typeRequestor.accept(answer.getBinaryType(), answerPackage, answer.getAccessRestriction());
			ReferenceBinding binding = answerPackage.getType0(name);
			if (binding instanceof BinaryTypeBinding) {
				((BinaryTypeBinding) binding).module = answerModule;
			}
		} else if (answer.isCompilationUnit()) {
			// the type was found as a .java file, try to build it then search the cache
			try {
				this.typeRequestor.accept(answer.getCompilationUnit(), answer.getAccessRestriction());
			} catch (AbortCompilation abort) {
				if (CharOperation.equals(name, TypeConstants.PACKAGE_INFO_NAME))
					return null; // silently, requestor may not be able to handle compilation units (HierarchyResolver)
				throw abort;
			}
		} else if (answer.isSourceType()) {
			// the type was found as a source model
			this.typeRequestor.accept(answer.getSourceTypes(), answerPackage, answer.getAccessRestriction());
			ReferenceBinding binding = answerPackage.getType0(name);
			if (binding instanceof SourceTypeBinding) {
				((SourceTypeBinding) binding).module = answerModule;
			}
			String externalAnnotationPath = answer.getExternalAnnotationPath();
			if (externalAnnotationPath != null && this.globalOptions.isAnnotationBasedNullAnalysisEnabled && binding instanceof SourceTypeBinding) {
				ExternalAnnotationSuperimposer.apply((SourceTypeBinding) binding, externalAnnotationPath);
			}
			candidate = combine(candidate, binding, clientModule);
			continue;
		}
		candidate = combine(candidate, answerPackage.getType0(name), clientModule);
	}
	return candidate;
}
/** Combine up-to two candidate types. If both types are present let accessibility from the given clientModule decide. */
private ReferenceBinding combine(ReferenceBinding one, ReferenceBinding two, ModuleBinding clientModule) {
	if (one == null) return two;
	if (two == null) return one;
	if (!clientModule.canAccess(one.fPackage)) return two;
	if (!clientModule.canAccess(two.fPackage)) return one;
	if (one == two) return one; //$IDENTITY-COMPARISON$
	return new ProblemReferenceBinding(one.compoundName, one, ProblemReasons.Ambiguous); // TODO(SHMOD): use a new problem ID
}
/** Collect answers from the oracle concerning the given clientModule (if present) and each of a set of other modules. */
private NameEnvironmentAnswer[] askForTypeFromModules(ModuleBinding clientModule, ModuleBinding[] otherModules,
		Function<ModuleBinding,NameEnvironmentAnswer> oracle)
{
	if (clientModule != null && clientModule.nameForLookup().length == 0) {
		NameEnvironmentAnswer answer = oracle.apply(clientModule);
		if (answer != null)
			answer.moduleBinding = this.root.getModuleFromAnswer(answer);
		return new NameEnvironmentAnswer[] { answer };
	} else {
		boolean found = false;
		NameEnvironmentAnswer[] answers = null;
		if (clientModule != null) {
			answers = new NameEnvironmentAnswer[otherModules.length+1];
			NameEnvironmentAnswer answer = oracle.apply(clientModule);
			if (answer != null) {
				answer.moduleBinding = clientModule;
				answers[answers.length-1] = answer;
				found = true;
			}
		} else {
			answers = new NameEnvironmentAnswer[otherModules.length];
		}
		for (int i = 0; i < otherModules.length; i++) {
			NameEnvironmentAnswer answer = oracle.apply(otherModules[i]);
			if (answer != null) {
				char[] nameFromAnswer = answer.moduleName();
				if (nameFromAnswer == null || CharOperation.equals(nameFromAnswer, otherModules[i].moduleName)) {
					answer.moduleBinding = otherModules[i];
				} else {
					answer.moduleBinding = getModule(nameFromAnswer);
				}
				answers[i] = answer;
				found = true;
			}
		}
		return found ? answers : null;
	}
}
/** First check for a known type in a split package and otherwise ask the oracle. */
private static NameEnvironmentAnswer fromSplitPackageOrOracle(IModuleAwareNameEnvironment moduleEnv, ModuleBinding module,
		PackageBinding packageBinding, char[] name)
{
	if (packageBinding instanceof SplitPackageBinding) {
		// when asking a split package getType0() we may have answered null in case of ambiguity (not knowing the module context).
		// now check if the module-incarnation of the package has the type:
		// (needed because the moduleEnv will not answer initial types).
		ReferenceBinding binding = ((SplitPackageBinding) packageBinding).getType0ForModule(module, name);
		if (binding != null && binding.isValidBinding()) {
			if (binding instanceof UnresolvedReferenceBinding)
				binding = ((UnresolvedReferenceBinding) binding).resolve(module.environment, false);
			if (binding.isValidBinding())
				return new NameEnvironmentAnswer(binding, module);
		}
	}
	return moduleEnv.findType(name, packageBinding.compoundName, module.nameForLookup());
}
private ModuleBinding getModuleFromAnswer(NameEnvironmentAnswer answer) {
	char[] moduleName = answer.moduleName();
	if (moduleName != null) {
		ModuleBinding moduleBinding;
		if (!this.useModuleSystem || moduleName == ModuleBinding.UNNAMED) {
			moduleBinding = this.UnNamedModule;
		} else { 
			moduleBinding = this.knownModules.get(moduleName);
			if (moduleBinding == null && this.nameEnvironment instanceof IModuleAwareNameEnvironment) {
				IModule iModule = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModule(moduleName);
				try {
					this.typeRequestor.accept(iModule, this);
					moduleBinding = this.knownModules.get(moduleName);
				} catch (NullPointerException e) {
					System.err.println("Bug 529367: moduleName: " + new String(moduleName) + "iModule null" +  //$NON-NLS-1$ //$NON-NLS-2$
							(iModule == null ? "true" : "false")); //$NON-NLS-1$ //$NON-NLS-2$]
					throw e;
				}
			}
		}
		return moduleBinding;
	}
	return null;
}

public boolean canTypeBeAccessed(SourceTypeBinding binding, Scope scope) {
	ModuleBinding client = scope.module();
	return client.canAccess(binding.fPackage);
}

/* Create the initial type bindings for the compilation unit.
*
* See completeTypeBindings() for a description of the remaining steps
*
* NOTE: This method can be called multiple times as additional source files are needed
*/
public void buildTypeBindings(CompilationUnitDeclaration unit, AccessRestriction accessRestriction) {
	CompilationUnitScope scope;
	ModuleBinding unitModule = null;
	if (unit.moduleDeclaration != null) {
		char[] moduleName = unit.moduleDeclaration.moduleName;
		scope = new CompilationUnitScope(unit, this.globalOptions);
		unitModule = unit.moduleDeclaration.setBinding(new SourceModuleBinding(moduleName, scope, this.root));
	} else {
		unitModule = unit.module(this);
		scope = new CompilationUnitScope(unit, unitModule != null ? unitModule.environment : this);
	}
	scope.buildTypeBindings(accessRestriction);
	LookupEnvironment rootEnv = this.root;
	int unitsLength = rootEnv.units.length;
	if (++rootEnv.lastUnitIndex >= unitsLength)
		System.arraycopy(rootEnv.units, 0, rootEnv.units = new CompilationUnitDeclaration[2 * unitsLength], 0, unitsLength);
	rootEnv.units[rootEnv.lastUnitIndex] = unit;
}

/* Cache the binary type since we know it is needed during this compile.
*
* Answer the created BinaryTypeBinding or null if the type is already in the cache.
*/
public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, AccessRestriction accessRestriction) {
	return cacheBinaryType(binaryType, true, accessRestriction);
}

/* Cache the binary type since we know it is needed during this compile.
*
* Answer the created BinaryTypeBinding or null if the type is already in the cache.
*/
public BinaryTypeBinding cacheBinaryType(IBinaryType binaryType, boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
	char[][] compoundName = CharOperation.splitOn('/', binaryType.getName());
	ReferenceBinding existingType = getCachedType(compoundName);

	if (existingType == null || existingType instanceof UnresolvedReferenceBinding)
		// only add the binary type if its not already in the cache
		return createBinaryTypeFrom(binaryType, computePackageFrom(compoundName, false /* valid pkg */), needFieldsAndMethods, accessRestriction);
	return null; // the type already exists & can be retrieved from the cache
}

public void completeTypeBindings() {
	if (this != this.root) {
		this.root.completeTypeBindings();
		return;
	}
	this.stepCompleted = BUILD_TYPE_HIERARCHY;

	for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
	    (this.unitBeingCompleted = this.units[i]).scope.checkAndSetImports();
	}
	this.stepCompleted = CHECK_AND_SET_IMPORTS;

	for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
	    (this.unitBeingCompleted = this.units[i]).scope.connectTypeHierarchy();
	}
	this.stepCompleted = CONNECT_TYPE_HIERARCHY;

	for (int i = this.lastCompletedUnitIndex + 1; i <= this.lastUnitIndex; i++) {
		CompilationUnitScope unitScope = (this.unitBeingCompleted = this.units[i]).scope;
		unitScope.checkParameterizedTypes();
		unitScope.buildFieldsAndMethods();
		this.units[i] = null; // release unnecessary reference to the parsed unit
	}
	this.stepCompleted = BUILD_FIELDS_AND_METHODS;
	this.lastCompletedUnitIndex = this.lastUnitIndex;
	this.unitBeingCompleted = null;
}

/*
* 1. Connect the type hierarchy for the type bindings created for parsedUnits.
* 2. Create the field bindings
* 3. Create the method bindings
*/

/* We know each known compilationUnit is free of errors at this point...
*
* Each step will create additional bindings unless a problem is detected, in which
* case either the faulty import/superinterface/field/method will be skipped or a
* suitable replacement will be substituted (such as Object for a missing superclass)
*/
public void completeTypeBindings(CompilationUnitDeclaration parsedUnit) {
	if (this != this.root) {
		this.root.completeTypeBindings(parsedUnit);
		return;
	}
	if (this.stepCompleted == BUILD_FIELDS_AND_METHODS) {
		// This can only happen because the original set of units are completely built and
		// are now being processed, so we want to treat all the additional units as a group
		// until they too are completely processed.
		completeTypeBindings();
	} else {
		if (parsedUnit.scope == null) return; // parsing errors were too severe

		if (this.stepCompleted >= CHECK_AND_SET_IMPORTS)
			(this.unitBeingCompleted = parsedUnit).scope.checkAndSetImports();

		if (this.stepCompleted >= CONNECT_TYPE_HIERARCHY)
			(this.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy();

		this.unitBeingCompleted = null;
	}
}

/*
* Used by other compiler tools which do not start by calling completeTypeBindings().
*
* 1. Connect the type hierarchy for the type bindings created for parsedUnits.
* 2. Create the field bindings
* 3. Create the method bindings
*/

/*
* Each step will create additional bindings unless a problem is detected, in which
* case either the faulty import/superinterface/field/method will be skipped or a
* suitable replacement will be substituted (such as Object for a missing superclass)
*/
public void completeTypeBindings(CompilationUnitDeclaration parsedUnit, boolean buildFieldsAndMethods) {
	if (parsedUnit.scope == null) return; // parsing errors were too severe
	LookupEnvironment rootEnv = this.root;
	(rootEnv.unitBeingCompleted = parsedUnit).scope.checkAndSetImports();
	parsedUnit.scope.connectTypeHierarchy();
	parsedUnit.scope.checkParameterizedTypes();
	if (buildFieldsAndMethods)
		parsedUnit.scope.buildFieldsAndMethods();
	rootEnv.unitBeingCompleted = null;
}

/*
* Used by other compiler tools which do not start by calling completeTypeBindings()
* and have more than 1 unit to complete.
*
* 1. Connect the type hierarchy for the type bindings created for parsedUnits.
* 2. Create the field bindings
* 3. Create the method bindings
*/
public void completeTypeBindings(CompilationUnitDeclaration[] parsedUnits, boolean[] buildFieldsAndMethods, int unitCount) {
	LookupEnvironment rootEnv = this.root;
	for (int i = 0; i < unitCount; i++) {
		CompilationUnitDeclaration parsedUnit = parsedUnits[i];
		if (parsedUnit.scope != null)
			(rootEnv.unitBeingCompleted = parsedUnit).scope.checkAndSetImports();
	}

	for (int i = 0; i < unitCount; i++) {
		CompilationUnitDeclaration parsedUnit = parsedUnits[i];
		if (parsedUnit.scope != null)
			(rootEnv.unitBeingCompleted = parsedUnit).scope.connectTypeHierarchy();
	}

	for (int i = 0; i < unitCount; i++) {
		CompilationUnitDeclaration parsedUnit = parsedUnits[i];
		if (parsedUnit.scope != null) {
			(rootEnv.unitBeingCompleted = parsedUnit).scope.checkParameterizedTypes();
			if (buildFieldsAndMethods[i])
				parsedUnit.scope.buildFieldsAndMethods();
		}
	}

	rootEnv.unitBeingCompleted = null;
}
public TypeBinding computeBoxingType(TypeBinding type) {
	TypeBinding boxedType;
	switch (type.id) {
		case TypeIds.T_JavaLangBoolean :
			return TypeBinding.BOOLEAN;
		case TypeIds.T_JavaLangByte :
			return TypeBinding.BYTE;
		case TypeIds.T_JavaLangCharacter :
			return TypeBinding.CHAR;
		case TypeIds.T_JavaLangShort :
			return TypeBinding.SHORT;
		case TypeIds.T_JavaLangDouble :
			return TypeBinding.DOUBLE;
		case TypeIds.T_JavaLangFloat :
			return TypeBinding.FLOAT;
		case TypeIds.T_JavaLangInteger :
			return TypeBinding.INT;
		case TypeIds.T_JavaLangLong :
			return TypeBinding.LONG;

		case TypeIds.T_int :
			boxedType = getType(JAVA_LANG_INTEGER, javaBaseModule());
			if (boxedType != null) return boxedType;
			return new ProblemReferenceBinding(JAVA_LANG_INTEGER, null, NotFound);
		case TypeIds.T_byte :
			boxedType = getType(JAVA_LANG_BYTE, javaBaseModule());
			if (boxedType != null) return boxedType;
			return new ProblemReferenceBinding(JAVA_LANG_BYTE, null, NotFound);
		case TypeIds.T_short :
			boxedType = getType(JAVA_LANG_SHORT, javaBaseModule());
			if (boxedType != null) return boxedType;
			return new ProblemReferenceBinding(JAVA_LANG_SHORT, null, NotFound);
		case TypeIds.T_char :
			boxedType = getType(JAVA_LANG_CHARACTER, javaBaseModule());
			if (boxedType != null) return boxedType;
			return new ProblemReferenceBinding(JAVA_LANG_CHARACTER, null, NotFound);
		case TypeIds.T_long :
			boxedType = getType(JAVA_LANG_LONG, javaBaseModule());
			if (boxedType != null) return boxedType;
			return new ProblemReferenceBinding(JAVA_LANG_LONG, null, NotFound);
		case TypeIds.T_float :
			boxedType = getType(JAVA_LANG_FLOAT, javaBaseModule());
			if (boxedType != null) return boxedType;
			return new ProblemReferenceBinding(JAVA_LANG_FLOAT, null, NotFound);
		case TypeIds.T_double :
			boxedType = getType(JAVA_LANG_DOUBLE, javaBaseModule());
			if (boxedType != null) return boxedType;
			return new ProblemReferenceBinding(JAVA_LANG_DOUBLE, null, NotFound);
		case TypeIds.T_boolean :
			boxedType = getType(JAVA_LANG_BOOLEAN, javaBaseModule());
			if (boxedType != null) return boxedType;
			return new ProblemReferenceBinding(JAVA_LANG_BOOLEAN, null, NotFound);
//		case TypeIds.T_int :
//			return getResolvedType(JAVA_LANG_INTEGER, null);
//		case TypeIds.T_byte :
//			return getResolvedType(JAVA_LANG_BYTE, null);
//		case TypeIds.T_short :
//			return getResolvedType(JAVA_LANG_SHORT, null);
//		case TypeIds.T_char :
//			return getResolvedType(JAVA_LANG_CHARACTER, null);
//		case TypeIds.T_long :
//			return getResolvedType(JAVA_LANG_LONG, null);
//		case TypeIds.T_float :
//			return getResolvedType(JAVA_LANG_FLOAT, null);
//		case TypeIds.T_double :
//			return getResolvedType(JAVA_LANG_DOUBLE, null);
//		case TypeIds.T_boolean :
//			return getResolvedType(JAVA_LANG_BOOLEAN, null);
	}
	// allow indirect unboxing conversion for wildcards and type parameters
	switch (type.kind()) {
		case Binding.WILDCARD_TYPE :
		case Binding.INTERSECTION_TYPE :
		case Binding.TYPE_PARAMETER :
		case Binding.INTERSECTION_TYPE18:
			switch (type.erasure().id) {
				case TypeIds.T_JavaLangBoolean :
					return TypeBinding.BOOLEAN;
				case TypeIds.T_JavaLangByte :
					return TypeBinding.BYTE;
				case TypeIds.T_JavaLangCharacter :
					return TypeBinding.CHAR;
				case TypeIds.T_JavaLangShort :
					return TypeBinding.SHORT;
				case TypeIds.T_JavaLangDouble :
					return TypeBinding.DOUBLE;
				case TypeIds.T_JavaLangFloat :
					return TypeBinding.FLOAT;
				case TypeIds.T_JavaLangInteger :
					return TypeBinding.INT;
				case TypeIds.T_JavaLangLong :
					return TypeBinding.LONG;
			}
			break;
		case Binding.POLY_TYPE:
			return ((PolyTypeBinding) type).computeBoxingType();
	}
	return type;
}

public ModuleBinding javaBaseModule() {
	if (this.JavaBaseModule != null)
		return this.JavaBaseModule;
	if (this.root != this)
		return this.JavaBaseModule = this.root.javaBaseModule();
	ModuleBinding resolvedModel = null;
	if (this.useModuleSystem)
		resolvedModel = getModule(TypeConstants.JAVA_BASE);
	return this.JavaBaseModule = (resolvedModel != null ? resolvedModel : this.UnNamedModule); // fall back to pre-Jigsaw view
}

private PackageBinding computePackageFrom(char[][] constantPoolName, boolean isMissing) {
	if (constantPoolName.length == 1)
		return this.defaultPackage;

	PackageBinding packageBinding = getPackage0(constantPoolName[0]);
	if (packageBinding == null || packageBinding == TheNotFoundPackage) {
		if (this.useModuleSystem) {
			if (this.module.isUnnamed()) {
				char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getUniqueModulesDeclaringPackage(null, constantPoolName[0], ModuleBinding.ANY);
				if (declaringModules != null) {
					for (char[] mod : declaringModules) {
						ModuleBinding declaringModule = this.root.getModule(mod);
						if (declaringModule != null)
							packageBinding = SplitPackageBinding.combine(declaringModule.getTopLevelPackage(constantPoolName[0]), packageBinding, this.module);
					}
				}
			} else {
				packageBinding = this.module.getTopLevelPackage(constantPoolName[0]);
			}
		}
		if (packageBinding == null || packageBinding == TheNotFoundPackage) {
			packageBinding = new PackageBinding(constantPoolName[0], this, this.module);
		}
		if (isMissing) packageBinding.tagBits |= TagBits.HasMissingType;
		this.knownPackages.put(constantPoolName[0], packageBinding); // TODO: split?
	}

	for (int i = 1, length = constantPoolName.length - 1; i < length; i++) {
		PackageBinding parent = packageBinding;
		if ((packageBinding = parent.getPackage0(constantPoolName[i])) == null || packageBinding == TheNotFoundPackage) {
			if (this.useModuleSystem) {
				if (this.module.isUnnamed()) {
					char[][] declaringModules = ((IModuleAwareNameEnvironment) this.nameEnvironment).getModulesDeclaringPackage(parent.compoundName, constantPoolName[i], ModuleBinding.ANY);
					if (declaringModules != null) {
						for (char[] mod : declaringModules) {
							ModuleBinding declaringModule = this.root.getModule(mod);
							if (declaringModule != null)
								packageBinding = SplitPackageBinding.combine(declaringModule.getPackage(parent.compoundName, constantPoolName[i]), packageBinding, this.module);
						}
					}
				} else {
					packageBinding = this.module.getVisiblePackage(parent, constantPoolName[i], true);
				}
			}
			if (packageBinding == null || packageBinding == TheNotFoundPackage) {
				packageBinding = new PackageBinding(CharOperation.subarray(constantPoolName, 0, i + 1), parent, this, this.module);
			}
			if (isMissing) {
				packageBinding.tagBits |= TagBits.HasMissingType;
			}
			packageBinding = parent.addPackage(packageBinding, this.module);
		}
	}
	if (packageBinding instanceof SplitPackageBinding) {
		PackageBinding candidate = null;
		// select from incarnations the unique package containing CUs, if any:
		for (PackageBinding incarnation : ((SplitPackageBinding) packageBinding).incarnations) {
			if (incarnation.hasCompilationUnit(false)) {
				if (candidate != null) {
					candidate = null;
					break; // likely to report "accessible from more than one module" downstream 
				}
				candidate = incarnation;
			}
		}
		if (candidate != null)
			return candidate;
	}
	return packageBinding;
}

/**
 * Convert a given source type into a parameterized form if generic.
 * generic X<E> --> param X<E>
 */
public ReferenceBinding convertToParameterizedType(ReferenceBinding originalType) {
	if (originalType != null) {
		boolean isGeneric = originalType.isGenericType();
		if (!isGeneric && !originalType.hasEnclosingInstanceContext())
			return originalType;
		ReferenceBinding originalEnclosingType = originalType.enclosingType();
		ReferenceBinding convertedEnclosingType = originalEnclosingType;
		boolean needToConvert = isGeneric;
		if (originalEnclosingType != null && originalType.hasEnclosingInstanceContext()) {
			convertedEnclosingType = convertToParameterizedType(originalEnclosingType);
			needToConvert |= TypeBinding.notEquals(originalEnclosingType, convertedEnclosingType);
		}
		if (needToConvert) {
			return createParameterizedType(originalType, isGeneric ? originalType.typeVariables() : null, convertedEnclosingType);
		}
	}
	return originalType;
}
/**
 * Returns the given binding's raw type binding.
 * @param type the TypeBinding to raw convert
 * @param forceRawEnclosingType forces recursive raw conversion of enclosing types (used in Javadoc references only)
 * @return TypeBinding the raw converted TypeBinding
 */
public TypeBinding convertToRawType(TypeBinding type, boolean forceRawEnclosingType) {
	int dimension;
	TypeBinding originalType;
	switch(type.kind()) {
		case Binding.BASE_TYPE :
		case Binding.TYPE_PARAMETER:
		case Binding.WILDCARD_TYPE:
		case Binding.INTERSECTION_TYPE:
		case Binding.RAW_TYPE:
			return type;
		case Binding.ARRAY_TYPE:
			dimension = type.dimensions();
			originalType = type.leafComponentType();
			break;
		default:
			if (type.id == TypeIds.T_JavaLangObject)
				return type; // Object is not generic
			dimension = 0;
			originalType = type;
	}
	boolean needToConvert;
	switch (originalType.kind()) {
		case Binding.BASE_TYPE :
			return type;
		case Binding.GENERIC_TYPE :
			needToConvert = true;
			break;
		case Binding.PARAMETERIZED_TYPE :
			ParameterizedTypeBinding paramType = (ParameterizedTypeBinding) originalType;
			needToConvert = paramType.genericType().isGenericType(); // only recursive call to enclosing type can find parameterizedType with arguments
			break;
		default :
			needToConvert = false;
			break;
	}
	forceRawEnclosingType &= !originalType.isStatic();
	ReferenceBinding originalEnclosing = originalType.enclosingType();
	TypeBinding convertedType;
	if (originalEnclosing == null) {
		convertedType = needToConvert ? createRawType((ReferenceBinding)originalType.erasure(), null) : originalType;
	} else {
		ReferenceBinding convertedEnclosing;
		if (!((ReferenceBinding)originalType).hasEnclosingInstanceContext()) {
			convertedEnclosing = (ReferenceBinding) originalEnclosing.original();
		} else {
			if (originalEnclosing.kind() == Binding.RAW_TYPE) {			
				convertedEnclosing = originalEnclosing;
				needToConvert = true;
			} else if (forceRawEnclosingType && !needToConvert/*stop recursion when conversion occurs*/) {
				convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing, forceRawEnclosingType);
				needToConvert = TypeBinding.notEquals(originalEnclosing, convertedEnclosing); // only convert generic or parameterized types
			} else if (needToConvert) {
				convertedEnclosing = (ReferenceBinding) convertToRawType(originalEnclosing, false);
			} else {
				convertedEnclosing = convertToParameterizedType(originalEnclosing);
			}
		}
		if (needToConvert) {
			convertedType = createRawType((ReferenceBinding) originalType.erasure(), convertedEnclosing);
		} else if (TypeBinding.notEquals(originalEnclosing, convertedEnclosing)) {
			convertedType = createParameterizedType((ReferenceBinding) originalType.erasure(), null, convertedEnclosing);
		} else {
			convertedType = originalType;
		}
	}
	if (TypeBinding.notEquals(originalType, convertedType)) {
		return dimension > 0 ? (TypeBinding)createArrayType(convertedType, dimension) : convertedType;
	}
	return type;
}

/**
 * Convert an array of types in raw forms.
 * Only allocate an array if anything is different.
 */
public ReferenceBinding[] convertToRawTypes(ReferenceBinding[] originalTypes, boolean forceErasure, boolean forceRawEnclosingType) {
	if (originalTypes == null) return null;
    ReferenceBinding[] convertedTypes = originalTypes;
    for (int i = 0, length = originalTypes.length; i < length; i++) {
        ReferenceBinding originalType = originalTypes[i];
        ReferenceBinding convertedType = (ReferenceBinding) convertToRawType(forceErasure ? originalType.erasure() : originalType, forceRawEnclosingType);
        if (TypeBinding.notEquals(convertedType, originalType)) {        
            if (convertedTypes == originalTypes) {
                System.arraycopy(originalTypes, 0, convertedTypes = new ReferenceBinding[length], 0, i);
            }
            convertedTypes[i] = convertedType;
        } else if (convertedTypes != originalTypes) {
            convertedTypes[i] = originalType;
        }
    }
    return convertedTypes;
}

// variation for unresolved types in binaries (consider generic type as raw)
public TypeBinding convertUnresolvedBinaryToRawType(TypeBinding type) {
	int dimension;
	TypeBinding originalType;
	switch(type.kind()) {
		case Binding.BASE_TYPE :
		case Binding.TYPE_PARAMETER:
		case Binding.WILDCARD_TYPE:
		case Binding.INTERSECTION_TYPE:
		case Binding.RAW_TYPE:
			return type;
		case Binding.ARRAY_TYPE:
			dimension = type.dimensions();
			originalType = type.leafComponentType();
			break;
		default:
			if (type.id == TypeIds.T_JavaLangObject)
				return type; // Object is not generic
			dimension = 0;
			originalType = type;
	}
	boolean needToConvert;
	switch (originalType.kind()) {
		case Binding.BASE_TYPE :
			return type;
		case Binding.GENERIC_TYPE :
			needToConvert = true;
			break;
		case Binding.PARAMETERIZED_TYPE :
			ParameterizedTypeBinding paramType = (ParameterizedTypeBinding) originalType;
			needToConvert = paramType.genericType().isGenericType(); // only recursive call to enclosing type can find parameterizedType with arguments
			break;
		default :
			needToConvert = false;
			break;
	}
	ReferenceBinding originalEnclosing = originalType.enclosingType();
	TypeBinding convertedType;
	if (originalEnclosing == null) {
		convertedType = needToConvert ? createRawType((ReferenceBinding)originalType.erasure(), null) : originalType;
	} else {
		if (!needToConvert && originalType.isStatic())
			return originalType;

		ReferenceBinding convertedEnclosing = (ReferenceBinding) convertUnresolvedBinaryToRawType(originalEnclosing);
		if (TypeBinding.notEquals(convertedEnclosing, originalEnclosing)) {
			needToConvert = true;
		}
		if (needToConvert) {
			convertedType = createRawType((ReferenceBinding) originalType.erasure(), convertedEnclosing);
		} else {
			convertedType = originalType;
		}
	}
	if (TypeBinding.notEquals(originalType, convertedType)) {
		return dimension > 0 ? (TypeBinding)createArrayType(convertedType, dimension) : convertedType;
	}
	return type;
}
/* Used to guarantee annotation identity: we do that only for marker annotations and others with all default values.
   We don't have the machinery for the general case as of now.
*/
public AnnotationBinding createAnnotation(ReferenceBinding annotationType, ElementValuePair[] pairs) {
	if (pairs.length != 0) {
		AnnotationBinding.setMethodBindings(annotationType, pairs);
		return new AnnotationBinding(annotationType, pairs);
	}
	return this.typeSystem.getAnnotationType(annotationType, true);
}

/* Used to guarantee annotation identity: we do that only for marker annotations and others with all default values.
   We don't have the machinery for the general case as of now.
*/
public AnnotationBinding createUnresolvedAnnotation(ReferenceBinding annotationType, ElementValuePair[] pairs) {
	if (pairs.length != 0) {
		return new UnresolvedAnnotationBinding(annotationType, pairs, this);
	}
	return this.typeSystem.getAnnotationType(annotationType, false);
}

/*
 *  Used to guarantee array type identity.
 */
public ArrayBinding createArrayType(TypeBinding leafComponentType, int dimensionCount) {
	return this.typeSystem.getArrayType(leafComponentType, dimensionCount);
}

public ArrayBinding createArrayType(TypeBinding leafComponentType, int dimensionCount, AnnotationBinding [] annotations) {
	return this.typeSystem.getArrayType(leafComponentType, dimensionCount, annotations);
}

public TypeBinding createIntersectionType18(ReferenceBinding[] intersectingTypes) {
	if (!intersectingTypes[0].isClass()) {
		Arrays.sort(intersectingTypes, new Comparator<TypeBinding>() {
			@Override
			public int compare(TypeBinding o1, TypeBinding o2) {
				//
				return o1.isClass() ? -1 : (o2.isClass() ? 1 : CharOperation.compareTo(o1.readableName(), o2.readableName()));
			}
		});
	}
	return this.typeSystem.getIntersectionType18(intersectingTypes);
}	

public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
	return createBinaryTypeFrom(binaryType, packageBinding, true, accessRestriction);
}

public BinaryTypeBinding createBinaryTypeFrom(IBinaryType binaryType, PackageBinding packageBinding, boolean needFieldsAndMethods, AccessRestriction accessRestriction) {
	if (this != packageBinding.environment)
		return packageBinding.environment.createBinaryTypeFrom(binaryType, packageBinding, needFieldsAndMethods, accessRestriction);
	BinaryTypeBinding binaryBinding = new BinaryTypeBinding(packageBinding, binaryType, this);

	// resolve any array bindings which reference the unresolvedType
	ReferenceBinding cachedType = packageBinding.getType0(binaryBinding.compoundName[binaryBinding.compoundName.length - 1]);
	if (cachedType != null && !cachedType.isUnresolvedType()) {
		if (cachedType.isBinaryBinding()) // sanity check... at this point the cache should ONLY contain unresolved types
			return (BinaryTypeBinding) cachedType;
		// it is possible with a large number of source files (exceeding AbstractImageBuilder.MAX_AT_ONCE) that a member type can be in the cache as an UnresolvedType,
		// but because its enclosingType is resolved while its created (call to BinaryTypeBinding constructor), its replaced with a source type
		return null;
	}
	packageBinding.addType(binaryBinding);
	setAccessRestriction(binaryBinding, accessRestriction);
	binaryBinding.cachePartsFrom(binaryType, needFieldsAndMethods);
	return binaryBinding;
}

/*
 * Used to create types denoting missing types.
 * If package is given, then reuse the package; if not then infer a package from compound name.
 * If the package is existing, then install the missing type in type cache
*/
public MissingTypeBinding createMissingType(PackageBinding packageBinding, char[][] compoundName) {
	// create a proxy for the missing BinaryType
	if (packageBinding == null) {
		packageBinding = computePackageFrom(compoundName, true /* missing */);
		if (packageBinding == TheNotFoundPackage) packageBinding = this.defaultPackage;
	}
	MissingTypeBinding missingType = new MissingTypeBinding(packageBinding, compoundName, this);
	if (missingType.id != TypeIds.T_JavaLangObject) {
		// make Object be its superclass - it could in turn be missing as well
		ReferenceBinding objectType = getType(TypeConstants.JAVA_LANG_OBJECT, javaBaseModule());
		if (objectType == null) {
			objectType = createMissingType(null, TypeConstants.JAVA_LANG_OBJECT);	// create a proxy for the missing Object type
		}
		missingType.setMissingSuperclass(objectType);
	}
	packageBinding.addType(missingType);
	if (this.missingTypes == null)
		this.missingTypes = new ArrayList(3);
	this.missingTypes.add(missingType);
	return missingType;
}

/*
 * 1. Connect the type hierarchy for the type bindings created for parsedUnits.
 * 2. Create the field bindings
 * 3. Create the method bindings
 */
public PackageBinding createPackage(char[][] compoundName) {
	PackageBinding packageBinding = getPackage0(compoundName[0]);
	if (packageBinding == null || packageBinding == TheNotFoundPackage) {
		packageBinding = new PackageBinding(compoundName[0], this, this.module);
		this.knownPackages.put(compoundName[0], packageBinding);
		if (this.module != null) {
			packageBinding = this.module.addPackage(packageBinding, true);
			this.knownPackages.put(compoundName[0], packageBinding); // update in case of split package
		}
	}

	for (int i = 1, length = compoundName.length; i < length; i++) {
		// check to see if it collides with a known type...
		// this case can only happen if the package does not exist as a directory in the file system
		// otherwise when the source type was defined, the correct error would have been reported
		// unless its an unresolved type which is referenced from an inconsistent class file
		// NOTE: empty packages are not packages according to changes in JLS v2, 7.4.3
		// so not all types cause collision errors when they're created even though the package did exist
		ReferenceBinding type = packageBinding.getType0(compoundName[i]);
		if (type != null && type != TheNotFoundType && !(type instanceof UnresolvedReferenceBinding))
			return null;

		PackageBinding parent = packageBinding;
		if ((packageBinding = parent.getPackage0(compoundName[i])) == null || packageBinding == TheNotFoundPackage) {
			// if the package is unknown, check to see if a type exists which would collide with the new package
			// catches the case of a package statement of: package java.lang.Object;
			// since the package can be added after a set of source files have already been compiled,
			// we need to check whenever a package is created
			if(this.nameEnvironment instanceof INameEnvironmentExtension) {
				//When the nameEnvironment is an instance of INameEnvironmentWithProgress, it can get avoided to search for secondaryTypes (see flag).
				// This is a performance optimization, because it is very expensive to search for secondary types and it isn't necessary to check when creating a package,
				// because package name can not collide with a secondary type name.
				if (((INameEnvironmentExtension)this.nameEnvironment).findType(compoundName[i], parent.compoundName, false, this.module.nameForLookup()) != null) {
					return null;
				}
			} else {
				if (this.nameEnvironment.findType(compoundName[i], parent.compoundName) != null) {
					return null;
				}
			}
			if (parent instanceof SplitPackageBinding) {
				// parent.getPackage0() may have been too shy, so drill into the split:
				PackageBinding singleParent = ((SplitPackageBinding) parent).getIncarnation(this.module);
				if (singleParent != null)
					packageBinding = singleParent.getPackage0(compoundName[i]);
			}
			if (packageBinding == null) {
				packageBinding = new PackageBinding(CharOperation.subarray(compoundName, 0, i + 1), parent, this, this.module);
				packageBinding = parent.addPackage(packageBinding, this.module);
			}
		}
	}
	if (packageBinding instanceof SplitPackageBinding)
		packageBinding = ((SplitPackageBinding) packageBinding).getIncarnation(this.module);
	return packageBinding;
}

public ParameterizedGenericMethodBinding createParameterizedGenericMethod(MethodBinding genericMethod, RawTypeBinding rawType) {
	// cached info is array of already created parameterized types for this type
	ParameterizedGenericMethodBinding[] cachedInfo = (ParameterizedGenericMethodBinding[])this.uniqueParameterizedGenericMethodBindings.get(genericMethod);
	boolean needToGrow = false;
	int index = 0;
	if (cachedInfo != null){
		nextCachedMethod :
			// iterate existing parameterized for reusing one with same type arguments if any
			for (int max = cachedInfo.length; index < max; index++){
				ParameterizedGenericMethodBinding cachedMethod = cachedInfo[index];
				if (cachedMethod == null) break nextCachedMethod;
				if (!cachedMethod.isRaw) continue nextCachedMethod;
				if (cachedMethod.declaringClass != (rawType == null ? genericMethod.declaringClass : rawType)) continue nextCachedMethod; //$IDENTITY-COMPARISON$
				return cachedMethod;
		}
		needToGrow = true;
	} else {
		cachedInfo = new ParameterizedGenericMethodBinding[5];
		this.uniqueParameterizedGenericMethodBindings.put(genericMethod, cachedInfo);
	}
	// grow cache ?
	int length = cachedInfo.length;
	if (needToGrow && index == length){
		System.arraycopy(cachedInfo, 0, cachedInfo = new ParameterizedGenericMethodBinding[length*2], 0, length);
		this.uniqueParameterizedGenericMethodBindings.put(genericMethod, cachedInfo);
	}
	// add new binding
	ParameterizedGenericMethodBinding parameterizedGenericMethod = new ParameterizedGenericMethodBinding(genericMethod, rawType, this);
	cachedInfo[index] = parameterizedGenericMethod;
	return parameterizedGenericMethod;
}

public ParameterizedGenericMethodBinding createParameterizedGenericMethod(MethodBinding genericMethod, TypeBinding[] typeArguments) {
	return createParameterizedGenericMethod(genericMethod, typeArguments, null);
}
public ParameterizedGenericMethodBinding createParameterizedGenericMethod(MethodBinding genericMethod, TypeBinding[] typeArguments, TypeBinding targetType) {
	return createParameterizedGenericMethod(genericMethod, typeArguments, false, false, targetType);
}
public ParameterizedGenericMethodBinding createParameterizedGenericMethod(MethodBinding genericMethod, TypeBinding[] typeArguments,
																			boolean inferredWithUncheckedConversion, boolean hasReturnProblem, TypeBinding targetType)
{
	// cached info is array of already created parameterized types for this type
	ParameterizedGenericMethodBinding[] cachedInfo = (ParameterizedGenericMethodBinding[])this.uniqueParameterizedGenericMethodBindings.get(genericMethod);
	int argLength = typeArguments == null ? 0: typeArguments.length;
	boolean needToGrow = false;
	int index = 0;
	if (cachedInfo != null){
		nextCachedMethod :
			// iterate existing parameterized for reusing one with same type arguments if any
			for (int max = cachedInfo.length; index < max; index++){
				ParameterizedGenericMethodBinding cachedMethod = cachedInfo[index];
				if (cachedMethod == null) break nextCachedMethod;
				if (cachedMethod.isRaw) continue nextCachedMethod;
				if (cachedMethod.targetType != targetType) continue nextCachedMethod; //$IDENTITY-COMPARISON$
				if (cachedMethod.inferredWithUncheckedConversion != inferredWithUncheckedConversion) continue nextCachedMethod;
				TypeBinding[] cachedArguments = cachedMethod.typeArguments;
				int cachedArgLength = cachedArguments == null ? 0 : cachedArguments.length;
				if (argLength != cachedArgLength) continue nextCachedMethod;
				for (int j = 0; j < cachedArgLength; j++){
					if (typeArguments[j] != cachedArguments[j]) continue nextCachedMethod; //$IDENTITY-COMPARISON$
				}
				if (inferredWithUncheckedConversion) { // JSL 18.5.2: "If unchecked conversion was necessary..."
					// don't tolerate remaining parameterized types / type variables, should have been eliminated by erasure:
					if (cachedMethod.returnType.isParameterizedType() || cachedMethod.returnType.isTypeVariable()) continue;
					for (TypeBinding exc : cachedMethod.thrownExceptions)
						if (exc.isParameterizedType() || exc.isTypeVariable()) continue nextCachedMethod;
				}
				// all arguments match, reuse current
				return cachedMethod;
		}
		needToGrow = true;
	} else {
		cachedInfo = new ParameterizedGenericMethodBinding[5];
		this.uniqueParameterizedGenericMethodBindings.put(genericMethod, cachedInfo);
	}
	// grow cache ?
	int length = cachedInfo.length;
	if (needToGrow && index == length){
		System.arraycopy(cachedInfo, 0, cachedInfo = new ParameterizedGenericMethodBinding[length*2], 0, length);
		this.uniqueParameterizedGenericMethodBindings.put(genericMethod, cachedInfo);
	}
	// add new binding
	ParameterizedGenericMethodBinding parameterizedGenericMethod =
			new ParameterizedGenericMethodBinding(genericMethod, typeArguments, this, inferredWithUncheckedConversion, hasReturnProblem, targetType);
	cachedInfo[index] = parameterizedGenericMethod;
	return parameterizedGenericMethod;
}
public PolymorphicMethodBinding createPolymorphicMethod(MethodBinding originalPolymorphicMethod, TypeBinding[] parameters, Scope scope) {
	// cached info is array of already created polymorphic methods for this type
	String key = new String(originalPolymorphicMethod.selector);
	PolymorphicMethodBinding[] cachedInfo = (PolymorphicMethodBinding[]) this.uniquePolymorphicMethodBindings.get(key);
	int parametersLength = parameters == null ? 0: parameters.length;
	TypeBinding[] parametersTypeBinding = new TypeBinding[parametersLength]; 
	for (int i = 0; i < parametersLength; i++) {
		TypeBinding parameterTypeBinding = parameters[i];
		if (parameterTypeBinding.id == TypeIds.T_null) {
			parametersTypeBinding[i] = getType(JAVA_LANG_VOID, javaBaseModule());
		} else {
			if (parameterTypeBinding.isPolyType()) {
				PolyTypeBinding ptb = (PolyTypeBinding) parameterTypeBinding;
				if (scope instanceof BlockScope && ptb.expression.resolvedType == null) {
					ptb.expression.setExpectedType(scope.getJavaLangObject());
					parametersTypeBinding[i] = ptb.expression.resolveType((BlockScope) scope);
				} else {
					parametersTypeBinding[i] = ptb.expression.resolvedType;
				}
			} else {
				parametersTypeBinding[i] = parameterTypeBinding.erasure();
			}
		}
	}
	boolean needToGrow = false;
	int index = 0;
	if (cachedInfo != null) {
		nextCachedMethod :
			// iterate existing polymorphic method for reusing one with same type arguments if any
			for (int max = cachedInfo.length; index < max; index++) {
				PolymorphicMethodBinding cachedMethod = cachedInfo[index];
				if (cachedMethod == null) {
					break nextCachedMethod;
				}
				if (cachedMethod.matches(parametersTypeBinding, originalPolymorphicMethod.returnType)) {
					return cachedMethod;
				}
		}
		needToGrow = true;
	} else {
		cachedInfo = new PolymorphicMethodBinding[5];
		this.uniquePolymorphicMethodBindings.put(key, cachedInfo);
	}
	// grow cache ?
	int length = cachedInfo.length;
	if (needToGrow && index == length) {
		System.arraycopy(cachedInfo, 0, cachedInfo = new PolymorphicMethodBinding[length*2], 0, length);
		this.uniquePolymorphicMethodBindings.put(key, cachedInfo);
	}
	// add new binding
	PolymorphicMethodBinding polymorphicMethod = new PolymorphicMethodBinding(
			originalPolymorphicMethod,
			parametersTypeBinding);
	cachedInfo[index] = polymorphicMethod;
	return polymorphicMethod;
}

public boolean usesAnnotatedTypeSystem() {
	return this.typeSystem.isAnnotatedTypeSystem();
}

public MethodBinding updatePolymorphicMethodReturnType(PolymorphicMethodBinding binding, TypeBinding typeBinding) {
	// update the return type to be the given return type, but reuse existing binding if one can match
	String key = new String(binding.selector);
	PolymorphicMethodBinding[] cachedInfo = (PolymorphicMethodBinding[]) this.uniquePolymorphicMethodBindings.get(key);
	boolean needToGrow = false;
	int index = 0;
	TypeBinding[] parameters = binding.parameters;
	if (cachedInfo != null) {
		nextCachedMethod :
			// iterate existing polymorphic method for reusing one with same type arguments if any
			for (int max = cachedInfo.length; index < max; index++) {
				PolymorphicMethodBinding cachedMethod = cachedInfo[index];
				if (cachedMethod == null) {
					break nextCachedMethod;
				}
				if (cachedMethod.matches(parameters, typeBinding)) {
					return cachedMethod;
				}
		}
		needToGrow = true;
	} else {
		cachedInfo = new PolymorphicMethodBinding[5];
		this.uniquePolymorphicMethodBindings.put(key, cachedInfo);
	}
	// grow cache ?
	int length = cachedInfo.length;
	if (needToGrow && index == length) {
		System.arraycopy(cachedInfo, 0, cachedInfo = new PolymorphicMethodBinding[length*2], 0, length);
		this.uniquePolymorphicMethodBindings.put(key, cachedInfo);
	}
	// add new binding
	PolymorphicMethodBinding polymorphicMethod = new PolymorphicMethodBinding(
			binding.original(),
			typeBinding,
			parameters);
	cachedInfo[index] = polymorphicMethod;
	return polymorphicMethod;
}
public ParameterizedMethodBinding createGetClassMethod(TypeBinding receiverType, MethodBinding originalMethod, Scope scope) {
	// see if we have already cached this method for the given receiver type.
	ParameterizedMethodBinding retVal = null;
	if (this.uniqueGetClassMethodBinding == null) {
		this.uniqueGetClassMethodBinding = new SimpleLookupTable(3);
	} else {
		retVal = (ParameterizedMethodBinding)this.uniqueGetClassMethodBinding.get(receiverType);
	}
	if (retVal == null) {
		retVal = ParameterizedMethodBinding.instantiateGetClass(receiverType, originalMethod, scope);
		this.uniqueGetClassMethodBinding.put(receiverType, retVal);
	}
	return retVal;
}
public ReferenceBinding createMemberType(ReferenceBinding memberType, ReferenceBinding enclosingType) {
	return this.typeSystem.getMemberType(memberType, enclosingType);
}
public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType) {
	AnnotationBinding[] annotations = genericType.typeAnnotations;
	if (annotations != Binding.NO_ANNOTATIONS)
		return this.typeSystem.getParameterizedType((ReferenceBinding) genericType.unannotated(), typeArguments, enclosingType, annotations);
	return this.typeSystem.getParameterizedType(genericType, typeArguments, enclosingType);
}

public ParameterizedTypeBinding createParameterizedType(ReferenceBinding genericType, TypeBinding[] typeArguments, ReferenceBinding enclosingType, AnnotationBinding [] annotations) {
	return this.typeSystem.getParameterizedType(genericType, typeArguments, enclosingType, annotations);
}
public ReferenceBinding maybeCreateParameterizedType(ReferenceBinding nonGenericType, ReferenceBinding enclosingType) {
	boolean canSeeEnclosingTypeParameters = enclosingType != null 
			&& (enclosingType.isParameterizedType() | enclosingType.isRawType())
			&& !nonGenericType.isStatic();
	if (canSeeEnclosingTypeParameters)
		return createParameterizedType(nonGenericType, null, enclosingType);
	return nonGenericType;
}

public TypeBinding createAnnotatedType(TypeBinding type, AnnotationBinding[][] annotations) {
	return this.typeSystem.getAnnotatedType(type, annotations);
}

// Variant to handle incoming type possibly carrying annotations.
public TypeBinding createAnnotatedType(TypeBinding type, AnnotationBinding[] newbies) {
	final int newLength = newbies == null ? 0 :  newbies.length;
	if (type == null || newLength == 0)
		return type;
	AnnotationBinding [] oldies = type.getTypeAnnotations();
	final int oldLength = oldies == null ? 0 : oldies.length;
	if (oldLength > 0) {
		System.arraycopy(newbies, 0, newbies = new AnnotationBinding[newLength + oldLength], 0, newLength);
		System.arraycopy(oldies, 0, newbies, newLength, oldLength);
	}
	if (this.globalOptions.isAnnotationBasedNullAnalysisEnabled) {
		// filter duplicate null annotations
		// (do we want to filter other annotations as well? only if not repeatable?)
		long tagBitsSeen = 0;
		AnnotationBinding[] filtered = new AnnotationBinding[newbies.length];
		int count = 0;
		for (int i = 0; i < newbies.length; i++) {
			if (newbies[i] == null) {
				filtered[count++] = null;
				// reset tagBitsSeen for next array dimension
				tagBitsSeen = 0;
				continue;
			}
			long tagBits = 0;
			if (newbies[i].type.hasNullBit(TypeIds.BitNonNullAnnotation)) {
				tagBits = TagBits.AnnotationNonNull;
			} else if (newbies[i].type.hasNullBit(TypeIds.BitNullableAnnotation)) {
				tagBits = TagBits.AnnotationNullable;
			}
			if ((tagBitsSeen & tagBits) == 0) {
				tagBitsSeen |= tagBits;
				filtered[count++] = newbies[i];
			}
		}
		if (count < newbies.length)
			System.arraycopy(filtered, 0, newbies = new AnnotationBinding[count], 0, count);
	}
	return this.typeSystem.getAnnotatedType(type, new AnnotationBinding [][] { newbies });
}

public RawTypeBinding createRawType(ReferenceBinding genericType, ReferenceBinding enclosingType) {
	AnnotationBinding[] annotations = genericType.typeAnnotations;
	if (annotations != Binding.NO_ANNOTATIONS)
		return this.typeSystem.getRawType((ReferenceBinding) genericType.unannotated(), enclosingType, annotations);
	return this.typeSystem.getRawType(genericType, enclosingType);
}

public RawTypeBinding createRawType(ReferenceBinding genericType, ReferenceBinding enclosingType, AnnotationBinding [] annotations) {
	return this.typeSystem.getRawType(genericType, enclosingType, annotations);
}

public WildcardBinding createWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind) {
	if (genericType != null) {
		AnnotationBinding[] annotations = genericType.typeAnnotations;
		if (annotations != Binding.NO_ANNOTATIONS)
			return this.typeSystem.getWildcard((ReferenceBinding) genericType.unannotated(), rank, bound, otherBounds, boundKind, annotations);
	}
	return this.typeSystem.getWildcard(genericType, rank, bound, otherBounds, boundKind);
}

public CaptureBinding createCapturedWildcard(WildcardBinding wildcard, ReferenceBinding contextType, int start, int end, ASTNode cud, int id) {
	return this.typeSystem.getCapturedWildcard(wildcard, contextType, start, end, cud, id);
}

public WildcardBinding createWildcard(ReferenceBinding genericType, int rank, TypeBinding bound, TypeBinding[] otherBounds, int boundKind, AnnotationBinding [] annotations) {
	return this.typeSystem.getWildcard(genericType, rank, bound, otherBounds, boundKind, annotations);
}

/**
 * Returns the access restriction associated to a given type, or null if none
 */
public AccessRestriction getAccessRestriction(TypeBinding type) {
	return (AccessRestriction) this.accessRestrictions.get(type);
}

/**
 *  Answer the type for the compoundName if it exists in the cache.
 * Answer theNotFoundType if it could not be resolved the first time
 * it was looked up, otherwise answer null.
 *
 * NOTE: Do not use for nested types... the answer is NOT the same for a.b.C or a.b.C.D.E
 * assuming C is a type in both cases. In the a.b.C.D.E case, null is the answer.
 */
public ReferenceBinding getCachedType(char[][] compoundName) {
	ReferenceBinding result = getCachedType0(compoundName);
	if (result == null && this.useModuleSystem) {
		ModuleBinding[] modulesToSearch = this.module.isUnnamed() || this.module.isAuto
				? this.root.knownModules.valueTable
				: this.module.getAllRequiredModules();
		for (ModuleBinding someModule : modulesToSearch) {
			if (someModule == null) continue;
			result = someModule.environment.getCachedType0(compoundName);
			if (result != null && result.isValidBinding())
				break;
		}
	}
	return result;
}
public ReferenceBinding getCachedType0(char[][] compoundName) {
	if (compoundName.length == 1) {
		return this.defaultPackage.getType0(compoundName[0]);
	}
	PackageBinding packageBinding = getPackage0(compoundName[0]);
	if (packageBinding == null || packageBinding == TheNotFoundPackage)
		return null;

	for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++)
		if ((packageBinding = packageBinding.getPackage0Any(compoundName[i])) == null || packageBinding == TheNotFoundPackage)
			return null;
	return packageBinding.getType0(compoundName[compoundName.length - 1]);
}

public AnnotationBinding getNullableAnnotation() {
	if (this.nullableAnnotation != null)
		return this.nullableAnnotation;
	if (this.root != this) {
		return this.nullableAnnotation = this.root.getNullableAnnotation();
	}
	ReferenceBinding nullable = getResolvedType(this.globalOptions.nullableAnnotationName, null);
	return this.nullableAnnotation = this.typeSystem.getAnnotationType(nullable, true);
}

public char[][] getNullableAnnotationName() {
	return this.globalOptions.nullableAnnotationName;
}

public AnnotationBinding getNonNullAnnotation() {
	if (this.nonNullAnnotation != null) 
		return this.nonNullAnnotation;
	if (this.root != this) {
		return this.nonNullAnnotation = this.root.getNonNullAnnotation();
	}
	ReferenceBinding nonNull = getResolvedType(this.globalOptions.nonNullAnnotationName, null);
	return this.nonNullAnnotation = this.typeSystem.getAnnotationType(nonNull, true);
}

public AnnotationBinding[] nullAnnotationsFromTagBits(long nullTagBits) {
	if (nullTagBits == TagBits.AnnotationNonNull)
		return new AnnotationBinding[] { getNonNullAnnotation() };
	else if (nullTagBits == TagBits.AnnotationNullable)
		return new AnnotationBinding[] { getNullableAnnotation() };
	return null;
}

public char[][] getNonNullAnnotationName() {
	return this.globalOptions.nonNullAnnotationName;
}

public char[][] getNonNullByDefaultAnnotationName() {
	return this.globalOptions.nonNullByDefaultAnnotationName;
}

int getNullAnnotationBit(char[][] qualifiedTypeName) {
	if (this.allNullAnnotations == null) {
		this.allNullAnnotations = new HashMap<>();
		this.allNullAnnotations.put(CharOperation.toString(this.globalOptions.nonNullAnnotationName), TypeIds.BitNonNullAnnotation);
		this.allNullAnnotations.put(CharOperation.toString(this.globalOptions.nullableAnnotationName), TypeIds.BitNullableAnnotation);
		this.allNullAnnotations.put(CharOperation.toString(this.globalOptions.nonNullByDefaultAnnotationName), TypeIds.BitNonNullByDefaultAnnotation);
		for (String name : this.globalOptions.nullableAnnotationSecondaryNames)
			this.allNullAnnotations.put(name, TypeIds.BitNullableAnnotation);
		for (String name : this.globalOptions.nonNullAnnotationSecondaryNames)
			this.allNullAnnotations.put(name, TypeIds.BitNonNullAnnotation);
		for (String name : this.globalOptions.nonNullByDefaultAnnotationSecondaryNames)
			this.allNullAnnotations.put(name, TypeIds.BitNonNullByDefaultAnnotation);
	}
	String qualifiedTypeString = CharOperation.toString(qualifiedTypeName);
	Integer typeBit = this.allNullAnnotations.get(qualifiedTypeString);
	return typeBit == null ? 0 : typeBit;
}
public boolean isNullnessAnnotationPackage(PackageBinding pkg) {
	return this.nonnullAnnotationPackage == pkg || this.nullableAnnotationPackage == pkg || this.nonnullByDefaultAnnotationPackage == pkg;
}

public boolean usesNullTypeAnnotations() {
	if(this.root != this) {
		return this.root.usesNullTypeAnnotations();
	}
	if (this.globalOptions.useNullTypeAnnotations != null)
		return this.globalOptions.useNullTypeAnnotations;

	initializeUsesNullTypeAnnotation();
	for (MethodBinding enumMethod : this.deferredEnumMethods) {
		int purpose = 0;
		if (CharOperation.equals(enumMethod.selector, TypeConstants.VALUEOF)) {
			purpose = SyntheticMethodBinding.EnumValueOf;
		} else if (CharOperation.equals(enumMethod.selector, TypeConstants.VALUES)) {
			purpose = SyntheticMethodBinding.EnumValues;
		}
		if (purpose != 0)
			SyntheticMethodBinding.markNonNull(enumMethod, purpose, this);
	}
	this.deferredEnumMethods.clear();
	return this.globalOptions.useNullTypeAnnotations;
}

private void initializeUsesNullTypeAnnotation() {
	this.globalOptions.useNullTypeAnnotations = Boolean.FALSE;
	if (!this.globalOptions.isAnnotationBasedNullAnalysisEnabled || this.globalOptions.originalSourceLevel < ClassFileConstants.JDK1_8)
		return;
	ReferenceBinding nullable;
	ReferenceBinding nonNull;
	boolean origMayTolerateMissingType = this.mayTolerateMissingType;
	this.mayTolerateMissingType = true;
	try {
		nullable = this.nullableAnnotation != null ? this.nullableAnnotation.getAnnotationType()
				: getType(this.getNullableAnnotationName(), this.UnNamedModule); // FIXME(SHMOD) module for null
																					// annotations??
		nonNull = this.nonNullAnnotation != null ? this.nonNullAnnotation.getAnnotationType()
				: getType(this.getNonNullAnnotationName(), this.UnNamedModule);
	} finally {
		this.mayTolerateMissingType = origMayTolerateMissingType;
	}
	if (nullable == null && nonNull == null)
		return;
	if (nullable == null || nonNull == null)
		return; // TODO should report an error about inconsistent setup
	long nullableMetaBits = nullable.getAnnotationTagBits() & TagBits.AnnotationForTypeUse;
	long nonNullMetaBits = nonNull.getAnnotationTagBits() & TagBits.AnnotationForTypeUse;
	if (nullableMetaBits != nonNullMetaBits)
		return; // TODO should report an error about inconsistent setup
	if (nullableMetaBits == 0)
		return;
	this.globalOptions.useNullTypeAnnotations = Boolean.TRUE;
}

/* Answer the top level package named name if it exists in the cache.
* Answer theNotFoundPackage if it could not be resolved the first time
* it was looked up, otherwise answer null.
*
* NOTE: Senders must convert theNotFoundPackage into a real problem
* package if its to returned.
*/
PackageBinding getPackage0(char[] name) {
	return this.knownPackages.get(name);
}

/* Answer the type corresponding to the compoundName.
* Ask the name environment for the type if its not in the cache.
* Fail with a classpath error if the type cannot be found.
*/
public ReferenceBinding getResolvedType(char[][] compoundName, Scope scope) {
	return getResolvedType(compoundName, scope == null ? this.UnNamedModule : scope.module(), scope);
}
public ReferenceBinding getResolvedType(char[][] compoundName, ModuleBinding moduleBinding, Scope scope) {
	if (this.module != moduleBinding)
		return moduleBinding.environment.getResolvedType(compoundName, moduleBinding, scope);
	ReferenceBinding type = getType(compoundName, moduleBinding);
	if (type != null) return type;

	// create a proxy for the missing BinaryType
	// report the missing class file first
	this.problemReporter.isClassPathCorrect(
		compoundName,
		scope == null ? this.root.unitBeingCompleted : scope.referenceCompilationUnit(),
		this.missingClassFileLocation);
	return createMissingType(null, compoundName);
}
public ReferenceBinding getResolvedJavaBaseType(char[][] compoundName, Scope scope) {
	return getResolvedType(compoundName, javaBaseModule(), scope);
}

/* Answer the top level package named name.
* Ask the oracle for the package if its not in the cache.
* Answer null if the package cannot be found.
*/
PackageBinding getTopLevelPackage(char[] name) {
	PackageBinding packageBinding = getPackage0(name);
	if (packageBinding != null) {
		if (packageBinding == TheNotFoundPackage)
			return null;
		return packageBinding;
	}
	if (this.useModuleSystem) {
		if (this.module != null)
			packageBinding = this.module.getTopLevelPackage(name);
	} else {
		if (this.nameEnvironment.isPackage(null, name)) {
			this.knownPackages.put(name, packageBinding = new PackageBinding(name, this, this.module));
		}
	}
	if (packageBinding != null) {
		if (packageBinding == TheNotFoundPackage)
			return null;
		return packageBinding;
	}

	this.knownPackages.put(name, TheNotFoundPackage); // saves asking the oracle next time
	return null;
}

public ReferenceBinding getType(char[][] compoundName) {
	return getType(compoundName, this.UnNamedModule);
}
/* Answer the type corresponding to the compoundName.
* Ask the name environment for the type if its not in the cache.
* Answer null if the type cannot be found.
*/
public ReferenceBinding getType(char[][] compoundName, ModuleBinding mod) {
	ReferenceBinding referenceBinding;

	if (compoundName.length == 1) {
		if ((referenceBinding = this.defaultPackage.getType0(compoundName[0])) == null) {
			PackageBinding packageBinding = getPackage0(compoundName[0]);
			if (packageBinding != null && packageBinding != TheNotFoundPackage)
				return null; // collides with a known package... should not call this method in such a case
			referenceBinding = askForType(this.defaultPackage, compoundName[0], mod);
		}
	} else {
		PackageBinding packageBinding = getPackage0(compoundName[0]);
		if (packageBinding == TheNotFoundPackage)
			return null;

		if (packageBinding != null) {
			for (int i = 1, packageLength = compoundName.length - 1; i < packageLength; i++) {
				if ((packageBinding = packageBinding.getPackage0(compoundName[i])) == null)
					break;
				if (packageBinding == TheNotFoundPackage)
					return null;
			}
		}

		if (packageBinding == null)
			referenceBinding = askForType(compoundName, mod);
		else if ((referenceBinding = packageBinding.getType0(compoundName[compoundName.length - 1])) == null)
			referenceBinding = askForType(packageBinding, compoundName[compoundName.length - 1], mod);
	}

	if (referenceBinding == null || referenceBinding == TheNotFoundType)
		return null;
	referenceBinding = (ReferenceBinding) BinaryTypeBinding.resolveType(referenceBinding, this, false /* no raw conversion for now */);

	// compoundName refers to a nested type incorrectly (for example, package1.A$B)
//	if (referenceBinding.isNestedType())
//		return new ProblemReferenceBinding(compoundName, referenceBinding, InternalNameProvided);
	return referenceBinding;
}

private TypeBinding[] getTypeArgumentsFromSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType, ReferenceBinding genericType,
		char[][][] missingTypeNames, ITypeAnnotationWalker walker)
{
	java.util.ArrayList args = new java.util.ArrayList(2);
	int rank = 0;
	do {
		args.add(getTypeFromVariantTypeSignature(wrapper, staticVariables, enclosingType, genericType, rank, missingTypeNames,
					walker.toTypeArgument(rank++)));
	} while (wrapper.signature[wrapper.start] != '>');
	wrapper.start++; // skip '>'
	TypeBinding[] typeArguments = new TypeBinding[args.size()];
	args.toArray(typeArguments);
	return typeArguments;
}

/* Answer the type corresponding to the compound name.
* Does not ask the oracle for the type if its not found in the cache... instead an
* unresolved type is returned which must be resolved before used.
*
* NOTE: Does NOT answer base types nor array types!
*/
private ReferenceBinding getTypeFromCompoundName(char[][] compoundName, boolean isParameterized, boolean wasMissingType) {
	ReferenceBinding binding = getCachedType(compoundName);
	if (binding == null) {
		PackageBinding packageBinding = computePackageFrom(compoundName, false /* valid pkg */);
		if(this.useModuleSystem) {
			// the package might not have been seen in getCachedType, so retry
			binding = packageBinding.getType0(compoundName[compoundName.length - 1]);
		}
		if(binding == null) {
			binding = new UnresolvedReferenceBinding(compoundName, packageBinding);
			if (wasMissingType) {
				binding.tagBits |= TagBits.HasMissingType; // record it was bound to a missing type
			}
			packageBinding.addType(binding);
		}
	} else if (binding == TheNotFoundType) {
		// report the missing class file first
		if (!wasMissingType) {
			/* Since missing types have been already been complained against while producing binaries, there is no class path 
			 * misconfiguration now that did not also exist in some equivalent form while producing the class files which encode 
			 * these missing types. So no need to bark again. Note that wasMissingType == true signals a type referenced in a .class 
			 * file which could not be found when the binary was produced. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=364450 */
			this.problemReporter.isClassPathCorrect(compoundName, this.root.unitBeingCompleted, this.missingClassFileLocation);
		}
		// create a proxy for the missing BinaryType
		binding = createMissingType(null, compoundName);
	} else if (!isParameterized) {
	    // check raw type, only for resolved types
        binding = (ReferenceBinding) convertUnresolvedBinaryToRawType(binding);
	}
	return binding;
}

/* Answer the type corresponding to the name from the binary file.
* Does not ask the oracle for the type if its not found in the cache... instead an
* unresolved type is returned which must be resolved before used.
*
* NOTE: Does NOT answer base types nor array types!
*/
ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end, boolean isParameterized, char[][][] missingTypeNames, ITypeAnnotationWalker walker) {
	if (end == -1)
		end = signature.length;
	char[][] compoundName = CharOperation.splitOn('/', signature, start, end);
	boolean wasMissingType = false;
	if (missingTypeNames != null) {
		for (int i = 0, max = missingTypeNames.length; i < max; i++) {
			if (CharOperation.equals(compoundName, missingTypeNames[i])) {
				wasMissingType = true;
				break;
			}
		}
	}
	ReferenceBinding binding = getTypeFromCompoundName(compoundName, isParameterized, wasMissingType);
	if (walker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
		binding = (ReferenceBinding) annotateType(binding, walker, missingTypeNames);
	}
	return binding;
}

ReferenceBinding getTypeFromConstantPoolName(char[] signature, int start, int end, boolean isParameterized, char[][][] missingTypeNames) {
	return getTypeFromConstantPoolName(signature, start, end, isParameterized, missingTypeNames, ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
}

/* Answer the type corresponding to the signature from the binary file.
* Does not ask the oracle for the type if its not found in the cache... instead an
* unresolved type is returned which must be resolved before used.
*
* NOTE: Does answer base types & array types.
*/
TypeBinding getTypeFromSignature(char[] signature, int start, int end, boolean isParameterized, TypeBinding enclosingType, 
		char[][][] missingTypeNames, ITypeAnnotationWalker walker)
{
	int dimension = 0;
	while (signature[start] == '[') {
		start++;
		dimension++;
	}
	// annotations on dimensions?
	AnnotationBinding [][] annotationsOnDimensions = null;
	if (dimension > 0 && walker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
		for (int i = 0; i < dimension; i++) {
			AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0, true), this, missingTypeNames);
			if (annotations != Binding.NO_ANNOTATIONS) { 
				if (annotationsOnDimensions == null)
					annotationsOnDimensions = new AnnotationBinding[dimension][];
					annotationsOnDimensions[i] = annotations;
			}
			walker = walker.toNextArrayDimension();
		}
	}
	
	if (end == -1)
		end = signature.length - 1;

	// Just switch on signature[start] - the L case is the else
	TypeBinding binding = null;
	if (start == end) {
		switch (signature[start]) {
			case 'I' :
				binding = TypeBinding.INT;
				break;
			case 'Z' :
				binding = TypeBinding.BOOLEAN;
				break;
			case 'V' :
				binding = TypeBinding.VOID;
				break;
			case 'C' :
				binding = TypeBinding.CHAR;
				break;
			case 'D' :
				binding = TypeBinding.DOUBLE;
				break;
			case 'B' :
				binding = TypeBinding.BYTE;
				break;
			case 'F' :
				binding = TypeBinding.FLOAT;
				break;
			case 'J' :
				binding = TypeBinding.LONG;
				break;
			case 'S' :
				binding = TypeBinding.SHORT;
				break;
			default :
				this.problemReporter.corruptedSignature(enclosingType, signature, start);
				// will never reach here, since error will cause abort
		}
	} else {
		binding = getTypeFromConstantPoolName(signature, start + 1, end, isParameterized, missingTypeNames); // skip leading 'L' or 'T'
	}
	
	if (isParameterized) {
		if (dimension != 0)
			throw new IllegalStateException();
		return binding;
	}
	
	if (walker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
		binding = annotateType(binding, walker, missingTypeNames);
	}
	
	if (dimension != 0)
		binding =  this.typeSystem.getArrayType(binding, dimension, AnnotatableTypeSystem.flattenedAnnotations(annotationsOnDimensions));
	
	return binding;
}

private TypeBinding annotateType(TypeBinding binding, ITypeAnnotationWalker walker, char[][][] missingTypeNames) {
	int depth = binding.depth() + 1;
	if (depth > 1) {
		// need to count non-static nesting levels, resolved binding required for precision
		if (binding.isUnresolvedType())
			binding = ((UnresolvedReferenceBinding) binding).resolve(this, true);
		depth = countNonStaticNestingLevels(binding) + 1;
	}
	AnnotationBinding [][] annotations = null;
	for (int i = 0; i < depth; i++) {
		AnnotationBinding[] annots = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(binding.id, i == depth - 1), this, missingTypeNames);
		if (annots != null && annots.length > 0) {
			if (annotations == null)
				annotations = new AnnotationBinding[depth][];
			annotations[i] = annots;
		}
		walker = walker.toNextNestedType();
	}
	if (annotations != null)
		binding = createAnnotatedType(binding, annotations);
	return binding;
}

// compute depth below lowest static enclosingType
private int countNonStaticNestingLevels(TypeBinding binding) {
	if (binding.isUnresolvedType()) {
		throw new IllegalStateException();
	}
	int depth = -1;
	TypeBinding currentBinding = binding;
	while (currentBinding != null) {
		depth++;
		if (currentBinding.isStatic())
			break;
		currentBinding = currentBinding.enclosingType();
	}
	return depth;
}

boolean qualifiedNameMatchesSignature(char[][] name, char[] signature) {
	int s = 1; // skip 'L'
	for (int i = 0; i < name.length; i++) {
		char[] n = name[i];
		for (int j = 0; j < n.length; j++)
			if (n[j] != signature[s++])
				return false;
		if (signature[s] == ';' && i == name.length-1)
			return true;
		if (signature[s++] != '/')
			return false;
	}
	return false;
}

public TypeBinding getTypeFromTypeSignature(SignatureWrapper wrapper, TypeVariableBinding[] staticVariables, ReferenceBinding enclosingType, 
		char[][][] missingTypeNames, ITypeAnnotationWalker walker) 
{
	// TypeVariableSignature = 'T' Identifier ';'
	// ArrayTypeSignature = '[' TypeSignature
	// ClassTypeSignature = 'L' Identifier TypeArgs(optional) ';'
	//   or ClassTypeSignature '.' 'L' Identifier TypeArgs(optional) ';'
	// TypeArgs = '<' VariantTypeSignature VariantTypeSignatures '>'
	int dimension = 0;
	while (wrapper.signature[wrapper.start] == '[') {
		wrapper.start++;
		dimension++;
	}
	// annotations on dimensions?
	AnnotationBinding [][] annotationsOnDimensions = null;
	if (dimension > 0 && walker != ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER) {
		for (int i = 0; i < dimension; i++) {
			AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(0, true), this, missingTypeNames);
			if (annotations != Binding.NO_ANNOTATIONS) { 
				if (annotationsOnDimensions == null)
					annotationsOnDimensions = new AnnotationBinding[dimension][];
					annotationsOnDimensions[i] = annotations;
			}
			walker = walker.toNextArrayDimension();
		}
	}
	if (wrapper.signature[wrapper.start] == 'T') {
	    int varStart = wrapper.start + 1;
	    int varEnd = wrapper.computeEnd();
		for (int i = staticVariables.length; --i >= 0;)
			if (CharOperation.equals(staticVariables[i].sourceName, wrapper.signature, varStart, varEnd))
				return getTypeFromTypeVariable(staticVariables[i], dimension, annotationsOnDimensions, walker, missingTypeNames);
	    ReferenceBinding initialType = enclosingType;
		do {
			TypeVariableBinding[] enclosingTypeVariables;
			if (enclosingType instanceof BinaryTypeBinding) { // compiler normal case, no eager resolution of binary variables
				enclosingTypeVariables = ((BinaryTypeBinding)enclosingType).typeVariables; // do not trigger resolution of variables
			} else { // codepath only use by codeassist for decoding signatures
				enclosingTypeVariables = enclosingType.typeVariables();
			}
			for (int i = enclosingTypeVariables.length; --i >= 0;)
				if (CharOperation.equals(enclosingTypeVariables[i].sourceName, wrapper.signature, varStart, varEnd))
					return getTypeFromTypeVariable(enclosingTypeVariables[i], dimension, annotationsOnDimensions, walker, missingTypeNames);
		} while ((enclosingType = enclosingType.enclosingType()) != null);
		this.problemReporter.undefinedTypeVariableSignature(CharOperation.subarray(wrapper.signature, varStart, varEnd), initialType);
		return null; // cannot reach this, since previous problem will abort compilation
	}
	boolean isParameterized;
	TypeBinding type = getTypeFromSignature(wrapper.signature, wrapper.start, wrapper.computeEnd(), isParameterized = (wrapper.end == wrapper.bracket), enclosingType, missingTypeNames, walker);

	if (!isParameterized)
		return dimension == 0 ? type : createArrayType(type, dimension, AnnotatableTypeSystem.flattenedAnnotations(annotationsOnDimensions));

	// type must be a ReferenceBinding at this point, cannot be a BaseTypeBinding or ArrayTypeBinding
	ReferenceBinding actualType = (ReferenceBinding) type;
	if (actualType instanceof UnresolvedReferenceBinding)
		if (actualType.depth() > 0)
			actualType = (ReferenceBinding) BinaryTypeBinding.resolveType(actualType, this, false /* no raw conversion */); // must resolve member types before asking for enclosingType
	ReferenceBinding actualEnclosing = actualType.enclosingType();

	ITypeAnnotationWalker savedWalker = walker;
	if(actualType.depth() > 0) {
		int nonStaticNestingLevels = countNonStaticNestingLevels(actualType);
		for (int i = 0; i < nonStaticNestingLevels; i++) {
			walker = walker.toNextNestedType();
		}
	}

	TypeBinding[] typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, actualType, missingTypeNames, walker);
	ReferenceBinding currentType = createParameterizedType(actualType, typeArguments, actualEnclosing);
	ReferenceBinding plainCurrent = actualType;

	while (wrapper.signature[wrapper.start] == '.') {
		wrapper.start++; // skip '.'
		int memberStart = wrapper.start;
		char[] memberName = wrapper.nextWord();
		plainCurrent = (ReferenceBinding) BinaryTypeBinding.resolveType(plainCurrent, this, false);
		ReferenceBinding memberType = plainCurrent.getMemberType(memberName);
		// need to protect against the member type being null when the signature is invalid
		if (memberType == null)
			this.problemReporter.corruptedSignature(currentType, wrapper.signature, memberStart); // aborts
		if(memberType.isStatic()) {
			// may happen for class files generated by eclipse before bug 460491 was fixed. 
			walker = savedWalker;
		} else {
			walker = walker.toNextNestedType();
		}
		if (wrapper.signature[wrapper.start] == '<') {
			wrapper.start++; // skip '<'
			typeArguments = getTypeArgumentsFromSignature(wrapper, staticVariables, enclosingType, memberType, missingTypeNames, walker);
		} else {
			typeArguments = null;
		}
		if (typeArguments != null || 											// has type arguments, or ... 
				(!memberType.isStatic() && currentType.isParameterizedType())) 	// ... can see type arguments of enclosing
		{
			if (memberType.isStatic())
				currentType = plainCurrent; // ignore bogus parameterization of enclosing
			currentType = createParameterizedType(memberType, typeArguments, currentType);
		} else {
			currentType = memberType;
		}
		plainCurrent = memberType;
	}
	wrapper.start++; // skip ';'
	TypeBinding annotatedType = annotateType(currentType, savedWalker, missingTypeNames);
	return dimension == 0 ? annotatedType : createArrayType(annotatedType, dimension, AnnotatableTypeSystem.flattenedAnnotations(annotationsOnDimensions));
}

private TypeBinding getTypeFromTypeVariable(TypeVariableBinding typeVariableBinding, int dimension, AnnotationBinding [][] annotationsOnDimensions, ITypeAnnotationWalker walker, char [][][] missingTypeNames) {
	AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(-1, false), this, missingTypeNames);
	if (annotations != null && annotations != Binding.NO_ANNOTATIONS)
		typeVariableBinding = (TypeVariableBinding) createAnnotatedType(typeVariableBinding, new AnnotationBinding [][] { annotations });

	if (dimension == 0) {
		return typeVariableBinding;
	}
	return this.typeSystem.getArrayType(typeVariableBinding, dimension, AnnotatableTypeSystem.flattenedAnnotations(annotationsOnDimensions));
}

TypeBinding getTypeFromVariantTypeSignature(
		SignatureWrapper wrapper,
		TypeVariableBinding[] staticVariables,
		ReferenceBinding enclosingType,
		ReferenceBinding genericType,
		int rank,
		char[][][] missingTypeNames,
		ITypeAnnotationWalker walker) {
	// VariantTypeSignature = '-' TypeSignature
	//   or '+' TypeSignature
	//   or TypeSignature
	//   or '*'
	switch (wrapper.signature[wrapper.start]) {
		case '-' :
			// ? super aType
			wrapper.start++;
			TypeBinding bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType, missingTypeNames, walker.toWildcardBound());
			AnnotationBinding [] annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(-1, false), this, missingTypeNames);
			return this.typeSystem.getWildcard(genericType, rank, bound, null /*no extra bound*/, Wildcard.SUPER, annotations);
		case '+' :
			// ? extends aType
			wrapper.start++;
			bound = getTypeFromTypeSignature(wrapper, staticVariables, enclosingType, missingTypeNames, walker.toWildcardBound());
			annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(-1, false), this, missingTypeNames);
			return this.typeSystem.getWildcard(genericType, rank, bound, null /*no extra bound*/, Wildcard.EXTENDS, annotations);
		case '*' :
			// ?
			wrapper.start++;
			annotations = BinaryTypeBinding.createAnnotations(walker.getAnnotationsAtCursor(-1, false), this, missingTypeNames);
			return this.typeSystem.getWildcard(genericType, rank, null, null /*no extra bound*/, Wildcard.UNBOUND, annotations);
		default :
			return getTypeFromTypeSignature(wrapper, staticVariables, enclosingType, missingTypeNames, walker);
	}
}

boolean isMissingType(char[] typeName) {
	for (int i = this.missingTypes == null ? 0 : this.missingTypes.size(); --i >= 0;) {
		MissingTypeBinding missingType = (MissingTypeBinding) this.missingTypes.get(i);
		if (CharOperation.equals(missingType.sourceName, typeName))
			return true;
	}
	return false;
}

// The method verifier is lazily initialized to guarantee the receiver, the compiler & the oracle are ready.
public MethodVerifier methodVerifier() {
	 // TODO(SHMOD): I'm not sure if the verifier would need to be created with a specific LE?
	if (this.verifier == null)
		this.verifier = newMethodVerifier();
	return this.verifier;
}

public MethodVerifier newMethodVerifier() {
	/* Always use MethodVerifier15. Even in a 1.4 project, we must internalize type variables and
	   observe any parameterization of super class and/or super interfaces in order to be able to
	   detect overriding in the presence of generics.
	   See https://bugs.eclipse.org/bugs/show_bug.cgi?id=324850
	 */
	return new MethodVerifier15(this);
}

public void releaseClassFiles(org.eclipse.jdt.internal.compiler.ClassFile[] classFiles) {
	for (int i = 0, fileCount = classFiles.length; i < fileCount; i++)
		this.classFilePool.release(classFiles[i]);
}

public void reset() {
	if (this.root != this) {
		this.root.reset();
		return;
	}
	this.knownModules = new HashtableOfModule();
	this.UnNamedModule = new ModuleBinding.UnNamedModule(this);
	this.module = this.UnNamedModule;
	this.JavaBaseModule = null;

	this.defaultPackage = new PackageBinding(this); // assume the default package always exists
	this.defaultImports = null;
	this.knownPackages = new HashtableOfPackage();
	this.accessRestrictions = new HashMap(3);

	this.verifier = null;
	
	// NOTE: remember to fix #updateCaches(...) when adding unique binding caches
	this.uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(3);
	this.uniquePolymorphicMethodBindings = new SimpleLookupTable(3);
	this.uniqueGetClassMethodBinding = null;
	this.missingTypes = null;
	this.typesBeingConnected = new HashSet();

	for (int i = this.units.length; --i >= 0;)
		this.units[i] = null;
	this.lastUnitIndex = -1;
	this.lastCompletedUnitIndex = -1;
	this.unitBeingCompleted = null; // in case AbortException occurred

	this.classFilePool.reset();
	this.typeSystem.reset();
	// name environment has a longer life cycle, and must be reset in
	// the code which created it.
}

/**
 * Associate a given type with some access restriction
 * (did not store the restriction directly into binding, since sparse information)
 */
public void setAccessRestriction(ReferenceBinding type, AccessRestriction accessRestriction) {
	if (accessRestriction == null) return;
	type.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
	this.accessRestrictions.put(type, accessRestriction);
}

void updateCaches(UnresolvedReferenceBinding unresolvedType, ReferenceBinding resolvedType) {
	this.typeSystem.updateCaches(unresolvedType, resolvedType);
}

public IQualifiedTypeResolutionListener[] resolutionListeners;	// ROOT_ONLY

public void addResolutionListener(IQualifiedTypeResolutionListener resolutionListener) {
	synchronized (this.root) {
		int length = this.root.resolutionListeners.length;
		for (int i = 0; i < length; i++){
			if (this.root.resolutionListeners[i].equals(resolutionListener))
				return;
		}
		System.arraycopy(this.root.resolutionListeners, 0,
				this.root.resolutionListeners = new IQualifiedTypeResolutionListener[length + 1], 0, length);
		this.root.resolutionListeners[length] = resolutionListener;
	}
}


public TypeBinding getUnannotatedType(TypeBinding typeBinding) {
	return this.typeSystem.getUnannotatedType(typeBinding);
}

// Given a type, return all its variously annotated versions.
public TypeBinding[] getAnnotatedTypes(TypeBinding type) {
	return this.typeSystem.getAnnotatedTypes(type);
}

public AnnotationBinding[] filterNullTypeAnnotations(AnnotationBinding[] typeAnnotations) {
	if (typeAnnotations.length == 0)
		return typeAnnotations;
	AnnotationBinding[] filtered = new AnnotationBinding[typeAnnotations.length];
	int count = 0;
	for (int i = 0; i < typeAnnotations.length; i++) {
		AnnotationBinding typeAnnotation = typeAnnotations[i];
		if (typeAnnotation == null) {
			count++; // sentinel in annotation sequence for array dimensions
		} else {
			if (!typeAnnotation.type.hasNullBit(TypeIds.BitNonNullAnnotation|TypeIds.BitNullableAnnotation))
				filtered[count++] = typeAnnotation;
		}
	}
	if (count == 0)
		return Binding.NO_ANNOTATIONS;
	if (count == typeAnnotations.length)
		return typeAnnotations;
	System.arraycopy(filtered, 0, filtered = new AnnotationBinding[count], 0, count);
	return filtered;
}

public boolean containsNullTypeAnnotation(IBinaryAnnotation[] typeAnnotations) {
	if (typeAnnotations.length == 0)
		return false;
	for (int i = 0; i < typeAnnotations.length; i++) {
		IBinaryAnnotation typeAnnotation = typeAnnotations[i];
		char[] typeName = typeAnnotation.getTypeName();
		// typeName must be "Lfoo/X;"
		if (typeName == null || typeName.length < 3 || typeName[0] != 'L') continue;
		char[][] name = CharOperation.splitOn('/', typeName, 1, typeName.length-1);
		if (getNullAnnotationBit(name) != 0)
			return true;
	}
	return false;
}
public boolean containsNullTypeAnnotation(AnnotationBinding[] typeAnnotations) {
	if (typeAnnotations.length == 0)
		return false;
	for (int i = 0; i < typeAnnotations.length; i++) {
		AnnotationBinding typeAnnotation = typeAnnotations[i];
		if (typeAnnotation.type.hasNullBit(TypeIds.BitNonNullAnnotation|TypeIds.BitNullableAnnotation))
			return true;
	}
	return false;	
}
}
