package org.eclipse.jdt.internal.compiler.ast;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
import org.eclipse.jdt.internal.compiler.IAbstractSyntaxTreeVisitor;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;

public class QualifiedAllocationExpression extends AllocationExpression {
	//qualification may be on both side
	public Expression enclosingInstance;
	public AnonymousLocalTypeDeclaration anonymousType;

public QualifiedAllocationExpression() {
	
}
public QualifiedAllocationExpression(AnonymousLocalTypeDeclaration anonymous) {
	anonymousType = anonymous ;
}
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {

	// variation on allocation, where can be specified an enclosing instance and an anonymous type

	// analyse the enclosing instance
	if (enclosingInstance != null) {
		flowInfo = enclosingInstance.analyseCode(currentScope, flowContext, flowInfo);
	}
	// process arguments
	if (arguments != null) {
		for (int i = 0, count = arguments.length; i < count; i++) {
			flowInfo = arguments[i].analyseCode(currentScope, flowContext, flowInfo);
		}
	}
	// record some dependency information for exception types
	int count;
	ReferenceBinding[] thrownExceptions;
	if ((count = (thrownExceptions = binding.thrownExceptions).length) != 0) {
		// check exception handling
		flowContext.checkExceptionHandlers(thrownExceptions, this, flowInfo, currentScope);
	}

	// analyse the anonymous nested type
	if (anonymousType != null) {
		flowInfo = anonymousType.analyseCode(currentScope, flowContext, flowInfo);
	}
	manageEnclosingInstanceAccessIfNecessary(currentScope);
	manageSyntheticAccessIfNecessary(currentScope);
	return flowInfo;
}
public Expression enclosingInstance() {
	return enclosingInstance;
}
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
	int pc = codeStream.position;
	ReferenceBinding allocatedType = binding.declaringClass;
	if (allocatedType.isLocalType()) {
		LocalTypeBinding localType = (LocalTypeBinding) allocatedType;
		localType.constantPoolName(codeStream.classFile.outerMostEnclosingClassFile().computeConstantPoolName(localType));
	}
	if (syntheticAccessor == null) {
		codeStream.new_(allocatedType);
		if (valueRequired) {
			codeStream.dup();
		}
		// better highlight for allocation: display the type individually
		codeStream.recordPositionsFrom(pc, type);
	}
	// handling innerclass instance allocation
	if (allocatedType.isNestedType()) { // make sure its name is computed before arguments, since may be necessary for argument emulation
		codeStream.generateSyntheticArgumentValues(currentScope, allocatedType, enclosingInstance(), this);
	}
	// generate the arguments for constructor
	if (arguments != null) {
		for (int i = 0, count = arguments.length; i < count; i++) {
			arguments[i].generateCode(currentScope, codeStream, true);
		}
	}
	// invoke constructor
	if (syntheticAccessor == null) {
		codeStream.invokespecial(binding);
	} else {
		codeStream.invokestatic(syntheticAccessor);
	}
	codeStream.recordPositionsFrom(pc, this);
	if (anonymousType != null) {
		anonymousType.generateCode(currentScope, codeStream);
	}
}
public boolean isSuperAccess() {
	// necessary to lookup super constructor of anonymous type
	return anonymousType != null;
}
/* Inner emulation consists in either recording a dependency 
 * link only, or performing one level of propagation.
 *
 * Dependency mechanism is used whenever dealing with source target
 * types, since by the time we reach them, we might not yet know their
 * exact need.
 */
public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope) {
	ReferenceBinding invocationType, allocatedType;

	// perform some emulation work in case there is some and we are inside a local type only
	if ((allocatedType = binding.declaringClass).isNestedType() && currentScope.enclosingSourceType().isLocalType()) {

		if (allocatedType.isLocalType()){
			((LocalTypeBinding)allocatedType).addInnerEmulationDependent(currentScope, enclosingInstance != null, false); // request cascade of accesses
		} else {
			// locally propagate, since we already now the desired shape for sure
			currentScope.propagateInnerEmulation(allocatedType, enclosingInstance != null, false); // request cascade of accesses
		}
	}
}
public TypeBinding resolveType(BlockScope scope) {
	if (anonymousType == null && enclosingInstance == null)
		return super.resolveType(scope); // added for code assist... is not possible with 'normal' code

	// Propagate the type checking to the arguments, and checks if the constructor is defined.

	// ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
	// ClassInstanceCreationExpression ::= Name '.' 'new' SimpleName '(' ArgumentListopt ')' ClassBodyopt
	// ==> by construction, when there is an enclosing instance the typename may NOT be qualified
	// ==> therefore by construction the type is always a SingleTypeReferenceType instead of being either 
	// sometime a SingleTypeReference and sometime a QualifedTypeReference

	constant = NotAConstant;
	TypeBinding enclosingInstTb = null;
	TypeBinding recType;
	if (anonymousType == null) {
		//----------------no anonymous class------------------------	
		if ((enclosingInstTb = enclosingInstance.resolveType(scope)) == null)
			return null;
		if (enclosingInstTb.isBaseType() | enclosingInstTb.isArrayType()) {
			scope.problemReporter().illegalPrimitiveOrArrayTypeForEnclosingInstance(enclosingInstTb, enclosingInstance);
			return null;
		}
		recType = ((SingleTypeReference) type).resolveTypeEnclosing(scope, (ReferenceBinding) enclosingInstTb); // will check for null after args are resolved
		TypeBinding[] argumentTypes = NoParameters;
		if (arguments != null) {
			boolean argHasError = false;
			int length = arguments.length;
			argumentTypes = new TypeBinding[length];
			for (int i = 0; i < length; i++)
				if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
					argHasError = true;
			if (argHasError)
				return recType;
		}
		if (recType == null)
			return null;
		if (!recType.canBeInstantiated()) {
			scope.problemReporter().cannotInstantiate(type, recType);
			return recType;
		}
		if ((binding = scope.getConstructor((ReferenceBinding) recType, argumentTypes, this)).isValidBinding()) {
			if (isMethodUseDeprecated(binding, scope))
				scope.problemReporter().deprecatedMethod(binding, this);

			if (arguments != null)
				for (int i = 0; i < arguments.length; i++)
					arguments[i].implicitWidening(binding.parameters[i], argumentTypes[i]);
		} else {
			if (binding.declaringClass == null)
				binding.declaringClass = (ReferenceBinding) recType;
			scope.problemReporter().invalidConstructor(this, binding);
			return recType;
		}

		// The enclosing instance must be compatible with the innermost enclosing type
		ReferenceBinding expectedType = binding.declaringClass.enclosingType();
		if (scope.areTypesCompatible(enclosingInstTb, expectedType))
			return recType;
		scope.problemReporter().typeMismatchErrorActualTypeExpectedType(enclosingInstance, enclosingInstTb, expectedType);
		return recType;
	}

	//--------------there is an anonymous type declaration-----------------
	if (enclosingInstance != null) {
		if ((enclosingInstTb = enclosingInstance.resolveType(scope)) == null)
			return null;
		if (enclosingInstTb.isBaseType() | enclosingInstTb.isArrayType()) {
			scope.problemReporter().illegalPrimitiveOrArrayTypeForEnclosingInstance(enclosingInstTb, enclosingInstance);
			return null;
		}
	}
	// due to syntax-construction, recType is a ReferenceBinding		
	recType =
		(enclosingInstance == null)
			? type.resolveType(scope)
			: ((SingleTypeReference) type).resolveTypeEnclosing(scope, (ReferenceBinding) enclosingInstTb);
	if (recType == null)
		return null;
	if (((ReferenceBinding) recType).isFinal()) {
		scope.problemReporter().anonymousClassCannotExtendFinalClass(type, recType);
		return null;
	}
	TypeBinding[] argumentTypes = NoParameters;
	if (arguments != null) {
		int length = arguments.length;
		argumentTypes = new TypeBinding[length];
		for (int i = 0; i < length; i++)
			if ((argumentTypes[i] = arguments[i].resolveType(scope)) == null)
				return null;
	}

	// an anonymous class inherits from java.lang.Object when declared "after" an interface
	ReferenceBinding superBinding = recType.isInterface() ? scope.getJavaLangObject() : (ReferenceBinding) recType;
	MethodBinding inheritedBinding = scope.getConstructor(superBinding, argumentTypes, this);
	if (!inheritedBinding.isValidBinding()) {
		if (inheritedBinding.declaringClass == null)
			inheritedBinding.declaringClass = superBinding;
		scope.problemReporter().invalidConstructor(this, inheritedBinding);
		return null;
	}
	if (enclosingInstance != null) {
		if (!scope.areTypesCompatible(enclosingInstTb, inheritedBinding.declaringClass.enclosingType())) {
			scope.problemReporter().typeMismatchErrorActualTypeExpectedType(enclosingInstance, enclosingInstTb, inheritedBinding.declaringClass.enclosingType());
			return null;
		}
	}

	// this promotion has to be done somewhere: here or inside the constructor of the
	// anonymous class. We do it here while the constructor of the inner is then easier.
	if (arguments != null)
		for (int i = 0; i < arguments.length; i++)
			arguments[i].implicitWidening(inheritedBinding.parameters[i], argumentTypes[i]);

		// Update the anonymous inner class : superclass, interface  
	scope.addAnonymousType(anonymousType, (ReferenceBinding) recType);
	anonymousType.resolve(scope);
	binding = anonymousType.createsInternalConstructorWithBinding(inheritedBinding);
	return anonymousType.binding; // 1.2 change
}
public String toStringExpression(int tab) {
	/*slow code */

	String s = ""/*nonNLS*/;
	if (enclosingInstance != null)
		s += enclosingInstance.toString() + "."/*nonNLS*/;
	s += super.toStringExpression(tab);
	if (anonymousType != null) {
		s += anonymousType.toString(tab);
	} //allows to restart just after the } one line under ....
	return s;
}
public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
	if (visitor.visit(this, scope)) {
		if (enclosingInstance != null) enclosingInstance.traverse(visitor, scope);
		type.traverse(visitor, scope);
		if (arguments != null) {
			int argumentsLength = arguments.length;
			for (int i = 0; i < argumentsLength; i++)
				arguments[i].traverse(visitor, scope);
		}
		if (anonymousType != null) anonymousType.traverse(visitor, scope);
	}
	visitor.endVisit(this, scope);
}
}
