/*******************************************************************************
 * Copyright (c) 2000, 2017 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
 *     Patrick Wienands <pwienands@abit.de> - Contribution for bug 393749
 *     Stephan Herrmann - Contribution for
 *								bug 331649 - [compiler][null] consider null annotations for fields
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ClassFile;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.BranchLabel;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
import org.eclipse.jdt.internal.compiler.flow.ExceptionHandlingFlowContext;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.flow.InitializationFlowContext;
import org.eclipse.jdt.internal.compiler.lookup.Binding;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.AbortMethod;

public class Clinit extends AbstractMethodDeclaration {
	private static int ENUM_CONSTANTS_THRESHOLD = 2000;

	private FieldBinding assertionSyntheticFieldBinding = null;
	private FieldBinding classLiteralSyntheticField = null;

	public Clinit(CompilationResult compilationResult) {
		super(compilationResult);
		this.modifiers = 0;
		this.selector = TypeConstants.CLINIT;
	}

	public void analyseCode(
		ClassScope classScope,
		InitializationFlowContext staticInitializerFlowContext,
		FlowInfo flowInfo) {

		if (this.ignoreFurtherInvestigation)
			return;
		try {
			ExceptionHandlingFlowContext clinitContext =
				new ExceptionHandlingFlowContext(
					staticInitializerFlowContext.parent,
					this,
					Binding.NO_EXCEPTIONS,
					staticInitializerFlowContext,
					this.scope,
					FlowInfo.DEAD_END);

			// check for missing returning path
			if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) {
				this.bits |= ASTNode.NeedFreeReturn;
			}

			// check missing blank final field initializations
			flowInfo = flowInfo.mergedWith(staticInitializerFlowContext.initsOnReturn);
			FieldBinding[] fields = this.scope.enclosingSourceType().fields();
			for (int i = 0, count = fields.length; i < count; i++) {
				FieldBinding field = fields[i];
				if (field.isStatic()) {
					if (!flowInfo.isDefinitelyAssigned(field)) {
						if (field.isFinal()) {
							this.scope.problemReporter().uninitializedBlankFinalField(
									field,
									this.scope.referenceType().declarationOf(field.original()));
							// can complain against the field decl, since only one <clinit>
						} else if (field.isNonNull()) {
							this.scope.problemReporter().uninitializedNonNullField(
									field,
									this.scope.referenceType().declarationOf(field.original()));
						}
					}
				}
			}
			// check static initializers thrown exceptions
			staticInitializerFlowContext.checkInitializerExceptions(
				this.scope,
				clinitContext,
				flowInfo);
		} catch (AbortMethod e) {
			this.ignoreFurtherInvestigation = true;
		}
	}

	/**
	 * Bytecode generation for a <clinit> method
	 *
	 * @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 clinitOffset = 0;
		if (this.ignoreFurtherInvestigation) {
			// should never have to add any <clinit> problem method
			return;
		}
		CompilationResult unitResult = null;
		int problemCount = 0;
		if (classScope != null) {
			TypeDeclaration referenceContext = classScope.referenceContext;
			if (referenceContext != null) {
				unitResult = referenceContext.compilationResult();
				problemCount = unitResult.problemCount;
			}
		}
		boolean restart = false;
		do {
			try {
				clinitOffset = classFile.contentsOffset;
				this.generateCode(classScope, classFile, clinitOffset);
				restart = false;
			} catch (AbortMethod e) {
				// should never occur
				// the clinit referenceContext is the type declaration
				// All clinit problems will be reported against the type: AbortType instead of AbortMethod
				// reset the contentsOffset to the value before generating the clinit code
				// decrement the number of method info as well.
				// This is done in the addProblemMethod and addProblemConstructor for other
				// cases.
				if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
					// a branch target required a goto_w, restart code gen in wide mode.
					classFile.contentsOffset = clinitOffset;
					classFile.methodCount--;
					classFile.codeStream.resetInWideMode(); // request wide mode
					// reset the problem count to prevent reporting the same warning twice
					if (unitResult != null) {
						unitResult.problemCount = problemCount;
					}
					// restart method generation
					restart = true;
				} else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) {
					classFile.contentsOffset = clinitOffset;
					classFile.methodCount--;
					classFile.codeStream.resetForCodeGenUnusedLocals();
					// reset the problem count to prevent reporting the same warning twice
					if (unitResult != null) {
						unitResult.problemCount = problemCount;
					}
					// restart method generation
					restart = true;
				} else {
					// produce a problem method accounting for this fatal error
					classFile.contentsOffset = clinitOffset;
					classFile.methodCount--;
					restart = false;
				}
			}
		} while (restart);
	}

	/**
	 * Bytecode generation for a <clinit> method
	 *
	 * @param classScope org.eclipse.jdt.internal.compiler.lookup.ClassScope
	 * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
	 */
	private void generateCode(
		ClassScope classScope,
		ClassFile classFile,
		int clinitOffset) {

		ConstantPool constantPool = classFile.constantPool;
		int constantPoolOffset = constantPool.currentOffset;
		int constantPoolIndex = constantPool.currentIndex;
		classFile.generateMethodInfoHeaderForClinit();
		int codeAttributeOffset = classFile.contentsOffset;
		classFile.generateCodeAttributeHeader();
		CodeStream codeStream = classFile.codeStream;
		resolve(classScope);

		codeStream.reset(this, classFile);
		TypeDeclaration declaringType = classScope.referenceContext;

		// initialize local positions - including initializer scope.
		MethodScope staticInitializerScope = declaringType.staticInitializerScope;
		staticInitializerScope.computeLocalVariablePositions(0, codeStream);

		// 1.4 feature
		// This has to be done before any other initialization
		if (this.assertionSyntheticFieldBinding != null) {
			// generate code related to the activation of assertion for this class
			codeStream.generateClassLiteralAccessForType(
					classScope.outerMostClassScope().enclosingSourceType(),
					this.classLiteralSyntheticField);
			codeStream.invokeJavaLangClassDesiredAssertionStatus();
			BranchLabel falseLabel = new BranchLabel(codeStream);
			codeStream.ifne(falseLabel);
			codeStream.iconst_1();
			BranchLabel jumpLabel = new BranchLabel(codeStream);
			codeStream.decrStackSize(1);
			codeStream.goto_(jumpLabel);
			falseLabel.place();
			codeStream.iconst_0();
			jumpLabel.place();
			codeStream.fieldAccess(Opcodes.OPC_putstatic, this.assertionSyntheticFieldBinding, null /* default declaringClass */);
		}
		boolean isJava9 = classScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK9;
		// generate static fields/initializers/enum constants
		final FieldDeclaration[] fieldDeclarations = declaringType.fields;
		int sourcePosition = -1;
		int remainingFieldCount = 0;
		if (TypeDeclaration.kind(declaringType.modifiers) == TypeDeclaration.ENUM_DECL) {
			int enumCount = declaringType.enumConstantsCounter;
			if (!isJava9 && enumCount > ENUM_CONSTANTS_THRESHOLD) {
				// generate synthetic methods to initialize all the enum constants
				int begin = -1;
				int count = 0;
				if (fieldDeclarations != null) {
					int max = fieldDeclarations.length;
					for (int i = 0; i < max; i++) {
						FieldDeclaration fieldDecl = fieldDeclarations[i];
						if (fieldDecl.isStatic()) {
							if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
								if (begin == -1) {
									begin = i;
								}
								count++;
								if (count > ENUM_CONSTANTS_THRESHOLD) {
									SyntheticMethodBinding syntheticMethod = declaringType.binding.addSyntheticMethodForEnumInitialization(begin, i);
									codeStream.invoke(Opcodes.OPC_invokestatic, syntheticMethod, null /* default declaringClass */);
									begin = i;
									count = 1;
								}
							} else {
								remainingFieldCount++;
							}
						}
					}
					if (count != 0) {
						// add last synthetic method
						SyntheticMethodBinding syntheticMethod = declaringType.binding.addSyntheticMethodForEnumInitialization(begin, max);
						codeStream.invoke(Opcodes.OPC_invokestatic, syntheticMethod, null /* default declaringClass */);
					}
				}
			} else if (fieldDeclarations != null) {
				for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
					FieldDeclaration fieldDecl = fieldDeclarations[i];
					if (fieldDecl.isStatic()) {
						if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
							fieldDecl.generateCode(staticInitializerScope, codeStream);
						} else {
							remainingFieldCount++;
						}
					}
				}
			}
			// enum need to initialize $VALUES synthetic cache of enum constants
			// $VALUES := new <EnumType>[<enumCount>]
			codeStream.generateInlinedValue(enumCount);
			codeStream.anewarray(declaringType.binding);
			if (enumCount > 0) {
				if (fieldDeclarations != null) {
					for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
						FieldDeclaration fieldDecl = fieldDeclarations[i];
						// $VALUES[i] = <enum-constant-i>
						if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
							codeStream.dup();
							codeStream.generateInlinedValue(fieldDecl.binding.id);
							codeStream.fieldAccess(Opcodes.OPC_getstatic, fieldDecl.binding, null /* default declaringClass */);
							codeStream.aastore();
						}
					}
				}
			}
			codeStream.fieldAccess(Opcodes.OPC_putstatic, declaringType.enumValuesSyntheticfield, null /* default declaringClass */);
			if (remainingFieldCount != 0) {
				// if fields that are not enum constants need to be generated (static initializer/static field)
				for (int i = 0, max = fieldDeclarations.length; i < max && remainingFieldCount >= 0; i++) {
					FieldDeclaration fieldDecl = fieldDeclarations[i];
					switch (fieldDecl.getKind()) {
						case AbstractVariableDeclaration.ENUM_CONSTANT :
							break;
						case AbstractVariableDeclaration.INITIALIZER :
							if (!fieldDecl.isStatic()) {
								break;
							}
							remainingFieldCount--;
							sourcePosition = ((Initializer) fieldDecl).block.sourceEnd;
							fieldDecl.generateCode(staticInitializerScope, codeStream);
							break;
						case AbstractVariableDeclaration.FIELD :
							if (!fieldDecl.binding.isStatic()) {
								break;
							}
							remainingFieldCount--;
							sourcePosition = fieldDecl.declarationEnd;
							fieldDecl.generateCode(staticInitializerScope, codeStream);
							break;
					}
				}
			}
		} else {
			if (fieldDeclarations != null) {
				for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
					FieldDeclaration fieldDecl = fieldDeclarations[i];
					switch (fieldDecl.getKind()) {
						case AbstractVariableDeclaration.INITIALIZER :
							if (!fieldDecl.isStatic())
								break;
							sourcePosition = ((Initializer) fieldDecl).block.sourceEnd;
							fieldDecl.generateCode(staticInitializerScope, codeStream);
							break;
						case AbstractVariableDeclaration.FIELD :
							if (!fieldDecl.binding.isStatic())
								break;
							sourcePosition = fieldDecl.declarationEnd;
							fieldDecl.generateCode(staticInitializerScope, codeStream);
							break;
					}
				}
			}
			if (isJava9) {
				declaringType.binding.generateSyntheticFinalFieldInitialization(codeStream);
			}
		}

		if (codeStream.position == 0) {
			// do not need to output a Clinit if no bytecodes
			// so we reset the offset inside the byte array contents.
			classFile.contentsOffset = clinitOffset;
			// like we don't addd a method we need to undo the increment on the method count
			classFile.methodCount--;
			// reset the constant pool to its state before the clinit
			constantPool.resetForClinit(constantPoolIndex, constantPoolOffset);
		} else {
			if ((this.bits & ASTNode.NeedFreeReturn) != 0) {
				int before = codeStream.position;
				codeStream.return_();
				if (sourcePosition != -1) {
					// expand the last initializer variables to include the trailing return
					codeStream.recordPositionsFrom(before, sourcePosition);
				}
			}
			// Record the end of the clinit: point to the declaration of the class
			codeStream.recordPositionsFrom(0, declaringType.sourceStart);
			classFile.completeCodeAttributeForClinit(codeAttributeOffset);
		}
	}

	public boolean isClinit() {

		return true;
	}

	public boolean isInitializationMethod() {

		return true;
	}

	public boolean isStatic() {

		return true;
	}

	public void parseStatements(Parser parser, CompilationUnitDeclaration unit) {
		//the clinit is filled by hand ....
	}

	public StringBuffer print(int tab, StringBuffer output) {

		printIndent(tab, output).append("<clinit>()"); //$NON-NLS-1$
		printBody(tab + 1, output);
		return output;
	}

	public void resolve(ClassScope classScope) {

		this.scope = new MethodScope(classScope, classScope.referenceContext, true);
	}

	public void traverse(
		ASTVisitor visitor,
		ClassScope classScope) {

		visitor.visit(this, classScope);
		visitor.endVisit(this, classScope);
	}

	public void setAssertionSupport(FieldBinding assertionSyntheticFieldBinding, boolean needClassLiteralField) {

		this.assertionSyntheticFieldBinding = assertionSyntheticFieldBinding;

		// we need to add the field right now, because the field infos are generated before the methods
		if (needClassLiteralField) {
			SourceTypeBinding sourceType =
				this.scope.outerMostClassScope().enclosingSourceType();
			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=22334
			if (!sourceType.isInterface() && !sourceType.isBaseType()) {
				this.classLiteralSyntheticField = sourceType.addSyntheticFieldForClassLiteral(sourceType, this.scope);
			}
		}
	}

}
