/*******************************************************************************
 * Copyright (c) 2000, 2020 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Fraunhofer FIRST - extended API and implementation
 *     Technical University Berlin - extended API and implementation
 *     Stephan Herrmann - Contributions for
 *								bug 186342 - [compiler][null] Using annotations for null checking
 *								bug 367203 - [compiler][null] detect assigning null to nonnull argument
 *								bug 365519 - editorial cleanup after bug 186342 and bug 365387
 *								bug 365531 - [compiler][null] investigate alternative strategy for internally encoding nullness defaults
 *								bug 382353 - [1.8][compiler] Implementation property modifiers should be accepted on default methods.
 *								bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
 *								bug 388281 - [compiler][null] inheritance of null annotations as an option
 *								bug 401030 - [1.8][null] Null analysis support for lambda methods.
 *								Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
 *								Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
 *								Bug 403216 - [1.8][null] TypeReference#captureTypeAnnotations treats type annotations as type argument annotations
 *								Bug 417295 - [1.8[[null] Massage type annotated null analysis to gel well with deep encoded type bindings.
 *								Bug 392238 - [1.8][compiler][null] Detect semantically invalid null type annotations
 *								Bug 435570 - [1.8][null] @NonNullByDefault illegally tries to affect "throws E"
 *								Bug 435805 - [1.8][compiler][null] Java 8 compiler does not recognize declaration style null annotations
 *								Bug 466713 - Null Annotations: NullPointerException using <int @Nullable []> as Type Param
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import java.util.List;

import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationPosition;
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
import org.eclipse.jdt.internal.compiler.problem.*;
import org.eclipse.jdt.internal.compiler.parser.*;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.AnchorListAttribute;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.BytecodeTransformer;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
import org.eclipse.objectteams.otdt.internal.core.compiler.lifting.Lifting;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.RoleModel;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.MethodModel.ProblemDetail;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.InsertTypeAdjustmentsVisitor;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.MethodSignatureEnhancer;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.TransformStatementsVisitor;

/**
 * OTDT changes:
 *
 * FIELDS:
 * What: Link to MethodModel and original binding (CopyInheritance)
 * 		 Add flags for different kinds of synthetic methods
 *
 * GENERATE/COPY BYTE CODE:
 * What:
 * 		1) store the completed byte code in RoleModel
 * 		1b) mark erroneous methods to prevent byte code copy (have not byte code)
 * 		2) switch between actual generateCode and adjusting copy
 * 		3) write OT-specific byte code attributes during generate code
 *
 * What: Provide a endOfMethodHook in generateCode (used by RoleInitializationMethod)
 * Why:  See RoleInitializationMethod.endOfMethodHook
 *
 * What: Support static role methods.
 * Why:  while disallowed in pure Java, static role methods are allowed and required
 *       a synthetic argument for passing the enclosing team instance.
 *       A second dummy argument (int) is used to align argument positions with those
 *       of a nested class ctor where local(0) == this.
 * Where:
 *       AbstractMethodDeclration.generateCode
 *       	respect binding.declaringClass.enclosingInstancesSlotSize
 *       	when computing local variable positions.
 *       MethodBinding.signature
 *       	prepend synthetic arguments "ILMyTeam;" to the signature.
 *       CodeStream.initMaxLocals
 *       	add 2 for synthetic arguments of static role methods.
 *       MesasgeSend.generateCode
 *       	generate synthetic argument values when invoking a static role method:
 *       	"iconst_0; aload_(enclosing_team_instance)"
 *		 BlockScope.getEmulationPath(..)
 *			now also applies to MyTeam.this expressions within static role methods
 *       MethodSpec.getResolvedParamters
 *       	include synthetic arguments
 *       BinaryTypeBinding.createMethod
 *          skip synthetic arguments
 *       MemberTypeBinding.checkSyntheticArgsAndFields
 *          create synth arg for role-interface, too (ifcs are usually skipped)
 *          in order to get consistent signatures for ifc- and class-methods.
 *
 * TRANSLATE:
 * What: perform type adjustments on statements
 * How:  resolveStatements triggers InsertTypeAdjustmentsVisitor and CollectedReplacementsTransformer.
 *
 * What: Add anchor list attribute (TODO (SH): unify this with base name strategy of team anchors)
 *
 * @version $Id: AbstractMethodDeclaration.java 23404 2010-02-03 14:10:22Z stephan $
 */
public abstract class AbstractMethodDeclaration
	extends ASTNode
	implements ProblemSeverities, ReferenceContext {

//	{ObjectTeams
	// fake argument binding for all role method to allocate a slot for a tsuper marker arg added dyring bytecode-copy:
	private static final char[] TSUPER_PLACEHOLDER = "_OT$tsuperMarkerArgPlaceholder$".toCharArray(); //$NON-NLS-1$
    // this holds additional info for role methods:
    public MethodModel model = null;
	public MethodModel getModel() {
		if (this.model != null)
			return this.model;
		if (this.binding != null)
			return this.binding.model;
		return null;
	}
	//Reference to original Binding in case of CopyInheritance
	public MethodBinding sourceMethodBinding;
	//For Methods which are created in the context of Implicit-Inheritance
	public boolean isCopied=false;
    //For other generated methods (lift methods, role constructors, creation methods, callin/out-wrappers)
    public boolean isGenerated=false;
    /**
     * Callout bindings may reuse an existing method declaration.
     * Also guard predicates are marked with this flag.
     * All other generated methods are purely generated.
     */
    public boolean isReusingSourceMethod=false;
    //For Methods that are tsuper versions (i.e., augmented with a marker arg:
    public boolean isTSuper=false;
    //Some clients don't invoke getMethodBodies, yet some statements might be generated,
    // this flag marks if source statements have been parsed:
    public boolean hasParsedStatements=false;
    //For callin/callout wrappers store the kind of the generating mapping:
    public enum WrapperKind {
    	NONE, CALLOUT, CALLIN;

		public boolean none()    { return this == NONE; }
		public boolean any()     { return this != NONE; }
		public boolean callout() { return this == CALLOUT; }
		public boolean _callin() { return this == CALLIN; }
    }
    public WrapperKind isMappingWrapper = WrapperKind.NONE;
    // links from a role method to its representation in the interface after role splitting:
    public AbstractMethodDeclaration interfacePartMethod = null;

    // ==== additional queries: ====
    /**
     * Is the method copied but not an interface method?
     * Only those methods have byte code to copy from the tsuper role.
     */
    public boolean isRelevantCopied() {
    	if (this.model != null && this.model.problemDetail == ProblemDetail.IllegalDefaultCtor) {
    		((ConstructorDeclaration)this).createExceptionStatements();
    		return false;
    	}
        return this.isCopied && ((this.modifiers & ExtraCompilerModifiers.AccSemicolonBody) == 0);
    }
	protected boolean areStatementsMissing() {
		return !this.hasParsedStatements;
	}
	public void setStatements(Statement[] statements) {
		this.statements = statements;
		this.hasParsedStatements = true;
	}
	public boolean isBasePredicate() {
		return false;
	}
	public boolean isCalloutWrapper() {
    	return this.isMappingWrapper.callout();
    }
    /** Callin method or callin wrapper */
    public boolean isAnyCallin() {
    	return (this.modifiers & ExtraCompilerModifiers.AccCallin) != 0;
    }
    /** Source level callin method only. */
    public boolean isCallin() {
    	return (this.modifiers & ExtraCompilerModifiers.AccCallin) != 0 && this.isMappingWrapper.none();
    }
//Markus Witte+SH}

	public MethodScope scope;
	//it is not relevent for constructor but it helps to have the name of the constructor here
	//which is always the name of the class.....parsing do extra work to fill it up while it do not have to....
	public char[] selector;
	public int declarationSourceStart;
	public int declarationSourceEnd;
	public int modifiers;
	public int modifiersSourceStart;
	public Annotation[] annotations;
	// jsr 308
	public Receiver receiver;
	public Argument[] arguments;
	public TypeReference[] thrownExceptions;
	public Statement[] statements;
	public int explicitDeclarations;
	public MethodBinding binding;
	public boolean ignoreFurtherInvestigation = false;

	public Javadoc javadoc;

	public int bodyStart;
	public int bodyEnd = -1;
	public CompilationResult compilationResult;
	public boolean containsSwitchWithTry = false;

	AbstractMethodDeclaration(CompilationResult compilationResult){
		this.compilationResult = compilationResult;
		this.containsSwitchWithTry = false;
	}

	/*
	 *	We cause the compilation task to abort to a given extent.
	 */
	@Override
	public void abort(int abortLevel, CategorizedProblem problem) {

		switch (abortLevel) {
			case AbortCompilation :
				throw new AbortCompilation(this.compilationResult, problem);
			case AbortCompilationUnit :
				throw new AbortCompilationUnit(this.compilationResult, problem);
			case AbortType :
				throw new AbortType(this.compilationResult, problem);
			default :
				throw new AbortMethod(this.compilationResult, problem);
		}
	}

	/**
	 * When a method is accessed via SourceTypeBinding.resolveTypesFor(MethodBinding)
	 * we create the argument binding and resolve annotations in order to compute null annotation tagbits.
	 */
	public void createArgumentBindings() {
		createArgumentBindings(this.arguments, this.binding, this.scope);
	}
	// version for invocation from LambdaExpression:
	static void createArgumentBindings(Argument[] arguments, MethodBinding binding, MethodScope scope) {
		boolean useTypeAnnotations = scope.environment().usesNullTypeAnnotations();
		if (arguments != null && binding != null) {
			for (int i = 0, length = arguments.length; i < length; i++) {
				Argument argument = arguments[i];
				binding.parameters[i] = argument.createBinding(scope, binding.parameters[i]);
				if (useTypeAnnotations)
					continue; // no business with SE7 null annotations in the 1.8 case.
				// createBinding() has resolved annotations, now transfer nullness info from the argument to the method:
				long argTypeTagBits = (argument.binding.tagBits & TagBits.AnnotationNullMASK);
				if (argTypeTagBits != 0) {
					if (binding.parameterNonNullness == null) {
						binding.parameterNonNullness = new Boolean[arguments.length];
						binding.tagBits |= TagBits.IsNullnessKnown;
					}
					binding.parameterNonNullness[i] = Boolean.valueOf(argTypeTagBits == TagBits.AnnotationNonNull);
				}
			}
		}
	}

	/**
	 * Bind and add argument's binding into the scope of the method
	 */
	public void bindArguments() {

		if (this.arguments != null) {
			// by default arguments in abstract/native methods are considered to be used (no complaint is expected)
//{ObjectTeams: for generated methods we may reach here without binding.parameters
/* orig:
			if (this.binding == null) {
  :giro */
			if (   this.binding == null
				|| this.binding.parameters == Binding.NO_PARAMETERS) {
// SH}
				for (int i = 0, length = this.arguments.length; i < length; i++) {
					this.arguments[i].bind(this.scope, null, true);
				}
				return;
			}
			boolean used = this.binding.isAbstract() || this.binding.isNative();
			AnnotationBinding[][] paramAnnotations = null;
			for (int i = 0, length = this.arguments.length; i < length; i++) {
				Argument argument = this.arguments[i];
				this.binding.parameters[i] = argument.bind(this.scope, this.binding.parameters[i], used);
				if (argument.annotations != null) {
					if (paramAnnotations == null) {
						paramAnnotations = new AnnotationBinding[length][];
						for (int j=0; j<i; j++) {
							paramAnnotations[j] = Binding.NO_ANNOTATIONS;
						}
					}
					paramAnnotations[i] = argument.binding.getAnnotations();
				} else if (paramAnnotations != null) {
					paramAnnotations[i] = Binding.NO_ANNOTATIONS;
				}
			}
			if (paramAnnotations == null) {
				paramAnnotations = getPropagatedRecordComponentAnnotations();
			}

			if (paramAnnotations != null)
				this.binding.setParameterAnnotations(paramAnnotations);
		}
//{ObjectTeams: for all role methods allocate the slot for tsuper marker arg:
		if (!this.ignoreFurtherInvestigation && this.binding.declaringClass.isDirectRole()) {
			LocalVariableBinding placeholderArg = new LocalVariableBinding(TSUPER_PLACEHOLDER, this.scope.getJavaLangObject(), 0, true);
			placeholderArg.useFlag = LocalVariableBinding.USED;
			this.scope.addLocalVariable(placeholderArg);
// SH}
		}
	}

	protected AnnotationBinding[][] getPropagatedRecordComponentAnnotations() {
		return null;
	}

	/**
	 * Record the thrown exception type bindings in the corresponding type references.
	 */
	public void bindThrownExceptions() {

		if (this.thrownExceptions != null
			&& this.binding != null
			&& this.binding.thrownExceptions != null) {
			int thrownExceptionLength = this.thrownExceptions.length;
			int length = this.binding.thrownExceptions.length;
			if (length == thrownExceptionLength) {
				for (int i = 0; i < length; i++) {
					this.thrownExceptions[i].resolvedType = this.binding.thrownExceptions[i];
				}
			} else {
				int bindingIndex = 0;
				for (int i = 0; i < thrownExceptionLength && bindingIndex < length; i++) {
					TypeReference thrownException = this.thrownExceptions[i];
					ReferenceBinding thrownExceptionBinding = this.binding.thrownExceptions[bindingIndex];
					char[][] bindingCompoundName = thrownExceptionBinding.compoundName;
					if (bindingCompoundName == null) continue; // skip problem case
					if (thrownException instanceof SingleTypeReference) {
						// single type reference
						int lengthName = bindingCompoundName.length;
						char[] thrownExceptionTypeName = thrownException.getTypeName()[0];
						if (CharOperation.equals(thrownExceptionTypeName, bindingCompoundName[lengthName - 1])) {
							thrownException.resolvedType = thrownExceptionBinding;
							bindingIndex++;
						}
					} else {
						// qualified type reference
						if (CharOperation.equals(thrownException.getTypeName(), bindingCompoundName)) {
							thrownException.resolvedType = thrownExceptionBinding;
							bindingIndex++;
						}
					}
				}
			}
		}
	}

	/**
	 * Feed null information from argument annotations into the analysis and mark arguments as assigned.
	 */
	static void analyseArguments(LookupEnvironment environment, FlowInfo flowInfo, Argument[] methodArguments, MethodBinding methodBinding) {
		if (methodArguments != null) {
			boolean usesNullTypeAnnotations = environment.usesNullTypeAnnotations();
			int length = Math.min(methodBinding.parameters.length, methodArguments.length);
			for (int i = 0; i < length; i++) {
				if (usesNullTypeAnnotations) {
					// leverage null type annotations:
					long tagBits = methodBinding.parameters[i].tagBits & TagBits.AnnotationNullMASK;
					if (tagBits == TagBits.AnnotationNonNull)
						flowInfo.markAsDefinitelyNonNull(methodArguments[i].binding);
					else if (tagBits == TagBits.AnnotationNullable)
						flowInfo.markPotentiallyNullBit(methodArguments[i].binding);
					else if (methodBinding.parameters[i].isFreeTypeVariable()) {
						flowInfo.markNullStatus(methodArguments[i].binding, FlowInfo.FREE_TYPEVARIABLE);
					}
				} else {
					if (methodBinding.parameterNonNullness != null) {
						// leverage null-info from parameter annotations:
						Boolean nonNullNess = methodBinding.parameterNonNullness[i];
						if (nonNullNess != null) {
							if (nonNullNess.booleanValue())
								flowInfo.markAsDefinitelyNonNull(methodArguments[i].binding);
							else
								flowInfo.markPotentiallyNullBit(methodArguments[i].binding);
						}
					}
				}
				// tag parameters as being set:
				flowInfo.markAsDefinitelyAssigned(methodArguments[i].binding);
			}
		}
	}

	@Override
	public CompilationResult compilationResult() {

		return this.compilationResult;
	}

	/**
	 * Bytecode generation for a method
	 * @param classScope
	 * @param classFile
	 */
	public void generateCode(ClassScope classScope, ClassFile classFile) {

//{ObjectTeams: if copied for implicit inheritance just adjust and write out
        // note: the same code is also inserted into ConstructorDeclaration.generateCode
        if(isRelevantCopied())
        {
        	if (!this.ignoreFurtherInvestigation)
        		new BytecodeTransformer().checkCopyMethodCode(classFile, this);
	        if (this.binding.bytecodeMissing && !Config.getConfig().ignoreMissingBytecode) { // copy did not succeed
				int problemsLength;
				CategorizedProblem[] problems =
					this.scope.referenceCompilationUnit().compilationResult.getProblems();
				CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
				System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
				classFile.addProblemConstructor(this, this.binding, problemsCopy);
	        }
            return;
        }
        if ((this.binding != null) && areStatementsMissing() && !isAbstract()) {
        	this.binding.bytecodeMissing = true;
        	return;
        }
// SH}
		classFile.codeStream.wideMode = false; // reset wideMode to false
		if (this.ignoreFurtherInvestigation) {
			// method is known to have errors, dump a problem method
			if (this.binding == null)
				return; // handle methods with invalid signature or duplicates
			int problemsLength;
			CategorizedProblem[] problems =
				this.scope.referenceCompilationUnit().compilationResult.getProblems();
			CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
			System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
			classFile.addProblemMethod(this, this.binding, problemsCopy);
//{ObjectTeams: mark this erroneous, so we don't try to copy the byte code later:
            if ((!this.binding.isNative()) && (!this.binding.isAbstract()))
                this.binding.bytecodeMissing = true;
            // similarly for contained local types:
            traverse(new ASTVisitor() {
            	@Override
				public boolean visit(TypeDeclaration type, BlockScope blockScope) {
            		type.tagAsHavingErrors();
            		return true;
            	}
			}, classScope);
// SH}
			return;
		}
		int problemResetPC = 0;
		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;
		boolean abort = false;
		// regular code generation
		do {
			try {
				problemResetPC = classFile.contentsOffset;
				this.generateCode(classFile);
				restart = false;
			} catch (AbortMethod e) {
				// a fatal error was detected during code generation, need to restart code gen if possible
				if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) {
					// a branch target required a goto_w, restart code gen in wide mode.
					classFile.contentsOffset = problemResetPC;
					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 = true;
				} else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) {
					classFile.contentsOffset = problemResetPC;
					classFile.methodCount--;
					classFile.codeStream.resetForCodeGenUnusedLocals();
					// reset the problem count to prevent reporting the same warning twice
					if (unitResult != null) {
						unitResult.problemCount = problemCount;
					}
					restart = true;
				} else {
					restart = false;
					abort = true;
				}
			}
		} while (restart);
		// produce a problem method accounting for this fatal error
		if (abort) {
			int problemsLength;
			CategorizedProblem[] problems =
				this.scope.referenceCompilationUnit().compilationResult.getAllProblems();
			CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
			System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
			classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC);
		}
	}

	public void generateCode(ClassFile classFile) {

		classFile.generateMethodInfoHeader(this.binding);
		int methodAttributeOffset = classFile.contentsOffset;
		int attributeNumber = classFile.generateMethodInfoAttributes(this.binding);
//{ObjectTeams: write OT-specific byte code attributes
        if (this.model != null)
            attributeNumber += this.model.writeAttributes(classFile);
        // special body for abstract static:
        int abstractStatic = ClassFileConstants.AccAbstract | ClassFileConstants.AccStatic;
        if (   (this.binding.modifiers & abstractStatic) == abstractStatic
        	&& !this.binding.declaringClass.isInterface())
        {
    		// Code attribute
    		attributeNumber += generateAbstractStaticRoleMethodCode(classFile);
        } else
// SH}
		if ((!this.binding.isNative()) && (!this.binding.isAbstract())) {
			int codeAttributeOffset = classFile.contentsOffset;
			classFile.generateCodeAttributeHeader();
			CodeStream codeStream = classFile.codeStream;
			codeStream.reset(this, classFile);
//{ObjectTeams:	static role methods have a synthetic team reference:
		  // cf. ConstructorDeclaration.internalGenerateCode().
		  ReferenceBinding declaringClass = this.binding.declaringClass;
		  SyntheticArgumentBinding syntheticArgumentBinding= null;
		  if (this.binding.needsSyntheticEnclosingTeamInstance()) {
			MemberTypeBinding nestedType = (MemberTypeBinding) declaringClass;
			this.scope.computeLocalVariablePositions(// consider synthetic arguments if any
				nestedType.getEnclosingInstancesSlotSize() + 1, // 1 for a dummy this arg
				codeStream);
			// add dummy argument only now, so it won't be resolved after regular args:
			syntheticArgumentBinding = new SyntheticArgumentBinding(nestedType.enclosingType());
			syntheticArgumentBinding.resolvedPosition= 1; // constantly;
			this.scope.extraSyntheticArguments= new SyntheticArgumentBinding[] { syntheticArgumentBinding };
			codeStream.record(syntheticArgumentBinding);
			syntheticArgumentBinding.recordInitializationStartPC(0);
		  } else
// SH}
			// initialize local positions
			this.scope.computeLocalVariablePositions(this.binding.isStatic() ? 0 : 1, codeStream);
//{ObjectTeams: runtime check in creation method?
	        if (this.binding.roleCreatorRequiringRuntimeCheck)
	        	Lifting.createDuplicateRoleCheck(codeStream, this);
// SH}
			// arguments initialization for local variable debug attributes
			if (this.arguments != null) {
				for (int i = 0, max = this.arguments.length; i < max; i++) {
					LocalVariableBinding argBinding;
					codeStream.addVisibleLocalVariable(argBinding = this.arguments[i].binding);
					argBinding.recordInitializationStartPC(0);
				}
			}
			if (this.statements != null) {
				for (Statement stmt : this.statements) {
					stmt.generateCode(this.scope, codeStream);
				}
			}
			// if a problem got reported during code gen, then trigger problem method creation
			if (this.ignoreFurtherInvestigation) {
				throw new AbortMethod(this.scope.referenceCompilationUnit().compilationResult, null);
			}
//{ObjectTeams: fieldInit-hook
			endOfMethodHook(classFile);
// SH}
			if ((this.bits & ASTNode.NeedFreeReturn) != 0) {
				codeStream.return_();
			}
			// local variable attributes
			codeStream.exitUserScope(this.scope);
			codeStream.recordPositionsFrom(0, this.declarationSourceEnd);
//{ObjectTeams: finish faked argument for static role method:
			if (   syntheticArgumentBinding != null
				&& syntheticArgumentBinding.initializationPCs != null) // null happens when codeStream doesn't care about positions
				syntheticArgumentBinding.recordInitializationEndPC(classFile.codeStream.position);
// SH}
			try {
				classFile.completeCodeAttribute(codeAttributeOffset,this.scope);
			} catch(NegativeArraySizeException e) {
				throw new AbortMethod(this.scope.referenceCompilationUnit().compilationResult, null);
			}
//{ObjectTeams: record the completed byte code
            maybeRecordByteCode(classFile, methodAttributeOffset-6); // include method header
// SH}
			attributeNumber++;
		} else {
			checkArgumentsSize();
		}
		classFile.completeMethodInfo(this.binding, methodAttributeOffset, attributeNumber);
	}
//{ObjectTeams: uninvokable method:
	private int generateAbstractStaticRoleMethodCode(ClassFile classFile) {
		int codeAttributeOffset = classFile.contentsOffset;
		classFile.generateCodeAttributeHeader();
		CodeStream codeStream = classFile.codeStream;
		codeStream.reset(this, classFile);
		String errorMessage = this.scope.problemReporter().problemFactory.getLocalizedMessage(IProblem.AbstractStaticMethodCalled,
										new String[]{new String(this.binding.readableName())});
		codeStream.generateCodeAttributeForProblemMethod(errorMessage);
		int[] startLineIndexes = this.compilationResult.getLineSeparatorPositions();
		int problemLine = Util.getLineNumber(this.sourceStart, startLineIndexes, 0, startLineIndexes.length-1);
		classFile.completeCodeAttributeForProblemMethod(this, this.binding, codeAttributeOffset, startLineIndexes, problemLine);
		return 1; // one attribute: Code.
	}
// recording byte code
	public void maybeRecordByteCode(ClassFile classFile, int methodAttributeOffset) {
		RoleModel.maybeRecordByteCode(
		        this,
		        classFile,
		        methodAttributeOffset);
		boolean shouldRecordTeamMethod = false;
		if (this.isMappingWrapper._callin()) {
			List<CallinMappingDeclaration> mappings = this.model._declaringMappings;
			if (mappings != null) {
				for(CallinMappingDeclaration mapping : mappings) {
					if (mapping.isCallin() && mapping.roleMethodSpec.isPrivate()) {
						shouldRecordTeamMethod = true;
						break;
					}
				}
			}
		} else if (this.binding.declaringClass.id == IOTConstants.T_OrgObjectTeamsTeam) {
			if (this.scope.environment().getTeamMethodGenerator().registerSourceMethodBytes(this.binding))
				shouldRecordTeamMethod = true;
		}
		if (shouldRecordTeamMethod)
			MethodModel.getModel(this).recordByteCode(classFile, methodAttributeOffset);
	}
// new hook:
	/**
	 * Hook for adding statements just before the final return.
	 * Used for field initialization by RoleInitializationMethod.
	 */
	protected void endOfMethodHook(ClassFile classfile) {
		// NOOP.
	}
// SH}

	public void getAllAnnotationContexts(int targetType, List allAnnotationContexts) {
		// do nothing
	}

	private void checkArgumentsSize() {
		TypeBinding[] parameters = this.binding.parameters;
		int size = 1; // an abstract method or a native method cannot be static
		for (int i = 0, max = parameters.length; i < max; i++) {
			switch(parameters[i].id) {
				case TypeIds.T_long :
				case TypeIds.T_double :
					size += 2;
					break;
				default :
					size++;
					break;
			}
			if (size > 0xFF) {
				this.scope.problemReporter().noMoreAvailableSpaceForArgument(this.scope.locals[i], this.scope.locals[i].declaration);
			}
		}
	}

	@Override
	public CompilationUnitDeclaration getCompilationUnitDeclaration() {
		if (this.scope != null) {
			return this.scope.compilationUnitScope().referenceContext;
		}
		return null;
	}

	@Override
	public boolean hasErrors() {
		return this.ignoreFurtherInvestigation;
	}

	public boolean isAbstract() {

		if (this.binding != null)
			return this.binding.isAbstract();
		return (this.modifiers & ClassFileConstants.AccAbstract) != 0;
	}

	public boolean isAnnotationMethod() {

		return false;
	}

	public boolean isClinit() {

		return false;
	}

	public boolean isConstructor() {

		return false;
	}

	public boolean isCanonicalConstructor() {

		return false;
	}
	public boolean isDefaultConstructor() {

		return false;
	}

	public boolean isDefaultMethod() {
		return false;
	}

	public boolean isInitializationMethod() {

		return false;
	}

	public boolean isMethod() {

		return false;
	}

	public boolean isNative() {

		if (this.binding != null)
			return this.binding.isNative();
		return (this.modifiers & ClassFileConstants.AccNative) != 0;
	}

	public RecordComponent getRecordComponent() {
		return null;
	}

	public boolean isStatic() {

		if (this.binding != null)
			return this.binding.isStatic();
		return (this.modifiers & ClassFileConstants.AccStatic) != 0;
	}

	/**
	 * Fill up the method body with statement
	 * @param parser
	 * @param unit
	 */
	public abstract void parseStatements(Parser parser, CompilationUnitDeclaration unit);

	@Override
	public StringBuffer print(int tab, StringBuffer output) {

		if (this.javadoc != null) {
			this.javadoc.print(tab, output);
		}
		printIndent(tab, output);
		printModifiers(this.modifiers, output);
		if (this.annotations != null) {
			printAnnotations(this.annotations, output);
			output.append(' ');
		}

		TypeParameter[] typeParams = typeParameters();
		if (typeParams != null) {
			output.append('<');
			int max = typeParams.length - 1;
			for (int j = 0; j < max; j++) {
				typeParams[j].print(0, output);
				output.append(", ");//$NON-NLS-1$
			}
			typeParams[max].print(0, output);
			output.append('>');
		}

		printReturnType(0, output).append(this.selector).append('(');
		if (this.receiver != null) {
			this.receiver.print(0, output);
		}
		if (this.arguments != null) {
//{ObjectTeams: retrench enhanced callin args:
			int firstArg = 0;
			if (isCallin() && this.scope != null)
				firstArg = MethodSignatureEnhancer.getEnhancingArgLen(this.scope.compilerOptions().weavingScheme);
			for (int i = firstArg; i < this.arguments.length; i++) {
/* orig:
			for (int i = 0; i < this.arguments.length; i++) {
  :giro */
// SH}
				if (i > 0 || this.receiver != null) output.append(", "); //$NON-NLS-1$
				this.arguments[i].print(0, output);
			}
		}
		output.append(')');
		if (this.thrownExceptions != null) {
			output.append(" throws "); //$NON-NLS-1$
			for (int i = 0; i < this.thrownExceptions.length; i++) {
				if (i > 0) output.append(", "); //$NON-NLS-1$
				this.thrownExceptions[i].print(0, output);
			}
		}
		printBody(tab + 1, output);
		return output;
	}

	public StringBuffer printBody(int indent, StringBuffer output) {

		if (isAbstract() || (this.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0)
			return output.append(';');

		output.append(" {"); //$NON-NLS-1$
		if (this.statements != null) {
			for (int i = 0; i < this.statements.length; i++) {
				output.append('\n');
				this.statements[i].printStatement(indent, output);
			}
		}
//{ObjectTeams: signal missing body for copy inherited methods
		else
		{
			if(this.isCopied==true && this.statements == null){
				output.append("\n"); //$NON-NLS-1$
				printIndent(indent == 0 ? 0 : indent - 1,output);
				output.append("     /* CopyInheritance */"); //$NON-NLS-1$
			}
		}
//Markus Witte}
		output.append('\n');
		printIndent(indent == 0 ? 0 : indent - 1, output).append('}');
		return output;
	}

	public StringBuffer printReturnType(int indent, StringBuffer output) {

		return output;
	}

	public void resolve(ClassScope upperScope) {

		if (this.binding == null) {
			this.ignoreFurtherInvestigation = true;
		}

		try {
			bindArguments();
			resolveReceiver();
			bindThrownExceptions();
//{ObjectTeams: no javadoc in generated / copied methods
		  if (!(this.isGenerated || this.isCopied))
// SH}
			resolveAnnotations(this.scope, this.annotations, this.binding, this.isConstructor());

			long sourceLevel = this.scope.compilerOptions().sourceLevel;
			if (sourceLevel < ClassFileConstants.JDK1_8) // otherwise already checked via Argument.createBinding
				validateNullAnnotations(this.scope.environment().usesNullTypeAnnotations());

			resolveStatements();
			// check @Deprecated annotation presence
			if (this.binding != null
					&& (this.binding.getAnnotationTagBits() & TagBits.AnnotationDeprecated) == 0
					&& (this.binding.modifiers & ClassFileConstants.AccDeprecated) != 0
					&& sourceLevel >= ClassFileConstants.JDK1_5) {
				this.scope.problemReporter().missingDeprecatedAnnotationForMethod(this);
			}
		} catch (AbortMethod e) {
			// ========= abort on fatal error =============
			this.ignoreFurtherInvestigation = true;
		}
	}

	public void resolveReceiver() {
		if (this.receiver == null) return;

		if (this.receiver.modifiers != 0) {
			this.scope.problemReporter().illegalModifiers(this.receiver.declarationSourceStart, this.receiver.declarationSourceEnd);
		}

		TypeBinding resolvedReceiverType = this.receiver.type.resolvedType;
		if (this.binding == null || resolvedReceiverType == null || !resolvedReceiverType.isValidBinding()) {
			return;
		}

		ReferenceBinding declaringClass = this.binding.declaringClass;
		/* neither static methods nor methods in anonymous types can have explicit 'this' */
		if (this.isStatic() || declaringClass.isAnonymousType()) {
			this.scope.problemReporter().disallowedThisParameter(this.receiver);
			return; // No need to do further validation
		}

		ReferenceBinding enclosingReceiver = this.scope.enclosingReceiverType();
		if (this.isConstructor()) {
			/* Only non static member types or local types can declare explicit 'this' params in constructors */
			if (declaringClass.isStatic()
					|| (declaringClass.tagBits & (TagBits.IsLocalType | TagBits.IsMemberType)) == 0) { /* neither member nor local type */
				this.scope.problemReporter().disallowedThisParameter(this.receiver);
				return; // No need to do further validation
			}
			enclosingReceiver = enclosingReceiver.enclosingType();
		}

		char[][] tokens = (this.receiver.qualifyingName == null) ? null : this.receiver.qualifyingName.getName();
		if (this.isConstructor()) {
			if (tokens == null || tokens.length > 1 || !CharOperation.equals(enclosingReceiver.sourceName(), tokens[0])) {
				this.scope.problemReporter().illegalQualifierForExplicitThis(this.receiver, enclosingReceiver);
				this.receiver.qualifyingName = null;
			}
		} else if (tokens != null && tokens.length > 0) {
			this.scope.problemReporter().illegalQualifierForExplicitThis2(this.receiver);
			this.receiver.qualifyingName = null;
		}

		if (TypeBinding.notEquals(enclosingReceiver, resolvedReceiverType)) {
			this.scope.problemReporter().illegalTypeForExplicitThis(this.receiver, enclosingReceiver);
		}

		if (this.receiver.type.hasNullTypeAnnotation(AnnotationPosition.ANY)) {
			this.scope.problemReporter().nullAnnotationUnsupportedLocation(this.receiver.type);
		}
	}
	public void resolveJavadoc() {

		if (this.binding == null) return;
		if (this.javadoc != null) {
			this.javadoc.resolve(this.scope);
			return;
		}
//{ObjectTeams: do nothing for generated methods:
		if (this.scope.isGeneratedScope())
			return;
// SH}
		if (this.binding.declaringClass != null && !this.binding.declaringClass.isLocalType()) {
			// Set javadoc visibility
			int javadocVisibility = this.binding.modifiers & ExtraCompilerModifiers.AccVisibilityMASK;
			ClassScope classScope = this.scope.classScope();
			ProblemReporter reporter = this.scope.problemReporter();
			int severity = reporter.computeSeverity(IProblem.JavadocMissing);
			if (severity != ProblemSeverities.Ignore) {
				if (classScope != null) {
					javadocVisibility = Util.computeOuterMostVisibility(classScope.referenceType(), javadocVisibility);
				}
				int javadocModifiers = (this.binding.modifiers & ~ExtraCompilerModifiers.AccVisibilityMASK) | javadocVisibility;
				reporter.javadocMissing(this.sourceStart, this.sourceEnd, severity, javadocModifiers);
			}
		}
	}

	public void resolveStatements() {
//{ObjectTeams:
//      by now the signature is all prepared and wrapped:
        AnchorListAttribute.checkAddAnchorList(this);
//      still waiting for statements to be generated?
        if (this.isGenerated && this.statements == null)
			return;
        // currently only for callins within types with errors:
        // TODO: could this obsolete STATE_STATEMENTS_TRANSFORMED?
        TransformStatementsVisitor.checkTransformStatements(this);
// SH}

//{ObjectTeams: prepare Config for InsertTypeAdjustmentsVisitor:
      Config oldConfig = Config.createOrResetConfig(this);
	  try {
	// orig:
		if (this.statements != null) {
 			for (int i = 0, length = this.statements.length; i < length; i++) {
 				Statement stmt = this.statements[i];
 				stmt.resolve(this.scope);
	// :giro
				// order in this condition is relevant, first part resets flags!
	            if (   Config.requireTypeAdjustment()
	               	&& !this.scope.problemReporter().referenceContext.hasErrors())
	            {
	                this.statements[i].traverse(new InsertTypeAdjustmentsVisitor(), this.scope);
	            }
// SH}
			}
		} else if ((this.bits & UndocumentedEmptyBlock) != 0) {
			if (!this.isConstructor() || this.arguments != null) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=319626
				this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd+1);
			}
		}
//{ObjectTeams:
	  } finally {
	   	Config.removeOrRestore(oldConfig, this);
	  }
// SH}
	}

	@Override
	public void tagAsHavingErrors() {
		this.ignoreFurtherInvestigation = true;
//{ObjectTeams: avoid attempts to copy the bytecode of this method:
		if (this.binding != null) {
			this.binding.bytecodeMissing = true;
			if (this.scope != null) {
				// similarly hide local types from copy inheritance:
				SourceTypeBinding sourceType = this.scope.enclosingSourceType();
				if (sourceType != null && sourceType.roleModel != null)
					sourceType.roleModel.purgeLocalTypes(this.sourceStart, this.declarationSourceEnd);
			}
		}
// SH}
	}

	@Override
	public void tagAsHavingIgnoredMandatoryErrors(int problemId) {
		// Nothing to do for this context;
	}

//{ObjectTeams: and remove it again:
	@Override
	public void resetErrorFlag() {
		this.ignoreFurtherInvestigation = false;
	}
// SH}

	public void traverse(
		ASTVisitor visitor,
		ClassScope classScope) {
		// default implementation: subclass will define it
	}

	public TypeParameter[] typeParameters() {
	    return null;
	}

	void validateNullAnnotations(boolean useTypeAnnotations) {
		if (this.binding == null) return;
		// null annotations on parameters?
		if (!useTypeAnnotations) {
			if (this.binding.parameterNonNullness != null) {
				int length = this.binding.parameters.length;
				for (int i=0; i<length; i++) {
					if (this.binding.parameterNonNullness[i] != null) {
						long nullAnnotationTagBit =  this.binding.parameterNonNullness[i].booleanValue()
								? TagBits.AnnotationNonNull : TagBits.AnnotationNullable;
						if (!this.scope.validateNullAnnotation(nullAnnotationTagBit, this.arguments[i].type, this.arguments[i].annotations))
							this.binding.parameterNonNullness[i] = null;
					}
				}
			}
		} else {
			int length = this.binding.parameters.length;
			for (int i=0; i<length; i++) {
				this.scope.validateNullAnnotation(this.binding.parameters[i].tagBits, this.arguments[i].type, this.arguments[i].annotations);
// TODO(stephan) remove once we're sure:
//					this.binding.parameters[i] = this.binding.parameters[i].unannotated();
			}
		}
	}
}
