/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import java.util.ArrayList;

import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.parser.*;
import org.eclipse.jdt.internal.compiler.problem.*;

public class ConstructorDeclaration extends AbstractMethodDeclaration {

	public ExplicitConstructorCall constructorCall;
	
	public boolean isDefaultConstructor = false;
	public TypeParameter[] typeParameters;

	public ConstructorDeclaration(CompilationResult compilationResult){
		super(compilationResult);
	}
	
	public void analyseCode(
		ClassScope classScope,
		InitializationFlowContext initializerFlowContext,
		FlowInfo flowInfo) {

		if (ignoreFurtherInvestigation)
			return;

		if (this.binding != null && this.binding.isPrivate() && !this.binding.isPrivateUsed()) {
			if (!classScope.referenceCompilationUnit().compilationResult.hasSyntaxError()) {
				scope.problemReporter().unusedPrivateConstructor(this);
			}
		}
			
		// check constructor recursion, once all constructor got resolved
		if (isRecursive(null /*lazy initialized visited list*/)) {				
			this.scope.problemReporter().recursiveConstructorInvocation(this.constructorCall);
		}
			
		try {
			ExceptionHandlingFlowContext constructorContext =
				new ExceptionHandlingFlowContext(
					initializerFlowContext.parent,
					this,
					binding.thrownExceptions,
					scope,
					FlowInfo.DEAD_END);
			initializerFlowContext.checkInitializerExceptions(
				scope,
				constructorContext,
				flowInfo);

			// anonymous constructor can gain extra thrown exceptions from unhandled ones
			if (binding.declaringClass.isAnonymousType()) {
				ArrayList computedExceptions = constructorContext.extendedExceptions;
				if (computedExceptions != null){
					int size;
					if ((size = computedExceptions.size()) > 0){
						ReferenceBinding[] actuallyThrownExceptions;
						computedExceptions.toArray(actuallyThrownExceptions = new ReferenceBinding[size]);
						binding.thrownExceptions = actuallyThrownExceptions;
					}
				}
			}
			
			// tag parameters as being set
			if (this.arguments != null) {
				for (int i = 0, count = this.arguments.length; i < count; i++) {
					flowInfo.markAsDefinitelyAssigned(this.arguments[i].binding);
				}
			}
			
			// propagate to constructor call
			if (constructorCall != null) {
				// if calling 'this(...)', then flag all non-static fields as definitely
				// set since they are supposed to be set inside other local constructor
				if (constructorCall.accessMode == ExplicitConstructorCall.This) {
					FieldBinding[] fields = binding.declaringClass.fields();
					for (int i = 0, count = fields.length; i < count; i++) {
						FieldBinding field;
						if (!(field = fields[i]).isStatic()) {
							flowInfo.markAsDefinitelyAssigned(field);
						}
					}
				}
				flowInfo = constructorCall.analyseCode(scope, constructorContext, flowInfo);
			}
			// propagate to statements
			if (statements != null) {
				boolean didAlreadyComplain = false;
				for (int i = 0, count = statements.length; i < count; i++) {
					Statement stat = statements[i];
					if (!stat.complainIfUnreachable(flowInfo, scope, didAlreadyComplain)) {
						flowInfo = stat.analyseCode(scope, constructorContext, flowInfo);
					} else {
						didAlreadyComplain = true;
					}
				}
			}
			// check for missing returning path
			this.needFreeReturn = flowInfo.isReachable();

			// check missing blank final field initializations
			if ((constructorCall != null)
				&& (constructorCall.accessMode != ExplicitConstructorCall.This)) {
				flowInfo = flowInfo.mergedWith(constructorContext.initsOnReturn);
				FieldBinding[] fields = binding.declaringClass.fields();
				for (int i = 0, count = fields.length; i < count; i++) {
					FieldBinding field;
					if ((!(field = fields[i]).isStatic())
						&& field.isFinal()
						&& (!flowInfo.isDefinitelyAssigned(fields[i]))) {
						scope.problemReporter().uninitializedBlankFinalField(
							field,
							isDefaultConstructor ? (ASTNode) scope.referenceType() : this);
					}
				}
			}
			// check unreachable catch blocks
			constructorContext.complainIfUnusedExceptionHandlers(this);
		} catch (AbortMethod e) {
			this.ignoreFurtherInvestigation = true;
		}
	}

	/**
	 * Bytecode generation for a constructor
	 *
	 * @param classScope org.eclipse.jdt.internal.compiler.lookup.ClassScope
	 * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
	 */
	public void generateCode(ClassScope classScope, ClassFile classFile) {
		
		int problemResetPC = 0;
		if (ignoreFurtherInvestigation) {
			if (this.binding == null)
				return; // Handle methods with invalid signature or duplicates
			int problemsLength;
			IProblem[] problems =
				scope.referenceCompilationUnit().compilationResult.getProblems();
			IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
			System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
			classFile.addProblemConstructor(this, binding, problemsCopy);
			return;
		}
		try {
			problemResetPC = classFile.contentsOffset;
			this.internalGenerateCode(classScope, classFile);
		} catch (AbortMethod e) {
			if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
				// a branch target required a goto_w, restart code gen in wide mode.
				try {
					classFile.contentsOffset = problemResetPC;
					classFile.methodCount--;
					classFile.codeStream.wideMode = true; // request wide mode 
					this.internalGenerateCode(classScope, classFile); // restart method generation
				} catch (AbortMethod e2) {
					int problemsLength;
					IProblem[] problems =
						scope.referenceCompilationUnit().compilationResult.getAllProblems();
					IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
					System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
					classFile.addProblemConstructor(this, binding, problemsCopy, problemResetPC);
				}
			} else {
				int problemsLength;
				IProblem[] problems =
					scope.referenceCompilationUnit().compilationResult.getAllProblems();
				IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
				System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
				classFile.addProblemConstructor(this, binding, problemsCopy, problemResetPC);
			}
		}
	}

	public void generateSyntheticFieldInitializationsIfNecessary(
		MethodScope methodScope,
		CodeStream codeStream,
		ReferenceBinding declaringClass) {
			
		if (!declaringClass.isNestedType()) return;
		
		NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;

		SyntheticArgumentBinding[] syntheticArgs = nestedType.syntheticEnclosingInstances();
		for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length; i < max; i++) {
			SyntheticArgumentBinding syntheticArg;
			if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
				codeStream.aload_0();
				codeStream.load(syntheticArg);
				codeStream.putfield(syntheticArg.matchingField);
			}
		}
		syntheticArgs = nestedType.syntheticOuterLocalVariables();
		for (int i = 0, max = syntheticArgs == null ? 0 : syntheticArgs.length; i < max; i++) {
			SyntheticArgumentBinding syntheticArg;
			if ((syntheticArg = syntheticArgs[i]).matchingField != null) {
				codeStream.aload_0();
				codeStream.load(syntheticArg);
				codeStream.putfield(syntheticArg.matchingField);
			}
		}
	}

	private void internalGenerateCode(ClassScope classScope, ClassFile classFile) {
		
		classFile.generateMethodInfoHeader(binding);
		int methodAttributeOffset = classFile.contentsOffset;
		int attributeNumber = classFile.generateMethodInfoAttribute(this.binding);
		if ((!binding.isNative()) && (!binding.isAbstract())) {
			
			TypeDeclaration declaringType = classScope.referenceContext;
			int codeAttributeOffset = classFile.contentsOffset;
			classFile.generateCodeAttributeHeader();
			CodeStream codeStream = classFile.codeStream;
			codeStream.reset(this, classFile);

			// initialize local positions - including initializer scope.
			ReferenceBinding declaringClass = binding.declaringClass;

			int enumOffset = declaringClass.isEnum() ? 2 : 0; // String name, int ordinal
			int argSlotSize = 1 + enumOffset; // this==aload0

			if (declaringClass.isNestedType()){
				NestedTypeBinding nestedType = (NestedTypeBinding) declaringClass;
				this.scope.extraSyntheticArguments = nestedType.syntheticOuterLocalVariables();
				scope.computeLocalVariablePositions(// consider synthetic arguments if any
					nestedType.enclosingInstancesSlotSize + 1 + enumOffset,
					codeStream);
				argSlotSize += nestedType.enclosingInstancesSlotSize;
				argSlotSize += nestedType.outerLocalVariablesSlotSize;
			} else {
				scope.computeLocalVariablePositions(1 + enumOffset,  codeStream);
			}
				
			if (arguments != null) {
				for (int i = 0, max = arguments.length; i < max; i++) {
					// arguments initialization for local variable debug attributes
					LocalVariableBinding argBinding;
					codeStream.addVisibleLocalVariable(argBinding = arguments[i].binding);
					argBinding.recordInitializationStartPC(0);
					TypeBinding argType;
					if ((argType = argBinding.type) == LongBinding || (argType == DoubleBinding)) {
						argSlotSize += 2;
					} else {
						argSlotSize++;
					}
				}
			}
			
			MethodScope initializerScope = declaringType.initializerScope;
			initializerScope.computeLocalVariablePositions(argSlotSize, codeStream); // offset by the argument size (since not linked to method scope)

			boolean needFieldInitializations = constructorCall == null || constructorCall.accessMode != ExplicitConstructorCall.This;

			// post 1.4 source level, synthetic initializations occur prior to explicit constructor call
			boolean preInitSyntheticFields = scope.environment().options.targetJDK >= ClassFileConstants.JDK1_4;

			if (needFieldInitializations && preInitSyntheticFields){
				generateSyntheticFieldInitializationsIfNecessary(scope, codeStream, declaringClass);
			}			
			// generate constructor call
			if (constructorCall != null) {
				constructorCall.generateCode(scope, codeStream);
			}
			// generate field initialization - only if not invoking another constructor call of the same class
			if (needFieldInitializations) {
				if (!preInitSyntheticFields){
					generateSyntheticFieldInitializationsIfNecessary(scope, codeStream, declaringClass);
				}
				// generate user field initialization
				if (declaringType.fields != null) {
					for (int i = 0, max = declaringType.fields.length; i < max; i++) {
						FieldDeclaration fieldDecl;
						if (!(fieldDecl = declaringType.fields[i]).isStatic()) {
							fieldDecl.generateCode(initializerScope, codeStream);
						}
					}
				}
			}
			// generate statements
			if (statements != null) {
				for (int i = 0, max = statements.length; i < max; i++) {
					statements[i].generateCode(scope, codeStream);
				}
			}
			if (this.needFreeReturn) {
				codeStream.return_();
			}
			// local variable attributes
			codeStream.exitUserScope(scope);
			codeStream.recordPositionsFrom(0, this.bodyEnd);
			classFile.completeCodeAttribute(codeAttributeOffset);
			attributeNumber++;
		}
		classFile.completeMethodInfo(methodAttributeOffset, attributeNumber);

		// if a problem got reported during code gen, then trigger problem method creation
		if (ignoreFurtherInvestigation) {
			throw new AbortMethod(scope.referenceCompilationUnit().compilationResult, null);
		}
	}

	public boolean isConstructor() {

		return true;
	}

	public boolean isDefaultConstructor() {

		return this.isDefaultConstructor;
	}

	public boolean isInitializationMethod() {

		return true;
	}

	/*
	 * Returns true if the constructor is directly involved in a cycle.
	 * Given most constructors aren't, we only allocate the visited list
	 * lazily.
	 */
	public boolean isRecursive(ArrayList visited) {

		if (this.binding == null
				|| this.constructorCall == null
				|| this.constructorCall.binding == null
				|| this.constructorCall.isSuperAccess()
				|| !this.constructorCall.binding.isValidBinding()) {
			return false;
		}
		
		ConstructorDeclaration targetConstructor = 
			((ConstructorDeclaration)this.scope.referenceType().declarationOf(constructorCall.binding.original()));
		if (this == targetConstructor) return true; // direct case

		if (visited == null) { // lazy allocation
			visited = new ArrayList(1);
		} else {
			int index = visited.indexOf(this);
			if (index >= 0) return index == 0; // only blame if directly part of the cycle
		}
		visited.add(this);

		return targetConstructor.isRecursive(visited);
	}
	
	public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {

		//fill up the constructor body with its statements
		if (ignoreFurtherInvestigation)
			return;
		if (isDefaultConstructor && this.constructorCall == null){
			this.constructorCall = SuperReference.implicitSuperConstructorCall();
			this.constructorCall.sourceStart = this.sourceStart;
			this.constructorCall.sourceEnd = this.sourceEnd; 
			return;
		}
		parser.parse(this, unit);

	}

	public StringBuffer printBody(int indent, StringBuffer output) {

		output.append(" {"); //$NON-NLS-1$
		if (constructorCall != null) {
			output.append('\n');
			constructorCall.printStatement(indent, output); //$NON-NLS-1$ //$NON-NLS-2$
		}
		if (statements != null) {
			for (int i = 0; i < statements.length; i++) {
				output.append('\n');
				statements[i].printStatement(indent, output); //$NON-NLS-1$
			}
		}
		output.append('\n');
		printIndent(indent == 0 ? 0 : indent - 1, output).append('}');
		return output;
	}
	
	public void resolveJavadoc() {
		
		if (this.binding == null || this.javadoc != null) {
			super.resolveJavadoc();
		} else if (!isDefaultConstructor) {
			this.scope.problemReporter().javadocMissing(this.sourceStart, this.sourceEnd, this.binding.modifiers);
		}
	}

	/*
	 * Type checking for constructor, just another method, except for special check
	 * for recursive constructor invocations.
	 */
	public void resolveStatements() {

		if (!CharOperation.equals(scope.enclosingSourceType().sourceName, selector)){
			scope.problemReporter().missingReturnType(this);
		}

		if (this.binding != null && this.binding.declaringClass.isAnnotationType()) {
			scope.problemReporter().annotationTypeDeclarationCannotHaveConstructor(this);
		}
		// if null ==> an error has occurs at parsing time ....
		if (this.constructorCall != null) {
			// e.g. using super() in java.lang.Object
			if (this.binding != null
				&& this.binding.declaringClass.id == T_JavaLangObject
				&& this.constructorCall.accessMode != ExplicitConstructorCall.This) {
					if (this.constructorCall.accessMode == ExplicitConstructorCall.Super) {
						scope.problemReporter().cannotUseSuperInJavaLangObject(this.constructorCall);
					}
					this.constructorCall = null;
			} else {
				this.constructorCall.resolve(this.scope);
			}
		}
		if ((modifiers & AccSemicolonBody) != 0) {
			scope.problemReporter().methodNeedBody(this);		
		}
		super.resolveStatements();
	}

	public void traverse(
		ASTVisitor visitor,
		ClassScope classScope) {

		
		if (visitor.visit(this, classScope)) {
			if (this.annotations != null) {
				int annotationsLength = this.annotations.length;
				for (int i = 0; i < annotationsLength; i++)
					this.annotations[i].traverse(visitor, scope);
			}
			if (this.typeParameters != null) {
				int typeParametersLength = this.typeParameters.length;
				for (int i = 0; i < typeParametersLength; i++) {
					this.typeParameters[i].traverse(visitor, scope);
				}
			}			
			if (arguments != null) {
				int argumentLength = arguments.length;
				for (int i = 0; i < argumentLength; i++)
					arguments[i].traverse(visitor, scope);
			}
			if (thrownExceptions != null) {
				int thrownExceptionsLength = thrownExceptions.length;
				for (int i = 0; i < thrownExceptionsLength; i++)
					thrownExceptions[i].traverse(visitor, scope);
			}
			if (constructorCall != null)
				constructorCall.traverse(visitor, scope);
			if (statements != null) {
				int statementsLength = statements.length;
				for (int i = 0; i < statementsLength; i++)
					statements[i].traverse(visitor, scope);
			}
		}
		visitor.endVisit(this, classScope);
	}
	public TypeParameter[] typeParameters() {
	    return this.typeParameters;
	}		
}
