package org.eclipse.jdt.internal.compiler.ast;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.problem.*;
import org.eclipse.jdt.internal.compiler.util.*;

public class CompilationUnitDeclaration extends AstNode implements ProblemSeverities, ReferenceContext {
	public ImportReference currentPackage;
	public ImportReference[] imports;
	public TypeDeclaration[] types;
	//public char[][] name;
	
	public boolean ignoreFurtherInvestigation = false; // once pointless to investigate due to errors
	public boolean ignoreMethodBodies = false;
	/*
	lookup is done first in the CompilationUnit then 
	on the explicit import types then in the current
	pakage and finaly into the on demand imports.
	*/
	public CompilationUnitScope scope;
	public ProblemReporter problemReporter;
	public CompilationResult compilationResult;
	//public ProblemHandler.Policy handlingPolicy;

	private LocalTypeBinding[] allLocalTypes;
	public boolean isPropagatingInnerClassEmulation;
public CompilationUnitDeclaration(ProblemReporter problemReporter, CompilationResult compilationResult, int sourceLength) {

	this.problemReporter = problemReporter;
	this.compilationResult = compilationResult;
	
	//by definition of a compilation unit....
	sourceStart = 0;
	sourceEnd = sourceLength - 1;
	
}
/*
 *	We cause the compilation task to abort to a given extent.
 */
public void abort(int abortLevel) {

	switch (abortLevel) {
		case AbortType :
			throw new AbortType(compilationResult);
		case AbortMethod :
			throw new AbortMethod(compilationResult);
		default :
			throw new AbortCompilationUnit(compilationResult);
	}
}
/*
 * Dispatch code analysis AND request saturation of inner emulation
 */
public void analyseCode() {
	if (ignoreFurtherInvestigation)
		return;
	try {
		if (types != null) {
			for (int i = 0, count = types.length; i < count; i++) {
				types[i].analyseCode(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() {

	ClassFile[] classFiles = compilationResult.getClassFiles();
	for (int i = 0, max = classFiles.length; i < max; i++){
		// clear the classFile back pointer to the bindings
		ClassFile classFile = classFiles[i];
		// null out the type's scope backpointers
	 	((SourceTypeBinding) classFile.referenceBinding).scope = null;
		// null out the classfile backpointer to a type binding
		classFile.referenceBinding = null;
		classFile.codeStream = null; // codeStream holds onto ast and scopes
		classFile.innerClassesBindings = null;
	}
}
public CompilationResult compilationResult(){
	return compilationResult;
}
/*
 * 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
 * eg. 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;
}
/**
 * Bytecode generation
 */
public void generateCode() {
	if (ignoreFurtherInvestigation) {
		if (types != null) {
			for (int i = 0, count = types.length; i < count; i++){
				types[i].ignoreFurtherInvestigation = true; // propagate the flag to request problem type creation
				types[i].generateCode(scope);
			}
		}
		return;
	}
	try {
		if (types != null) {
			for (int i = 0, count = types.length; i < count; i++)
				types[i].generateCode(scope);
		}
	} catch (AbortCompilationUnit e) {
	}
}
public char[] getFileName() {
	return compilationResult.getFileName();
}
public char[] getMainTypeName() {
	if (compilationResult.compilationUnit == null) {
		char[] fileName = 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 compilationResult.compilationUnit.getMainTypeName();
	}
}
public boolean isEmpty() {
	
	return 	(currentPackage == null) 
			&& (imports == null)
			&& (types == null);}
/*
 * Force inner local types to update their innerclass emulation
 */
public void propagateInnerEmulationForAllLocalTypes() {

	isPropagatingInnerClassEmulation = true;
	if (allLocalTypes != null) {
		for (int i = 0, max = allLocalTypes.length; i < max; i++) {
			allLocalTypes[i].updateInnerEmulationDependents();
		}
	}
}
/*
 * Keep track of all local types, so as to update their innerclass
 * emulation later on.
 */ 
public void record(LocalTypeBinding localType){
	if (allLocalTypes == null){
		allLocalTypes = new LocalTypeBinding[]{ localType };
	} else {
		int length = allLocalTypes.length;
		System.arraycopy(allLocalTypes, 0, (allLocalTypes = new LocalTypeBinding[length+1]), 0, length);
		allLocalTypes[length] = localType; 
	}
}
public void resolve() {
	try {
		if (types != null)
			for (int i = 0, count = types.length; i < count; i++)
				types[i].resolve(scope);
	} catch (AbortCompilationUnit e) {
		this.ignoreFurtherInvestigation = true;
		return;
	}
}
public void tagAsHavingErrors(){
	ignoreFurtherInvestigation = true;
}
public String toString(int tab) {
	/*very slow code*/

	String s = ""/*nonNLS*/;
	if (currentPackage != null)
		s = tabString(tab) + "package "/*nonNLS*/ + currentPackage.toString(0, false) + ";\n"/*nonNLS*/;

	if (imports != null)
		for (int i = 0; i < imports.length; i++) {
			s += tabString(tab) + "import "/*nonNLS*/ + imports[i].toString() + ";\n"/*nonNLS*/;
		};

	if (types != null)
		for (int i = 0; i < types.length; i++) {
			s +=  types[i].toString(tab) + "\n"/*nonNLS*/;
		}
	return s;
}
public void traverse(IAbstractSyntaxTreeVisitor visitor, CompilationUnitScope scope) {
	if (ignoreFurtherInvestigation)
		return;
	try {
		if (visitor.visit(this, scope)) {
			if (imports != null) {
				int importLength = imports.length;
				for (int i = 0; i < importLength; i++)
					imports[i].traverse(visitor, scope);
			}
			if (types != null) {
				int typesLength = types.length;
				for (int i = 0; i < typesLength; i++)
					types[i].traverse(visitor, scope);
			}
		}
	} catch (AbortCompilationUnit e) {
	}
}
}
