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.codegen.*;
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) {
	}
}
}
