package org.eclipse.jdt.internal.compiler;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
/**
 * This is the public entry point to resolve type hierarchies.
 *
 * When requesting additional types from the name environment, the resolver
 * accepts all forms (binary, source & compilation unit) for additional types.
 *
 * Side notes: Binary types already know their resolved supertypes so this
 * only makes sense for source types. Even though the compiler finds all binary
 * types to complete the hierarchy of a given source type, is there any reason
 * why the requestor should be informed that binary type X subclasses Y &
 * implements I & J?
 */

import org.eclipse.jdt.internal.compiler.env.*;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.parser.*;
import org.eclipse.jdt.internal.compiler.problem.*;
import org.eclipse.jdt.internal.compiler.util.*;

import java.util.Locale;
import java.util.Map;

public class HierarchyResolver implements ITypeRequestor {
	IHierarchyRequestor requestor;
	LookupEnvironment lookupEnvironment;

	private int typeIndex;
	private IGenericType[] typeModels;
	private ReferenceBinding[] typeBindings;
	private ReferenceBinding focusType;
	
public HierarchyResolver(
	INameEnvironment nameEnvironment,
	IErrorHandlingPolicy policy,
	Map settings,
	IHierarchyRequestor requestor,
	IProblemFactory problemFactory) {

	// create a problem handler given a handling policy
	CompilerOptions options = settings == null ? new CompilerOptions() : new CompilerOptions(settings);
	ProblemReporter problemReporter = new ProblemReporter(policy, options, problemFactory);
	this.lookupEnvironment = new LookupEnvironment(this, options, problemReporter, nameEnvironment);
	this.requestor = requestor;

	this.typeIndex = -1;
	this.typeModels = new IGenericType[5];
	this.typeBindings = new ReferenceBinding[5];
}
public HierarchyResolver(INameEnvironment nameEnvironment, IHierarchyRequestor requestor, IProblemFactory problemFactory) {
	this(
		nameEnvironment,
		DefaultErrorHandlingPolicies.exitAfterAllProblems(),
		null,
		requestor,
		problemFactory);
}
/**
 * Add an additional binary type
 */

public void accept(IBinaryType binaryType, PackageBinding packageBinding) {
	BinaryTypeBinding typeBinding = lookupEnvironment.createBinaryTypeFrom(binaryType, packageBinding);
	remember(binaryType, typeBinding);
}
/**
 * Add an additional compilation unit.
 */

public void accept(ICompilationUnit sourceUnit) {
	//System.out.println("Cannot accept compilation units inside the HierarchyResolver.");
	lookupEnvironment.problemReporter.abortDueToInternalError(
		new StringBuffer(Util.bind("accept.cannot")) //$NON-NLS-1$
			.append(sourceUnit.getFileName())
			.toString());
}
/**
 * Add additional source types
 */

public void accept(ISourceType[] sourceTypes, PackageBinding packageBinding) {
	CompilationResult result = new CompilationResult(sourceTypes[0].getFileName(), 1, 1);
	CompilationUnitDeclaration unit =
		SourceTypeConverter.buildCompilationUnit(sourceTypes, false, true, lookupEnvironment.problemReporter, result);

	if (unit != null) {
		lookupEnvironment.buildTypeBindings(unit);
		for (int i = 0, length = sourceTypes.length; i < length; i++) {
			rememberWithMemberTypes(sourceTypes[i], unit.types[i].binding);
		}

		lookupEnvironment.completeTypeBindings(unit, false);
	}
}
private void remember(IGenericType suppliedType, ReferenceBinding typeBinding) {
	if (typeBinding == null) return;
	
	if (!subOrSuperOfFocus(typeBinding)) {
		return; // ignore types outside of hierarchy
	}

	if (++typeIndex == typeModels.length) {
		System.arraycopy(typeModels, 0, typeModels = new IGenericType[typeIndex * 2], 0, typeIndex);
		System.arraycopy(typeBindings, 0, typeBindings = new ReferenceBinding[typeIndex * 2], 0, typeIndex);
	}
	typeModels[typeIndex] = suppliedType;
	typeBindings[typeIndex] = typeBinding;
}
private void rememberWithMemberTypes(TypeDeclaration typeDeclaration, HierarchyType enclosingType, ICompilationUnit unit) {

	if (typeDeclaration.binding == null) return;

	HierarchyType hierarchyType = new HierarchyType(
		enclosingType, 
		!typeDeclaration.isInterface(),
		typeDeclaration.name,
		typeDeclaration.binding.modifiers,
		unit);
	remember(hierarchyType, typeDeclaration.binding);

	// propagate into member types
	if (typeDeclaration.memberTypes == null) return;
	MemberTypeDeclaration[] memberTypes = typeDeclaration.memberTypes;
	for (int i = 0, max = memberTypes.length; i < max; i++){
		rememberWithMemberTypes(memberTypes[i], hierarchyType, unit);
	}
}
private void rememberWithMemberTypes(ISourceType suppliedType, ReferenceBinding typeBinding) {
	if (typeBinding == null) return;

	remember(suppliedType, typeBinding);

	ISourceType[] memberTypes = suppliedType.getMemberTypes();
	if (memberTypes == null) return;
	for (int m = memberTypes.length; --m >= 0;) {
		ISourceType memberType = memberTypes[m];
		rememberWithMemberTypes(memberType, typeBinding.getMemberType(memberType.getName()));
	}
}
private void reportHierarchy() {
	// ensure each binary type knows its supertypes before reporting the hierarchy
	int problemLength = typeIndex+1;
	boolean[] typesWithProblem = new boolean[problemLength];
	for (int current = 0; current <= typeIndex; current++) { // typeIndex may continue to grow
		ReferenceBinding typeBinding = typeBindings[current];
		if (typeBinding.isBinaryBinding()) {
			// fault in its hierarchy...
			try {
				typeBinding.superclass();
				typeBinding.superInterfaces();
			} catch (AbortCompilation e) {
				if (current >= problemLength) {
					System.arraycopy(typesWithProblem, 0, typesWithProblem = new boolean[current+1], 0, problemLength);
					problemLength = current+1;
				}
				typesWithProblem[current] = true;
			}
		}
	}

	for (int current = typeIndex; current >= 0; current--) {
		IGenericType suppliedType = typeModels[current];
		ReferenceBinding typeBinding = typeBindings[current];
		if (current < problemLength && typesWithProblem[current]) continue;

		ReferenceBinding superBinding = typeBinding.superclass();
		IGenericType superclass = null;
		if (superBinding != null) {
			for (int t = typeIndex; t >= 0; t--) {
				if (typeBindings[t] == superBinding) {
					superclass = typeModels[t];
					break;
				}
			}
		}

		ReferenceBinding[] interfaceBindings = typeBinding.superInterfaces();
		int length = interfaceBindings.length;
		IGenericType[] superinterfaces = new IGenericType[length];
		next : for (int i = 0; i < length; i++) {
			ReferenceBinding interfaceBinding = interfaceBindings[i];
			for (int t = typeIndex; t >= 0; t--) {
				if (typeBindings[t] == interfaceBinding) {
					superinterfaces[i] = typeModels[t];
					continue next;
				}
			}
		}
		if (typeBinding.isInterface()){ // do not connect interfaces to Object
			superclass = null;
		}
		requestor.connect(suppliedType, superclass, superinterfaces);
	}
}
private void reset(){
	lookupEnvironment.reset();

	this.typeIndex = -1;
	this.typeModels = new IGenericType[5];
	this.typeBindings = new ReferenceBinding[5];
}
/**
 * Resolve the supertypes for the supplied source types.
 * Inform the requestor of the resolved supertypes for each
 * supplied source type using:
 *    connect(ISourceType suppliedType, IGenericType superclass, IGenericType[] superinterfaces)
 *
 * Also inform the requestor of the supertypes of each
 * additional requested super type which is also a source type
 * instead of a binary type.
 */

public void resolve(IGenericType[] suppliedTypes) {
	resolve(suppliedTypes, null);
}
/**
 * Resolve the supertypes for the supplied source types.
 * Inform the requestor of the resolved supertypes for each
 * supplied source type using:
 *    connect(ISourceType suppliedType, IGenericType superclass, IGenericType[] superinterfaces)
 *
 * Also inform the requestor of the supertypes of each
 * additional requested super type which is also a source type
 * instead of a binary type.
 */

public void resolve(IGenericType[] suppliedTypes, ICompilationUnit[] sourceUnits) {
	try {
		int suppliedLength = suppliedTypes == null ? 0 : suppliedTypes.length;
		int sourceLength = sourceUnits == null ? 0 : sourceUnits.length;
		CompilationUnitDeclaration[] units = new CompilationUnitDeclaration[suppliedLength + sourceLength];
		
		// build type bindings
		for (int i = 0; i < suppliedLength; i++) {
			if (suppliedTypes[i].isBinaryType()) {
				IBinaryType binaryType = (IBinaryType) suppliedTypes[i];
				try {
					remember(binaryType, lookupEnvironment.cacheBinaryType(binaryType, false));
				} catch (AbortCompilation e) {
					// classpath problem for this type: ignore
				}
			} else {
				// must start with the top level type
				ISourceType topLevelType = (ISourceType) suppliedTypes[i];
				while (topLevelType.getEnclosingType() != null)
					topLevelType = topLevelType.getEnclosingType();
				CompilationResult result = new CompilationResult(topLevelType.getFileName(), i, suppliedLength);
				units[i] = SourceTypeConverter.buildCompilationUnit(new ISourceType[]{topLevelType}, false, true, lookupEnvironment.problemReporter, result);
				if (units[i] != null) {
					try {
						lookupEnvironment.buildTypeBindings(units[i]);
					} catch (AbortCompilation e) {
						// classpath problem for this type: ignore
					}
				}
			}
		}
		for (int i = 0; i < sourceLength; i++){
			ICompilationUnit sourceUnit = sourceUnits[i];
			CompilationResult unitResult = new CompilationResult(sourceUnit, suppliedLength+i, suppliedLength+sourceLength); 
			CompilerOptions options = new CompilerOptions();
			Parser parser = new Parser(lookupEnvironment.problemReporter, false, options.getAssertMode());
			CompilationUnitDeclaration parsedUnit = parser.dietParse(sourceUnit, unitResult);
			if (parsedUnit != null) {
				units[suppliedLength+i] = parsedUnit;
				lookupEnvironment.buildTypeBindings(parsedUnit);
			}
		}
		
		// complete type bindings (ie. connect super types) and remember them
		for (int i = 0; i < suppliedLength; i++) {
			if (!suppliedTypes[i].isBinaryType()) { // note that binary types have already been remembered above
				CompilationUnitDeclaration parsedUnit = units[i];
				if (parsedUnit != null) {
					// must start with the top level type
					ISourceType topLevelType = (ISourceType) suppliedTypes[i];
					suppliedTypes[i] = null; // no longer needed pass this point				
					while (topLevelType.getEnclosingType() != null)
						topLevelType = topLevelType.getEnclosingType();
					try {
						lookupEnvironment.completeTypeBindings(parsedUnit, false);
						rememberWithMemberTypes(topLevelType, parsedUnit.types[0].binding);
					} catch (AbortCompilation e) {
						// classpath problem for this type: ignore
					}
				}
			}
		}
		for (int i = 0; i < sourceLength; i++) {
			CompilationUnitDeclaration parsedUnit = units[suppliedLength+i];
			if (parsedUnit != null) {
				lookupEnvironment.completeTypeBindings(parsedUnit, false);
				int typeCount = parsedUnit.types == null ? 0 : parsedUnit.types.length;
				ICompilationUnit sourceUnit = sourceUnits[i];
				sourceUnits[i] = null; // no longer needed pass this point
				for (int j = 0; j < typeCount; j++){
					rememberWithMemberTypes(parsedUnit.types[j], null, sourceUnit);
				}
			}
		}

		reportHierarchy();
		
	} catch (ClassCastException e){ // work-around for 1GF5W1S - can happen in case duplicates are fed to the hierarchy with binaries hiding sources
	} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
	} finally {
		reset();
	}
}
/**
 * Resolve the supertypes for the supplied source type.
 * Inform the requestor of the resolved supertypes using:
 *    connect(ISourceType suppliedType, IGenericType superclass, IGenericType[] superinterfaces)
 */

public void resolve(IGenericType suppliedType) {
	try {
		if (suppliedType.isBinaryType()) {
			remember(suppliedType, lookupEnvironment.cacheBinaryType((IBinaryType) suppliedType));
		} else {
			// must start with the top level type
			ISourceType topLevelType = (ISourceType) suppliedType;
			while (topLevelType.getEnclosingType() != null)
				topLevelType = topLevelType.getEnclosingType();
			CompilationResult result = new CompilationResult(topLevelType.getFileName(), 1, 1);
			CompilationUnitDeclaration unit =
				SourceTypeConverter.buildCompilationUnit(new ISourceType[]{topLevelType}, false, true, lookupEnvironment.problemReporter, result);

			if (unit != null) {
				lookupEnvironment.buildTypeBindings(unit);
				rememberWithMemberTypes(topLevelType, unit.types[0].binding);

				lookupEnvironment.completeTypeBindings(unit, false);
			}
		}
		reportHierarchy();
	} catch (AbortCompilation e) { // ignore this exception for now since it typically means we cannot find java.lang.Object
	} finally {
		reset();
	}
}
/**
 * Set the focus type (ie. the type that this resolver is computing the hierarch for.
 */
public void setFocusType(char[][] compoundName) {
	if (compoundName == null || this.lookupEnvironment == null) return;
	this.focusType = this.lookupEnvironment.askForType(compoundName);
	
	/* All siblings of the focus type were added (since this.focusType == null).
	   Remove the ones that are not part of the hierarchy
	 */
	int typeIndex = this.typeIndex;
	this.typeIndex = -1;
	ReferenceBinding[] typeBindings = this.typeBindings;
	this.typeBindings = new ReferenceBinding[5];
	IGenericType[] typeModels = this.typeModels;
	this.typeModels = new IGenericType[5];
	for (int i = 0; i <= typeIndex; i++) {
		this.remember(typeModels[i], typeBindings[i]); // will skip types not part of the hierarchy
	}
	
}
private boolean subOrSuperOfFocus(ReferenceBinding typeBinding) {
	if (this.focusType == null) return true; // accept all types (case of hierarchy in a region)
	if (this.subTypeOfType(this.focusType, typeBinding)) return true;
	if (this.subTypeOfType(typeBinding, this.focusType)) return true;
	return false;
}
private boolean subTypeOfType(ReferenceBinding subType, ReferenceBinding typeBinding) {
	if (typeBinding == null || subType == null) return false;
	if (subType == typeBinding) return true;
	if (this.subTypeOfType(subType.superclass(), typeBinding)) return true;
	ReferenceBinding[] superInterfaces = subType.superInterfaces();
	if (superInterfaces != null) {
		for (int i = 0, length = superInterfaces.length; i < length; i++) {
			if (this.subTypeOfType(superInterfaces[i], typeBinding)) return true;
		} 
	}
	return false;
}
}
