package org.eclipse.jdt.internal.compiler.lookup;

/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.ast.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.problem.*;
import org.eclipse.jdt.internal.compiler.util.*;

/**
 * Particular block scope used for methods, constructors or clinits, representing
 * its outermost blockscope. Note also that such a scope will be provided to enclose
 * field initializers subscopes as well.
 */
public class MethodScope extends BlockScope {
	public ReferenceContext referenceContext;
	public boolean needToCompactLocalVariables;
	public boolean isStatic; // method modifier or initializer one

	//fields used in the TC process (no real meaning)
	public static final int NotInFieldDecl = -1 ; 		//must be a negative value 
	public boolean isConstructorCall = false ; 			//modified on the fly by the TC
	public int fieldDeclarationIndex = NotInFieldDecl ; //modified on the fly by the TC

	public int analysisIndex; 	// for setting flow-analysis id

	public boolean isPropagatingInnerClassEmulation;

	// for local variables table attributes
	public int lastIndex = 0;
	public long[] definiteInits = new long[4];
	public long[][] extraDefiniteInits = new long[4][];
public MethodScope(ClassScope parent, ReferenceContext context, boolean isStatic) {
	super(METHOD_SCOPE, parent);
	locals = new LocalVariableBinding[5]; 	
	this.referenceContext = context;
	this.isStatic = isStatic;
	this.startIndex = 0;
}
String basicToString(int tab) {
	String newLine = "\n"/*nonNLS*/;
	for (int i = tab; --i >= 0;)
		newLine += "\t"/*nonNLS*/;

	String s = newLine + "--- Method Scope ---"/*nonNLS*/;
	newLine += "\t"/*nonNLS*/;
	s += newLine + "locals:"/*nonNLS*/;
	for (int i = 0; i < localIndex; i++)
		s += newLine + "\t"/*nonNLS*/ + locals[i].toString();
	s += newLine + "startIndex = "/*nonNLS*/ + startIndex;
	s += newLine + "isConstructorCall = "/*nonNLS*/ + isConstructorCall;
	s += newLine + "fieldDeclarationIndex = "/*nonNLS*/ + fieldDeclarationIndex;
	return s;
}
/* Spec : 8.4.3 & 9.4
*/

private void checkAndSetModifiersForConstructor(MethodBinding methodBinding) {
	int modifiers = methodBinding.modifiers;
	if ((modifiers & AccAlternateModifierProblem) != 0)
		problemReporter().duplicateModifierForMethod(methodBinding.declaringClass, (AbstractMethodDeclaration) referenceContext);

	if (((ConstructorDeclaration) referenceContext).isDefaultConstructor) {
		if (methodBinding.declaringClass.isPublic())
			modifiers |= AccPublic;
		else if (methodBinding.declaringClass.isProtected())
			modifiers |= AccProtected;
	}

	// after this point, tests on the 16 bits reserved.
	int realModifiers = modifiers & AccJustFlag;

	// check for abnormal modifiers
	int unexpectedModifiers = ~(AccPublic | AccPrivate | AccProtected | AccStrictfp);
	if ((realModifiers & unexpectedModifiers) != 0)
		problemReporter().illegalModifierForMethod(methodBinding.declaringClass, (AbstractMethodDeclaration) referenceContext);
	else if ((((AbstractMethodDeclaration) referenceContext).modifiers & AccStrictfp) != 0) // must check the parse node explicitly
		problemReporter().illegalModifierForMethod(methodBinding.declaringClass, (AbstractMethodDeclaration) referenceContext);

	// check for incompatible modifiers in the visibility bits, isolate the visibility bits
	int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
	if ((accessorBits & (accessorBits - 1)) != 0) {
		problemReporter().illegalVisibilityModifierCombinationForMethod(methodBinding.declaringClass, (AbstractMethodDeclaration) referenceContext);

		// need to keep the less restrictive
		if ((accessorBits & AccPublic) != 0) {
			if ((accessorBits & AccProtected) != 0)
				modifiers ^= AccProtected;
			if ((accessorBits & AccPrivate) != 0)
				modifiers ^= AccPrivate;
		}
		if ((accessorBits & AccProtected) != 0)
			if ((accessorBits & AccPrivate) != 0)
				modifiers ^= AccPrivate;
	}

	// if the receiver's declaring class is a private nested type, then make sure the receiver is not private (causes problems for inner type emulation)
	if (methodBinding.declaringClass.isPrivate())
		if ((modifiers & AccPrivate) != 0)
			modifiers ^= AccPrivate;

	methodBinding.modifiers = modifiers;
}
/* Spec : 8.4.3 & 9.4
*/

private void checkAndSetModifiersForMethod(MethodBinding methodBinding) {
	int modifiers = methodBinding.modifiers;
	if ((modifiers & AccAlternateModifierProblem) != 0)
		problemReporter().duplicateModifierForMethod(methodBinding.declaringClass, (AbstractMethodDeclaration) referenceContext);

	// after this point, tests on the 16 bits reserved.
	int realModifiers = modifiers & AccJustFlag;

	// set the requested modifiers for a method in an interface
	if (methodBinding.declaringClass.isInterface()) {
		if ((realModifiers & ~(AccPublic | AccAbstract)) != 0)
			problemReporter().illegalModifierForInterfaceMethod(methodBinding.declaringClass, (AbstractMethodDeclaration) referenceContext);
		return;
	}

	// check for abnormal modifiers
	int unexpectedModifiers = ~(AccPublic | AccPrivate | AccProtected | AccAbstract | AccStatic | AccFinal | AccSynchronized | AccNative | AccStrictfp);
	if ((realModifiers & unexpectedModifiers) != 0)
		problemReporter().illegalModifierForMethod(methodBinding.declaringClass, (AbstractMethodDeclaration) referenceContext);

	// check for incompatible modifiers in the visibility bits, isolate the visibility bits
	int accessorBits = realModifiers & (AccPublic | AccProtected | AccPrivate);
	if ((accessorBits & (accessorBits - 1)) != 0) {
		problemReporter().illegalVisibilityModifierCombinationForMethod(methodBinding.declaringClass, (AbstractMethodDeclaration) referenceContext);

		// need to keep the less restrictive
		if ((accessorBits & AccPublic) != 0) {
			if ((accessorBits & AccProtected) != 0)
				modifiers ^= AccProtected;
			if ((accessorBits & AccPrivate) != 0)
				modifiers ^= AccPrivate;
		}
		if ((accessorBits & AccProtected) != 0)
			if ((accessorBits & AccPrivate) != 0)
				modifiers ^= AccPrivate;
	}

	// check for modifiers incompatible with abstract modifier
	if ((modifiers & AccAbstract) != 0) {
		int incompatibleWithAbstract = AccPrivate | AccStatic | AccFinal | AccSynchronized | AccNative | AccStrictfp;
		if ((modifiers & incompatibleWithAbstract) != 0)
			problemReporter().illegalAbstractModifierCombinationForMethod(methodBinding.declaringClass, (AbstractMethodDeclaration) referenceContext);
		if (!methodBinding.declaringClass.isAbstract())
			problemReporter().abstractMethodInAbstractClass((SourceTypeBinding) methodBinding.declaringClass, (AbstractMethodDeclaration) referenceContext);
	}

	/* DISABLED for backward compatibility with javac (if enabled should also mark private methods as final)
	// methods from a final class are final : 8.4.3.3 
	if (methodBinding.declaringClass.isFinal())
		modifiers |= AccFinal;
	*/
	// native methods cannot also be tagged as strictfp
	if ((modifiers & AccNative) != 0 && (modifiers & AccStrictfp) != 0)
		problemReporter().nativeMethodsCannotBeStrictfp(methodBinding.declaringClass, (AbstractMethodDeclaration) referenceContext);

	// static members are only authorized in a static member or top level type
	if (((realModifiers & AccStatic) != 0) && methodBinding.declaringClass.isNestedType() && !methodBinding.declaringClass.isStatic())
		problemReporter().unexpectedStaticModifierForMethod(methodBinding.declaringClass, (AbstractMethodDeclaration) referenceContext);

	methodBinding.modifiers = modifiers;
}
/* Error management:
* 		keep null for all the errors that prevent the method to be created
* 		otherwise return a correct method binding (but without the element
*		that caused the problem) : ie : Incorrect thrown exception
*/

MethodBinding createMethod(AbstractMethodDeclaration method) {
	// is necessary to ensure error reporting
	this.referenceContext = method;
	method.scope = this;
	SourceTypeBinding declaringClass = referenceType().binding;
	int modifiers = method.modifiers | AccUnresolved;
	if (method.isConstructor()) {
		method.binding = new MethodBinding(modifiers, null, null, declaringClass);
		checkAndSetModifiersForConstructor(method.binding);
	} else {
		if (((MethodDeclaration) method).returnType == null) {
			problemReporter().missingReturnType(method);
			return null;
		}
		if (declaringClass.isInterface())
			modifiers |= AccPublic | AccAbstract;
		method.binding = new MethodBinding(modifiers, method.selector, null, null, null, declaringClass);
		checkAndSetModifiersForMethod(method.binding);
	}

	this.isStatic = method.binding.isStatic();
	return method.binding;
}
/* Overridden to detect the error case inside an explicit constructor call:

class X {
	int i;
	X myX;
	X(X x) {
		this(i, myX.i, x.i); // same for super calls... only the first 2 field accesses are errors
	}
}
*/

public FieldBinding findField(TypeBinding receiverType, char[] fieldName, InvocationSite invocationSite) {
	FieldBinding field = super.findField(receiverType, fieldName, invocationSite);
	if (field == null) return null;
	if (!field.isValidBinding()) return field; // answer the error field
	if (field.isStatic()) return field; // static fields are always accessible

	if (!isConstructorCall || receiverType != enclosingSourceType())
		return field;

	if (invocationSite instanceof SingleNameReference)
		return new ProblemFieldBinding(fieldName, NonStaticReferenceInConstructorInvocation);
	if (invocationSite instanceof QualifiedNameReference) { // look to see if the field is the first binding
		QualifiedNameReference name = (QualifiedNameReference) invocationSite;
		if (name.binding == null) // only true when the field is the fieldbinding at the beginning of name's tokens
			return new ProblemFieldBinding(fieldName, NonStaticReferenceInConstructorInvocation);
	}
	return field;
}
public boolean isInsideInitializer() {
	return (referenceContext instanceof TypeDeclaration);
}
public boolean isInsideInitializerOrConstructor() {
	return (referenceContext instanceof TypeDeclaration) || (referenceContext instanceof ConstructorDeclaration);
}
/* Answer the problem reporter to use for raising new problems.
*
* Note that as a side-effect, this updates the current reference context
* (unit, type or method) in case the problem handler decides it is necessary
* to abort.
*/

public ProblemReporter problemReporter() {
	MethodScope outerMethodScope;
	if ((outerMethodScope = outerMostMethodScope()) == this) {
		ProblemReporter problemReporter = referenceCompilationUnit().problemReporter;
		problemReporter.referenceContext = referenceContext;
		return problemReporter;
	} else {
		return outerMethodScope.problemReporter();
	}
}
public final int recordInitializationStates(FlowInfo flowInfo) {
	if ((flowInfo == FlowInfo.DeadEnd) || (flowInfo.isFakeReachable())) {
		return -1;
	}
	UnconditionalFlowInfo unconditionalFlowInfo = flowInfo.unconditionalInits();
	long[] extraInits = unconditionalFlowInfo.extraDefiniteInits;
	long inits = unconditionalFlowInfo.definiteInits;
	checkNextEntry : for (int i = lastIndex; --i >= 0;) {
		if (definiteInits[i] == inits) {
			long[] otherInits = extraDefiniteInits[i];
			if ((extraInits != null) && (otherInits != null)) {
				if (extraInits.length == otherInits.length) {
					int j, max;
					for (j = 0, max = extraInits.length; j < max; j++) {
						if (extraInits[j] != otherInits[j]) {
							continue checkNextEntry;
						}
					}
					return i;
				}
			} else {
				if ((extraInits == null) && (otherInits == null)) {
					return i;
				}
			}
		}
	}
	
	// add a new entry
	if (definiteInits.length == lastIndex) {
		// need a resize
		System.arraycopy(definiteInits, 0, (definiteInits = new long[lastIndex + 20]), 0, lastIndex);
		System.arraycopy(extraDefiniteInits, 0, (extraDefiniteInits = new long[lastIndex + 20][]), 0, lastIndex);
	}
	definiteInits[lastIndex] = inits;
	if (extraInits != null) {
		extraDefiniteInits[lastIndex] = new long[extraInits.length];
		System.arraycopy(extraInits, 0, extraDefiniteInits[lastIndex], 0, extraInits.length);
	}
	return lastIndex++;
}
/* Answer the reference type of this scope.
*
* i.e. the nearest enclosing type of this scope.
*/

public TypeDeclaration referenceType() {
	return (TypeDeclaration) ((ClassScope) parent).referenceContext;
}
}
