/*******************************************************************************
 * 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
 *     Fraunhofer FIRST - extended API and implementation
 *     Technical University Berlin - extended API and implementation
 *     Stephan Herrmann  - Contribution for bug 295551
 *     Jesper S Moller   - Contributions for
 *							  Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335
 *     Frits Jalvingh    - contributions for bug 533830.             
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import java.util.Arrays;
import java.util.Comparator;

import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.impl.IrritantSet;
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.ImportBinding;
import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.parser.NLSTag;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilationUnit;
import org.eclipse.jdt.internal.compiler.problem.AbortMethod;
import org.eclipse.jdt.internal.compiler.problem.AbortType;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.compiler.util.HashSetOfInt;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateMemento;

/**
 * OTDT changes:
 *
 * ROLE UNITS:
 * What: link to CUD of enclosing team
 * Why:  it should be possible to find both the physically containing (RoleUnit)
 * 		 as well as logically containing (team) CUD.
 *
 * DECOUPLE FROM COMPILER:
 * What: store index into Compiler.unitsToProcess
 * What: Let resolve only be called by Dependencies.
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public class CompilationUnitDeclaration extends ASTNode implements ProblemSeverities, ReferenceContext {

	private static final Comparator STRING_LITERAL_COMPARATOR = new Comparator() {
		@Override
		public int compare(Object o1, Object o2) {
			StringLiteral literal1 = (StringLiteral) o1;
			StringLiteral literal2 = (StringLiteral) o2;
			return literal1.sourceStart - literal2.sourceStart;
		}
	};
	private static final int STRING_LITERALS_INCREMENT = 10;

	public ImportReference currentPackage;
	public ImportReference[] imports;
	public TypeDeclaration[] types;
	public ModuleDeclaration moduleDeclaration;
	public int[][] comments;

	public boolean ignoreFurtherInvestigation = false; // once pointless to investigate due to errors
	public boolean ignoreMethodBodies = false;
	public CompilationUnitScope scope;
	public ProblemReporter problemReporter;
	public CompilationResult compilationResult;

	public LocalTypeBinding[] localTypes;
	public int localTypeCount = 0;

//{ObjectTeams:
	// store this index so we can invoke getMethodBodies from outside Compiler
    public int place; // index into Compiler.unitsToProcess
	// State with respect to Dependencies:
	public final StateMemento state= new StateMemento();
	// for some CUD we need no method bodies. This is different from ignoreMethodBodies,
	// because the latter seems to relate to syntax errors, whereas this flag is set for
	// a CUD that created by the SourceTypeConverter (and is seemingly needed only indirectly)
	public boolean parseMethodBodies = true;
	// back reference needed as 'client' for Config:
	public Compiler compiler;
// SH}

	public boolean isPropagatingInnerClassEmulation;

	public Javadoc javadoc; // 1.5 addition for package-info.java

	public NLSTag[] nlsTags;
	private StringLiteral[] stringLiterals;
	private int stringLiteralsPtr;
	private HashSetOfInt stringLiteralsStart;

	public boolean[] validIdentityComparisonLines;

	IrritantSet[] suppressWarningIrritants;  // irritant for suppressed warnings
	Annotation[] suppressWarningAnnotations;
	long[] suppressWarningScopePositions; // (start << 32) + end
	int suppressWarningsCount;
	public int functionalExpressionsCount;
	public FunctionalExpression[] functionalExpressions;

public CompilationUnitDeclaration(ProblemReporter problemReporter, CompilationResult compilationResult, int sourceLength) {
	this.problemReporter = problemReporter;
	this.compilationResult = compilationResult;
	//by definition of a compilation unit....
	this.sourceStart = 0;
	this.sourceEnd = sourceLength - 1;
}

/*
 *	We cause the compilation task to abort to a given extent.
 */
@Override
public void abort(int abortLevel, CategorizedProblem problem) {
	switch (abortLevel) {
		case AbortType :
			throw new AbortType(this.compilationResult, problem);
		case AbortMethod :
			throw new AbortMethod(this.compilationResult, problem);
		default :
			throw new AbortCompilationUnit(this.compilationResult, problem);
	}
}

/*
 * Dispatch code analysis AND request saturation of inner emulation
 */
public void analyseCode() {
//{ObjectTeams: postponed from resolve() to also catch import usage from late statement generators.
	if (!this.compilationResult.hasMandatoryErrors())
		checkUnusedImports();
// SH}
	if (this.ignoreFurtherInvestigation)
		return;
	try {
		if (this.types != null) {
			for (int i = 0, count = this.types.length; i < count; i++) {
				this.types[i].analyseCode(this.scope);
			}
		}
		if (this.moduleDeclaration != null) {
			this.moduleDeclaration.analyseCode(this.scope);
		}
		// request inner emulation propagation
		propagateInnerEmulationForAllLocalTypes();
	} catch (AbortCompilationUnit e) {
		this.ignoreFurtherInvestigation = true;
		return;
	}
}

/*
 * When unit result is about to be accepted, removed back pointers
 * to compiler structures.
 */
public void cleanUp() {
//{ObjectTeams: cleanup additional field:
	this.compiler = null;
// SH}
	if (this.types != null) {
		for (int i = 0, max = this.types.length; i < max; i++) {
			cleanUp(this.types[i]);
		}
		for (int i = 0, max = this.localTypeCount; i < max; i++) {
		    LocalTypeBinding localType = this.localTypes[i];
			// null out the type's scope backpointers
			localType.cleanUp(); // local members are already in the list
			localType.enclosingCase = null;
		}
	}
	if (this.functionalExpressionsCount > 0) {
		for (int i = 0, max = this.functionalExpressionsCount; i < max; i++) {
			this.functionalExpressions[i].cleanUp();
		}
	}

	this.compilationResult.recoveryScannerData = null; // recovery is already done

	ClassFile[] classFiles = this.compilationResult.getClassFiles();
	for (int i = 0, max = classFiles.length; i < max; i++) {
		// clear the classFile back pointer to the bindings
		ClassFile classFile = classFiles[i];
//{ObjectTeams: should writeClassFile store the path of the class file written?
		classFile.maybeRememberModel();
// SH}
		// null out the classfile backpointer to a type binding
		classFile.referenceBinding = null;
		classFile.innerClassesBindings = null;
		classFile.bootstrapMethods = null;
		classFile.missingTypes = null;
		classFile.visitedTypes = null;
	}

	this.suppressWarningAnnotations = null;

	if (this.scope != null)
		this.scope.cleanUpInferenceContexts();
}

private void cleanUp(TypeDeclaration type) {
	if (type.memberTypes != null) {
		for (int i = 0, max = type.memberTypes.length; i < max; i++){
//{ObjectTeams: ROFI: don't descend into role files which have their on CompilationUnitDeclaration:
		  if (!type.memberTypes[i].isRoleFile())
// SH}
			cleanUp(type.memberTypes[i]);
		}
	}
	if (type.binding != null && type.binding.isAnnotationType())
		this.compilationResult.hasAnnotations = true;
	if (type.binding != null) {
		// null out the type's scope backpointers
		type.binding.cleanUp();
	}
//{ObjectTeams: final cleanup also from us:
	type.cleanupModels();
// SH}
}

public void checkUnusedImports(){
	if (this.scope.imports != null){
		for (int i = 0, max = this.scope.imports.length; i < max; i++){
			ImportBinding importBinding = this.scope.imports[i];
			ImportReference importReference = importBinding.reference;
			if (importReference != null && ((importReference.bits & ASTNode.Used) == 0)){
				this.scope.problemReporter().unusedImport(importReference);
			}
		}
	}
}

@Override
public CompilationResult compilationResult() {
	return this.compilationResult;
}

public void createPackageInfoType() {
	TypeDeclaration declaration = new TypeDeclaration(this.compilationResult);
	declaration.name = TypeConstants.PACKAGE_INFO_NAME;
	declaration.modifiers = ClassFileConstants.AccDefault | ClassFileConstants.AccInterface;
	declaration.javadoc = this.javadoc;
	this.types[0] = declaration; // Assumes the first slot is meant for this type
}

/*
 * Finds the matching type amoung this compilation unit types.
 * Returns null if no type with this name is found.
 * The type name is a compound name
 * e.g. if we're looking for X.A.B then a type name would be {X, A, B}
 */
public TypeDeclaration declarationOfType(char[][] typeName) {
	for (int i = 0; i < this.types.length; i++) {
		TypeDeclaration typeDecl = this.types[i].declarationOfType(typeName);
		if (typeDecl != null) {
			return typeDecl;
		}
	}
	return null;
}

public void finalizeProblems() {
//{ObjectTeams: filter out over-eager problems:
	IrritantSet[] foundIrritants = new IrritantSet[this.suppressWarningsCount];
	this.compilationResult.recheckProblems(foundIrritants);
// orig:
	int problemCount = this.compilationResult.problemCount;
	CategorizedProblem[] problems = this.compilationResult.problems;
	if (this.suppressWarningsCount == 0) {
		return;
	}
	int removed = 0;
/* 
	IrritantSet[] foundIrritants = new IrritantSet[this.suppressWarningsCount];
  :giro */
// SH}
	CompilerOptions options = this.scope.compilerOptions();
	boolean hasMandatoryErrors = false;
	nextProblem: for (int iProblem = 0, length = problemCount; iProblem < length; iProblem++) {
		CategorizedProblem problem = problems[iProblem];
		int problemID = problem.getID();
		int irritant = ProblemReporter.getIrritant(problemID);
		boolean isError = problem.isError();
		if (isError) {
			if (irritant == 0) {
				// tolerate unused warning tokens when mandatory errors
				hasMandatoryErrors = true;
				continue;
			}
			if (!options.suppressOptionalErrors) {
				continue;
			}
		}
		int start = problem.getSourceStart();
		int end = problem.getSourceEnd();
		nextSuppress: for (int iSuppress = 0, suppressCount = this.suppressWarningsCount; iSuppress < suppressCount; iSuppress++) {
			long position = this.suppressWarningScopePositions[iSuppress];
			int startSuppress = (int) (position >>> 32);
			int endSuppress = (int) position;
			if (start < startSuppress) continue nextSuppress;
			if (end > endSuppress) continue nextSuppress;
			if (!this.suppressWarningIrritants[iSuppress].isSet(irritant)) {
				if (problem instanceof DefaultProblem) {
					((DefaultProblem) problem).reportError();
				}
				continue nextSuppress;
			}
			// discard suppressed warning
			removed++;
			problems[iProblem] = null;
			this.compilationResult.removeProblem(problem);
			if (foundIrritants[iSuppress] == null){
				foundIrritants[iSuppress] = new IrritantSet(irritant);
			} else {
				foundIrritants[iSuppress].set(irritant);
			}
			continue nextProblem;
		}
	}
//{ObjectTeams: also remove marked problems in generated code (no longer need it to match SuppressWarnings):
	// (see also CompilationUnitProblemFinder#initializeParser)
	for (int iProblem = 0, length = problemCount; iProblem < length; iProblem++) {
		CategorizedProblem problem = problems[iProblem];
		if (problem instanceof DefaultProblem) {
			DefaultProblem defaultProblem = (DefaultProblem) problem;
			if (defaultProblem.isInGenerated()) {
				problems[iProblem] = null;
				this.compilationResult.removeProblem(defaultProblem);
				removed++;
			}
		}
	}
// SH}
	// compact remaining problems
	if (removed > 0) {
		for (int i = 0, index = 0; i < problemCount; i++) {
			CategorizedProblem problem;
			if ((problem = problems[i]) != null) {
				if (i > index) {
					problems[index++] = problem;
				} else {
					index++;
				}
			}
		}
	}
	// flag SuppressWarnings which had no effect (only if no (mandatory) error got detected within unit
	if (!hasMandatoryErrors) {
		int severity = options.getSeverity(CompilerOptions.UnusedWarningToken);
		if (severity != ProblemSeverities.Ignore) {
			boolean unusedWarningTokenIsWarning = (severity & ProblemSeverities.Error) == 0;
			for (int iSuppress = 0, suppressCount = this.suppressWarningsCount; iSuppress < suppressCount; iSuppress++) {
				Annotation annotation = this.suppressWarningAnnotations[iSuppress];
				if (annotation == null) continue; // implicit annotation
				IrritantSet irritants = this.suppressWarningIrritants[iSuppress];
				if (unusedWarningTokenIsWarning && irritants.areAllSet()) continue; // @SuppressWarnings("all") also suppresses unused warning token
//{ObjectTeams: don't report unused suppress against copy-inherited member:
				switch (annotation.recipient.kind()) {
					case Binding.METHOD:
						if (((MethodBinding)annotation.recipient).copyInheritanceSrc != null)
							continue;
						break;
					case Binding.FIELD:
						if (((FieldBinding)annotation.recipient).copyInheritanceSrc != null)
							continue;
						break;
				}
// SH}
				if (irritants != foundIrritants[iSuppress]) { // mismatch, some warning tokens were unused
					MemberValuePair[] pairs = annotation.memberValuePairs();
					pairLoop: for (int iPair = 0, pairCount = pairs.length; iPair < pairCount; iPair++) {
						MemberValuePair pair = pairs[iPair];
						if (CharOperation.equals(pair.name, TypeConstants.VALUE)) {
							Expression value = pair.value;
							if (value instanceof ArrayInitializer) {
								ArrayInitializer initializer = (ArrayInitializer) value;
								Expression[] inits = initializer.expressions;
								if (inits != null) {
									for (int iToken = 0, tokenCount = inits.length; iToken < tokenCount; iToken++) {
										Constant cst = inits[iToken].constant;
										if (cst != Constant.NotAConstant && cst.typeID() == TypeIds.T_JavaLangString) {
											IrritantSet tokenIrritants = CompilerOptions.warningTokenToIrritants(cst.stringValue());
											if (tokenIrritants != null) {
												if (!tokenIrritants.areAllSet() // no complaint against @SuppressWarnings("all")
														&& (foundIrritants[iSuppress] == null || !foundIrritants[iSuppress].isAnySet(tokenIrritants))) { // if irritant had no matching problem
													if (unusedWarningTokenIsWarning) {
														int start = value.sourceStart, end = value.sourceEnd;
														nextSuppress: for (int jSuppress = iSuppress - 1; jSuppress >= 0; jSuppress--) {
															long position = this.suppressWarningScopePositions[jSuppress];
															int startSuppress = (int) (position >>> 32);
															int endSuppress = (int) position;
															if (start < startSuppress) continue nextSuppress;
															if (end > endSuppress) continue nextSuppress;
															if (this.suppressWarningIrritants[jSuppress].areAllSet()) break pairLoop; // suppress all?
														}
													}
													int id = options.getIgnoredIrritant(tokenIrritants);
													if (id > 0) {
														String key = CompilerOptions.optionKeyFromIrritant(id);
														this.scope.problemReporter().problemNotAnalysed(inits[iToken], key);
													} else {
														this.scope.problemReporter().unusedWarningToken(inits[iToken]);														
													}
												}
											}
										}
									}
								}
							} else {
								Constant cst = value.constant;
								if (cst != Constant.NotAConstant && cst.typeID() == T_JavaLangString) {
									IrritantSet tokenIrritants = CompilerOptions.warningTokenToIrritants(cst.stringValue());
									if (tokenIrritants != null) {
										if (!tokenIrritants.areAllSet() // no complaint against @SuppressWarnings("all")
												&& (foundIrritants[iSuppress] == null || !foundIrritants[iSuppress].isAnySet(tokenIrritants))) { // if irritant had no matching problem
											if (unusedWarningTokenIsWarning) {
												int start = value.sourceStart, end = value.sourceEnd;
												nextSuppress: for (int jSuppress = iSuppress - 1; jSuppress >= 0; jSuppress--) {
													long position = this.suppressWarningScopePositions[jSuppress];
													int startSuppress = (int) (position >>> 32);
													int endSuppress = (int) position;
													if (start < startSuppress) continue nextSuppress;
													if (end > endSuppress) continue nextSuppress;
													if (this.suppressWarningIrritants[jSuppress].areAllSet()) break pairLoop; // suppress all?
												}
											}
											int id = options.getIgnoredIrritant(tokenIrritants);
											if (id > 0) {
												String key = CompilerOptions.optionKeyFromIrritant(id);
												this.scope.problemReporter().problemNotAnalysed(value, key);
											} else {
												this.scope.problemReporter().unusedWarningToken(value);
											}
										}
									}
								}
							}
							break pairLoop;
						}
					}
				}
			}
		}
	}
}

/**
 * Bytecode generation
 */
public void generateCode() {
	if (this.ignoreFurtherInvestigation) {
		if (this.types != null) {
			for (int i = 0, count = this.types.length; i < count; i++) {
				this.types[i].ignoreFurtherInvestigation = true;
				// propagate the flag to request problem type creation
				this.types[i].generateCode(this.scope);
			}
		}
		return;
	}
	try {
		if (this.types != null) {
			for (int i = 0, count = this.types.length; i < count; i++)
				this.types[i].generateCode(this.scope);
		}
		if (this.moduleDeclaration != null) {
			this.moduleDeclaration.generateCode();
		}
	} catch (AbortCompilationUnit e) {
		// ignore
	}
}

@Override
public CompilationUnitDeclaration getCompilationUnitDeclaration() {
	return this;
}

public char[] getFileName() {
	return this.compilationResult.getFileName();
}

public char[] getMainTypeName() {
	if (this.compilationResult.compilationUnit == null) {
		char[] fileName = this.compilationResult.getFileName();

		int start = CharOperation.lastIndexOf('/', fileName) + 1;
		if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName))
			start = CharOperation.lastIndexOf('\\', fileName) + 1;

		int end = CharOperation.lastIndexOf('.', fileName);
		if (end == -1)
			end = fileName.length;

		return CharOperation.subarray(fileName, start, end);
	} else {
		return this.compilationResult.compilationUnit.getMainTypeName();
	}
}

public boolean isEmpty() {
	return (this.currentPackage == null) && (this.imports == null) && (this.types == null);
}

public boolean isPackageInfo() {
	return CharOperation.equals(getMainTypeName(), TypeConstants.PACKAGE_INFO_NAME);
}

public boolean isModuleInfo() {
	return CharOperation.equals(getMainTypeName(), TypeConstants.MODULE_INFO_NAME);
}

public boolean isSuppressed(CategorizedProblem problem) {
	if (this.suppressWarningsCount == 0) return false;
	int irritant = ProblemReporter.getIrritant(problem.getID());
	if (irritant == 0) return false;
	int start = problem.getSourceStart();
	int end = problem.getSourceEnd();
	nextSuppress: for (int iSuppress = 0, suppressCount = this.suppressWarningsCount; iSuppress < suppressCount; iSuppress++) {
		long position = this.suppressWarningScopePositions[iSuppress];
		int startSuppress = (int) (position >>> 32);
		int endSuppress = (int) position;
		if (start < startSuppress) continue nextSuppress;
		if (end > endSuppress) continue nextSuppress;
		if (this.suppressWarningIrritants[iSuppress].isSet(irritant))
			return true;
	}
	return false;
}

public boolean hasFunctionalTypes() {
	return this.compilationResult.hasFunctionalTypes;
}

@Override
public boolean hasErrors() {
	return this.ignoreFurtherInvestigation;
}

@Override
public StringBuffer print(int indent, StringBuffer output) {
	if (this.currentPackage != null) {
//{ObjectTeams: package can have "team" modifier:
/* orig:
		printIndent(indent, output).append("package "); //$NON-NLS-1$
  :giro */
		printIndent(indent, output);
		if ((this.currentPackage.modifiers & ExtraCompilerModifiers.AccTeam) != 0)
			output.append("team ");      //$NON-NLS-1$
		output.append("package ");       //$NON-NLS-1$
// SH}
		this.currentPackage.print(0, output, false).append(";\n"); //$NON-NLS-1$
	}
	if (this.imports != null)
		for (int i = 0; i < this.imports.length; i++) {
			printIndent(indent, output).append("import "); //$NON-NLS-1$
			ImportReference currentImport = this.imports[i];
			if (currentImport.isStatic()) {
				output.append("static "); //$NON-NLS-1$
			}
//{ObjectTeams:
			else if (currentImport.isBase()) {
				output.append("base "); //$NON-NLS-1$
			}
// SH}
			currentImport.print(0, output).append(";\n"); //$NON-NLS-1$
		}
	if (this.moduleDeclaration != null) {
		this.moduleDeclaration.print(indent, output).append("\n"); //$NON-NLS-1$
	} else if (this.types != null) {
		for (int i = 0; i < this.types.length; i++) {
			this.types[i].print(indent, output).append("\n"); //$NON-NLS-1$
		}
	}
	return output;
}

/*
 * Force inner local types to update their innerclass emulation
 */
public void propagateInnerEmulationForAllLocalTypes() {
	this.isPropagatingInnerClassEmulation = true;
	for (int i = 0, max = this.localTypeCount; i < max; i++) {
		LocalTypeBinding localType = this.localTypes[i];
		// only propagate for reachable local types
		if ((localType.scope.referenceType().bits & IsReachable) != 0) {
			localType.updateInnerEmulationDependents();
		}
	}
}

public void recordStringLiteral(StringLiteral literal, boolean fromRecovery) {
	if (this.stringLiteralsStart != null) {
		if (this.stringLiteralsStart.contains(literal.sourceStart)) return;
		this.stringLiteralsStart.add(literal.sourceStart);
	} else if (fromRecovery) {
		this.stringLiteralsStart = new HashSetOfInt(this.stringLiteralsPtr + STRING_LITERALS_INCREMENT);
		for (int i = 0; i < this.stringLiteralsPtr; i++) {
			this.stringLiteralsStart.add(this.stringLiterals[i].sourceStart);
		}

		if (this.stringLiteralsStart.contains(literal.sourceStart)) return;
		this.stringLiteralsStart.add(literal.sourceStart);
	}

	if (this.stringLiterals == null) {
		this.stringLiterals = new StringLiteral[STRING_LITERALS_INCREMENT];
		this.stringLiteralsPtr = 0;
	} else {
		int stackLength = this.stringLiterals.length;
		if (this.stringLiteralsPtr == stackLength) {
			System.arraycopy(
				this.stringLiterals,
				0,
				this.stringLiterals = new StringLiteral[stackLength + STRING_LITERALS_INCREMENT],
				0,
				stackLength);
		}
	}
	this.stringLiterals[this.stringLiteralsPtr++] = literal;
}
private boolean isLambdaExpressionCopyContext(ReferenceContext context) {
	if (context instanceof LambdaExpression && context != ((LambdaExpression) context).original())
		return true; // Do not record from copies. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=441929
	Scope cScope = context instanceof AbstractMethodDeclaration ? ((AbstractMethodDeclaration) context).scope :
		context instanceof TypeDeclaration ? ((TypeDeclaration) context).scope : 
		context instanceof LambdaExpression ? ((LambdaExpression) context).scope :
			null;
	return cScope != null ? isLambdaExpressionCopyContext(cScope.parent.referenceContext()) : false;
}

//{ObjectTeams: decapsulation warning needs to check before entering warning
/**
 * @param problemID the problem to check
 * @param start
 * @param end
 * @param foundIrritants if a suppress warning has been used record that fact here, if recording is not desired null may be passed.
 */
public boolean isWarningSuppressedAt(int problemID, int start, int end, IrritantSet[] foundIrritants) {
	for (int j = 0, max = this.suppressWarningsCount; j < max; j++) {
		long position = this.suppressWarningScopePositions[j];
		int startSuppress = (int) (position >>> 32);
		int endSuppress = (int) position;
		if (start < startSuppress) continue;
		if (end > endSuppress) continue;
		int irritant = ProblemReporter.getIrritant(problemID);
		// record the fact that this suppress has been used:
		if (this.suppressWarningIrritants[j].isSet(irritant)) {
			if (foundIrritants != null) {
				if (foundIrritants[j] == null)
					foundIrritants[j] = new IrritantSet(irritant);
				else
					foundIrritants[j].set(irritant);
			}
			return true;
		}
	}
	return false;
}
// SH}

public void recordSuppressWarnings(IrritantSet irritants, Annotation annotation, int scopeStart, int scopeEnd, ReferenceContext context) {
	if (isLambdaExpressionCopyContext(context))
		return; // Do not record from copies. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=441929
		
	if (this.suppressWarningIrritants == null) {
		this.suppressWarningIrritants = new IrritantSet[3];
		this.suppressWarningAnnotations = new Annotation[3];
		this.suppressWarningScopePositions = new long[3];
	} else if (this.suppressWarningIrritants.length == this.suppressWarningsCount) {
		System.arraycopy(this.suppressWarningIrritants, 0,this.suppressWarningIrritants = new IrritantSet[2*this.suppressWarningsCount], 0, this.suppressWarningsCount);
		System.arraycopy(this.suppressWarningAnnotations, 0,this.suppressWarningAnnotations = new Annotation[2*this.suppressWarningsCount], 0, this.suppressWarningsCount);
		System.arraycopy(this.suppressWarningScopePositions, 0,this.suppressWarningScopePositions = new long[2*this.suppressWarningsCount], 0, this.suppressWarningsCount);
	}
	final long scopePositions = ((long)scopeStart<<32) + scopeEnd;
	for (int i = 0, max = this.suppressWarningsCount; i < max; i++) {
		if (this.suppressWarningAnnotations[i] == annotation
				&& this.suppressWarningScopePositions[i] == scopePositions
				&& this.suppressWarningIrritants[i].hasSameIrritants(irritants)) {
			// annotation data already recorded
			return;
		}
	}
	this.suppressWarningIrritants[this.suppressWarningsCount] = irritants;
	this.suppressWarningAnnotations[this.suppressWarningsCount] = annotation;
	this.suppressWarningScopePositions[this.suppressWarningsCount++] = scopePositions;
}

/*
 * Keep track of all local types, so as to update their innerclass
 * emulation later on.
 */
public void record(LocalTypeBinding localType) {
	if (this.localTypeCount == 0) {
		this.localTypes = new LocalTypeBinding[5];
	} else if (this.localTypeCount == this.localTypes.length) {
		System.arraycopy(this.localTypes, 0, (this.localTypes = new LocalTypeBinding[this.localTypeCount * 2]), 0, this.localTypeCount);
	}
	this.localTypes[this.localTypeCount++] = localType;
}

/*
 * Keep track of all lambda/method reference expressions, so as to be able to look it up later without 
 * having to traverse AST. Return the "ordinal" returned by the enclosing type.
 */
public int record(FunctionalExpression expression) {
	if (this.functionalExpressionsCount == 0) {
		this.functionalExpressions = new FunctionalExpression[5];
	} else if (this.functionalExpressionsCount == this.functionalExpressions.length) {
		System.arraycopy(this.functionalExpressions, 0, (this.functionalExpressions = new FunctionalExpression[this.functionalExpressionsCount * 2]), 0, this.functionalExpressionsCount);
	}
	this.functionalExpressions[this.functionalExpressionsCount++] = expression;
	return expression.enclosingScope.classScope().referenceContext.record(expression);
}

//{ObjectTeams: should only be called by Dependencies!
// SH}
public void resolve() {
	int startingTypeIndex = 0;
	boolean isPackageInfo = isPackageInfo();
	if (this.types != null && isPackageInfo) {
		// resolve synthetic type declaration
		final TypeDeclaration syntheticTypeDeclaration = this.types[0];
		// set empty javadoc to avoid missing warning (see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=95286)
		if (syntheticTypeDeclaration.javadoc == null) {
			syntheticTypeDeclaration.javadoc = new Javadoc(syntheticTypeDeclaration.declarationSourceStart, syntheticTypeDeclaration.declarationSourceStart);
		}
		syntheticTypeDeclaration.resolve(this.scope);
		/*
		 * resolve javadoc package if any, skip this step if we don't have a valid scope due to an earlier error (bug 252555)
		 * we do it now as the javadoc in the fake type won't be resolved. The peculiar usage of MethodScope to resolve the
		 * package level javadoc is because the CU level resolve method	is a NOP to mimic Javadoc's behavior and can't be used
		 * as such.
		 */
		if (this.javadoc != null && syntheticTypeDeclaration.staticInitializerScope != null) {
			this.javadoc.resolve(syntheticTypeDeclaration.staticInitializerScope);
		}
		startingTypeIndex = 1;
	} else {
		// resolve compilation unit javadoc package if any
		if (this.javadoc != null) {
			this.javadoc.resolve(this.scope);
		}
	}
	if (this.currentPackage != null && this.currentPackage.annotations != null && !isPackageInfo) {
		this.scope.problemReporter().invalidFileNameForPackageAnnotations(this.currentPackage.annotations[0]);
	}
	try {
		if (this.types != null) {
			for (int i = startingTypeIndex, count = this.types.length; i < count; i++) {
				this.types[i].resolve(this.scope);
			}
		}
//{ObjectTeams: postponed to analyseCode():
/* orig:
		if (!this.compilationResult.hasMandatoryErrors()) checkUnusedImports();
  :giro */
	  if (!isRoleUnit())
// SH}
		reportNLSProblems();
	} catch (AbortCompilationUnit e) {
		this.ignoreFurtherInvestigation = true;
		return;
	}
}

//{ObjectTeams: accessible for TypeDeclaration.resolve():
/* orig:
private void reportNLSProblems() {
  :giro */
void reportNLSProblems() {
// SH}
	if (this.nlsTags != null || this.stringLiterals != null) {
		final int stringLiteralsLength = this.stringLiteralsPtr;
		final int nlsTagsLength = this.nlsTags == null ? 0 : this.nlsTags.length;
		if (stringLiteralsLength == 0) {
			if (nlsTagsLength != 0) {
				for (int i = 0; i < nlsTagsLength; i++) {
					NLSTag tag = this.nlsTags[i];
					if (tag != null) {
						this.scope.problemReporter().unnecessaryNLSTags(tag.start, tag.end);
					}
				}
			}
		} else if (nlsTagsLength == 0) {
			// resize string literals
			if (this.stringLiterals.length != stringLiteralsLength) {
				System.arraycopy(this.stringLiterals, 0, (this.stringLiterals = new StringLiteral[stringLiteralsLength]), 0, stringLiteralsLength);
			}
			Arrays.sort(this.stringLiterals, STRING_LITERAL_COMPARATOR);
			for (int i = 0; i < stringLiteralsLength; i++) {
				this.scope.problemReporter().nonExternalizedStringLiteral(this.stringLiterals[i]);
			}
		} else {
			// need to iterate both arrays to find non matching elements
			if (this.stringLiterals.length != stringLiteralsLength) {
				System.arraycopy(this.stringLiterals, 0, (this.stringLiterals = new StringLiteral[stringLiteralsLength]), 0, stringLiteralsLength);
			}
			Arrays.sort(this.stringLiterals, STRING_LITERAL_COMPARATOR);
			int indexInLine = 1;
			int lastLineNumber = -1;
			StringLiteral literal = null;
			int index = 0;
			int i = 0;
			stringLiteralsLoop: for (; i < stringLiteralsLength; i++) {
				literal = this.stringLiterals[i];
				final int literalLineNumber = literal.lineNumber;
				if (lastLineNumber != literalLineNumber) {
					indexInLine = 1;
					lastLineNumber = literalLineNumber;
				} else {
					indexInLine++;
				}
				if (index < nlsTagsLength) {
					nlsTagsLoop: for (; index < nlsTagsLength; index++) {
						NLSTag tag = this.nlsTags[index];
						if (tag == null) continue nlsTagsLoop;
						int tagLineNumber = tag.lineNumber;
						if (literalLineNumber < tagLineNumber) {
							this.scope.problemReporter().nonExternalizedStringLiteral(literal);
							continue stringLiteralsLoop;
						} else if (literalLineNumber == tagLineNumber) {
							if (tag.index == indexInLine) {
								this.nlsTags[index] = null;
								index++;
								continue stringLiteralsLoop;
							} else {
								nlsTagsLoop2: for (int index2 = index + 1; index2 < nlsTagsLength; index2++) {
									NLSTag tag2 = this.nlsTags[index2];
									if (tag2 == null) continue nlsTagsLoop2;
									int tagLineNumber2 = tag2.lineNumber;
									if (literalLineNumber == tagLineNumber2) {
										if (tag2.index == indexInLine) {
											this.nlsTags[index2] = null;
											continue stringLiteralsLoop;
										} else {
											continue nlsTagsLoop2;
										}
									} else {
										this.scope.problemReporter().nonExternalizedStringLiteral(literal);
										continue stringLiteralsLoop;
									}
								}
								this.scope.problemReporter().nonExternalizedStringLiteral(literal);
								continue stringLiteralsLoop;
							}
						} else {
							this.scope.problemReporter().unnecessaryNLSTags(tag.start, tag.end);
							continue nlsTagsLoop;
						}
					}
				}
				// all nls tags have been processed, so remaining string literals are not externalized
				break stringLiteralsLoop;
			}
			for (; i < stringLiteralsLength; i++) {
				this.scope.problemReporter().nonExternalizedStringLiteral(this.stringLiterals[i]);
			}
			if (index < nlsTagsLength) {
				for (; index < nlsTagsLength; index++) {
					NLSTag tag = this.nlsTags[index];
					if (tag != null) {
						this.scope.problemReporter().unnecessaryNLSTags(tag.start, tag.end);
					}
				}
			}
		}
	}
}

@Override
public void tagAsHavingErrors() {
	this.ignoreFurtherInvestigation = true;
}

@Override
public void tagAsHavingIgnoredMandatoryErrors(int problemId) {
	// Nothing to do for this context;
}

//{ObjectTeams: and let us remove it again:
@Override
public void resetErrorFlag() {
	this.ignoreFurtherInvestigation = false;
}
// SH}

public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope) {
	traverse(visitor, unitScope, true);
}
public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope, boolean skipOnError) {
	if (skipOnError && this.ignoreFurtherInvestigation)
		return;
	try {
		if (visitor.visit(this, this.scope)) {
			if (this.types != null && isPackageInfo()) {
	            // resolve synthetic type declaration
				final TypeDeclaration syntheticTypeDeclaration = this.types[0];
				// resolve javadoc package if any
				final MethodScope methodScope = syntheticTypeDeclaration.staticInitializerScope;
				// Don't traverse in null scope and invite trouble a la bug 252555.
				if (this.javadoc != null && methodScope != null) {
					this.javadoc.traverse(visitor, methodScope);
				}
				// Don't traverse in null scope and invite trouble a la bug 252555.
				if (this.currentPackage != null && methodScope != null) {
					final Annotation[] annotations = this.currentPackage.annotations;
					if (annotations != null) {
						int annotationsLength = annotations.length;
						for (int i = 0; i < annotationsLength; i++) {
							annotations[i].traverse(visitor, methodScope);
						}
					}
				}
			}
			if (this.currentPackage != null) {
				this.currentPackage.traverse(visitor, this.scope);
			}
			if (this.imports != null) {
				int importLength = this.imports.length;
				for (int i = 0; i < importLength; i++) {
					this.imports[i].traverse(visitor, this.scope);
				}
			}
			if (this.types != null) {
				int typesLength = this.types.length;
				for (int i = 0; i < typesLength; i++) {
					this.types[i].traverse(visitor, this.scope);
				}
			}
			if (this.isModuleInfo() && this.moduleDeclaration != null) {
				this.moduleDeclaration.traverse(visitor, this.scope);
			}
		}
		visitor.endVisit(this, this.scope);
	} catch (AbortCompilationUnit e) {
		// ignore
	}
}
//{ObjectTeams
/**
 * Does the CUD represent a role file?
 */
public boolean isRoleUnit() {
	if (this.types != null  && this.types.length > 0) {
		TypeDeclaration t1 = this.types[0];
		return (t1.modifiers & ExtraCompilerModifiers.AccRole) != 0;
	}
	return false;
}
// SH}
public ModuleBinding module(LookupEnvironment environment) {
	if (this.moduleDeclaration != null) {
		ModuleBinding binding = this.moduleDeclaration.binding;
		if (binding != null)
			return binding;
	}
	if (this.compilationResult != null) {
		ICompilationUnit compilationUnit = this.compilationResult.compilationUnit;
		if (compilationUnit != null)
			return compilationUnit.module(environment);
	}
	return environment.module;
}
}
