/*******************************************************************************
 * 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 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
 *								Bug 388630 - @NonNull diagnostics at line 0
 *								Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
 *								Bug 416176 - [1.8][compiler][null] null type annotations cause grief on type variables
 *								Bug 424727 - [compiler][null] NullPointerException in nullAnnotationUnsupportedLocation(ProblemReporter.java:5708)
 *								Bug 457210 - [1.8][compiler][null] Wrong Nullness errors given on full build build but not on incremental build?
 *     Keigo Imai - Contribution for  bug 388903 - Cannot extend inner class as an anonymous class when it extends the outer class
  *    Pierre-Yves B. <pyvesdev@gmail.com> - Contributions for
 *                              Bug 542520 - [JUnit 5] Warning The method xxx from the type X is never used locally is shown when using MethodSource
 *                              Bug 546084 - Using Junit 5s MethodSource leads to ClassCastException
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.eclipse.jdt.core.compiler.*;
import org.eclipse.jdt.internal.compiler.*;
import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions.WeavingScheme;
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.lookup.PackageBinding.TeamPackageBinding;
import org.eclipse.jdt.internal.compiler.parser.*;
import org.eclipse.jdt.internal.compiler.problem.*;
import org.eclipse.jdt.internal.compiler.util.SimpleSetOfCharArray;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.objectteams.otdt.core.compiler.IOTConstants;
import org.eclipse.objectteams.otdt.core.compiler.ISMAPConstants;
import org.eclipse.objectteams.otdt.core.exceptions.InternalCompilerError;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.AbstractMethodMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.CallinMappingDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.GuardPredicateDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.PrecedenceDeclaration;
import org.eclipse.objectteams.otdt.internal.core.compiler.ast.TypeValueParameter;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.BytecodeTransformer;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.CallinPrecedenceAttribute;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.InlineAttribute;
import org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.WordValueAttribute;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Config;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.Dependencies;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.ITranslationStates;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateHelper;
import org.eclipse.objectteams.otdt.internal.core.compiler.control.StateMemento;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.CallinCalloutBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.OTClassScope;
import org.eclipse.objectteams.otdt.internal.core.compiler.lookup.PrecedenceBinding;
import org.eclipse.objectteams.otdt.internal.core.compiler.model.*;
import org.eclipse.objectteams.otdt.internal.core.compiler.smap.AbstractSmapGenerator;
import org.eclipse.objectteams.otdt.internal.core.compiler.smap.RoleSmapGenerator;
import org.eclipse.objectteams.otdt.internal.core.compiler.smap.TeamSmapGenerator;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.copyinheritance.CopyInheritance;
import org.eclipse.objectteams.otdt.internal.core.compiler.statemachine.transformer.RoleSplitter;
import org.eclipse.objectteams.otdt.internal.core.compiler.util.Sorting;

/**
 * OTDT changes:
 *
 * New structural elements:
 * + baseclass for "playedBy"
 * + precedences
 * + callinCallouts for method mappings
 * + predicate
 *
 * + additional flags: isGenerated, isPurelyCopied
 *
 * Linkage to various models, which store additional information:
 * + TypeModel, RoleModel, TeamModel
 *
 * Role files (ROFI):
 * + store the role compilation unit
 *
 * ----
 * What: copy-inherited local types need to set constantPoolName in analyseCode already.
 * Why:  TODO(SH) document the reason
 *
 * What: avoid generation of default constructor for bound role
 * Why:  bound roles have a default lifting constructor instead.
 * Where:createsInternalConstructor()
 *
 * What: fine-grained dependency control in generateCode()
 * Why:  tsupers need to be generated first (including synthetic fields and methods),
 * 	     even if they are within the same compilation unit (nested teams)
 *
 * What: conclude base call analysis in conjunction with replace bindings
 * Where:internalAnalyseCode; See also MethodDeclaration (class comment).
 *
 * @version $Id: TypeDeclaration.java 23405 2010-02-03 17:02:18Z stephan $
 */
public class TypeDeclaration extends Statement implements ProblemSeverities, ReferenceContext,
//{ObjectTeams:
	ClassFileConstants
// SH}
{
	// Type decl kinds
	public static final int CLASS_DECL = 1;
	public static final int INTERFACE_DECL = 2;
	public static final int ENUM_DECL = 3;
	public static final int ANNOTATION_TYPE_DECL = 4;
	/*
	 * @noreference This field is not intended to be referenced by clients as it is a part of Java preview feature.
	 */
	public static final int RECORD_DECL = 5;

	public int modifiers = ClassFileConstants.AccDefault;
	public int modifiersSourceStart;
	public int functionalExpressionsCount = 0;
	public Annotation[] annotations;
	public char[] name;
	public TypeReference superclass;
	public TypeReference[] superInterfaces;
	public FieldDeclaration[] fields;
	public AbstractMethodDeclaration[] methods;
	public TypeDeclaration[] memberTypes;
	public SourceTypeBinding binding;
	public ClassScope scope;
	public MethodScope initializerScope;
	public MethodScope staticInitializerScope;
	public boolean ignoreFurtherInvestigation = false;
	public int maxFieldCount;
	public int declarationSourceStart;
	public int declarationSourceEnd;
	public int restrictedIdentifierStart = -1; // used only for record and permits restricted keywords.
	public int bodyStart;
	public int bodyEnd; // doesn't include the trailing comment if any.
	public CompilationResult compilationResult;
	public MethodDeclaration[] missingAbstractMethods;
	public Javadoc javadoc;

	public QualifiedAllocationExpression allocation; // for anonymous only
	public TypeDeclaration enclosingType; // for member types only

	public FieldBinding enumValuesSyntheticfield; 	// for enum
	public int enumConstantsCounter;

	// 1.5 support
	public TypeParameter[] typeParameters;

	// 14 Records preview support
	public RecordComponent[] recordComponents;
	public int nRecordComponents;
	public static Set<String> disallowedComponentNames;

	// 15 Sealed Type preview support
	public TypeReference[] permittedTypes;

	static {
		disallowedComponentNames = new HashSet<>(6);
		disallowedComponentNames.add("clone"); //$NON-NLS-1$
		disallowedComponentNames.add("finalize"); //$NON-NLS-1$
		disallowedComponentNames.add("getClass"); //$NON-NLS-1$
		disallowedComponentNames.add("hashCode"); //$NON-NLS-1$
		disallowedComponentNames.add("notify");   //$NON-NLS-1$
		disallowedComponentNames.add("notifyAll");//$NON-NLS-1$
		disallowedComponentNames.add("toString"); //$NON-NLS-1$
		disallowedComponentNames.add("wait"); //$NON-NLS-1$
	}

//{ObjectTeams: added fields and their accessors:

	// ==== New Main Structural Fields:
	public AbstractMethodMappingDeclaration[] callinCallouts;
	public PrecedenceDeclaration[] precedences;
	public TypeReference baseclass;


	// (stored by Parser.consumePredicate(), copied to methods from Parser.dispatchDeclarationInto())
	public GuardPredicateDeclaration predicate     = null;
	/** Copy all predicates within this type into this.methods. */
	public void copyPredicates () {
		int count = 0;
		if (this.predicate != null)
			count++;
		int max =   count
				  + ((this.methods == null) ?        0 : this.methods.length)
				  + ((this.callinCallouts == null) ? 0 : this.callinCallouts.length);
		GuardPredicateDeclaration[] guardMethods = new GuardPredicateDeclaration[max];
		if (this.predicate != null)
			guardMethods[0] = this.predicate;
		if (this.methods != null) {
			for (AbstractMethodDeclaration method : this.methods) {
				if (method.isMethod()) {
					MethodDeclaration md = (MethodDeclaration)method;
					if (md.predicate != null)
						guardMethods[count++] = md.predicate;
				}
			}
		}
		if (this.callinCallouts != null) {
			for (AbstractMethodMappingDeclaration mapping : this.callinCallouts) {
				if (mapping.isCallin()) {
					CallinMappingDeclaration callinDecl = (CallinMappingDeclaration)mapping;
					if (callinDecl.predicate != null)
						guardMethods[count++] = callinDecl.predicate;
				}
			}
		}
		if (count == 0)
			return;
		int oldLen = 0;
		if (this.methods != null)
			oldLen = this.methods.length;
		AbstractMethodDeclaration[] newMethods = new AbstractMethodDeclaration[oldLen+count];
		if (oldLen > 0)
			System.arraycopy(this.methods, 0, newMethods, 0, oldLen);
		if (count > 0)
			System.arraycopy(guardMethods, 0, newMethods, oldLen, count);
		this.methods = newMethods;
	}


	/** role files link back to their compilationUnit: */
	public CompilationUnitDeclaration compilationUnit = null;

	/** has this type been converted from ISourceType? */
	public boolean isConverted = false;

	/** Is this a role declaration defined in its on file (and compilation unit)? */
	public boolean isRoleFile() {
		if (this.compilationUnit == null)
			return false;
		for (int i = 0; i < this.compilationUnit.types.length; i++) {
			if (this.compilationUnit.types[i] == this)
				return true;
		}
		return false; // nested within a role file
	}
	/**
	 * Given that this is a role file, retreive the package from the enclosing team
	 * (and check for consistency with this role file's team package).
	 */
	public PlainPackageBinding getPackageOfTeam(ImportReference teamPackage, Scope aScope)
	{
		TypeDeclaration teamDecl = this.enclosingType;
		if (teamDecl == null)
			return null;
		// prefer name manipulation over RoleModel.getInterfaceAst(),
		// because we might be called before copied roles have connected class/ifc parts.
		char[] teamName= teamDecl.name;
		if (RoleSplitter.isClassPartName(teamName))
			teamName= RoleSplitter.getInterfacePartName(teamName);
		boolean match;
		if (teamDecl.binding != null)
			match = CharOperation.equals(teamPackage.tokens,
					TeamPackageBinding.adjustTeamPackageName(teamDecl.binding.compoundName));
		else
			match = CharOperation.equals(
						teamPackage.tokens[teamPackage.tokens.length-1],
						teamName);
		if (!match)
		{
			aScope.problemReporter().mismatchingPackageForRole(
					teamPackage.tokens,
					teamName,
					this.name,
					teamPackage.sourceStart,
					teamPackage.sourceEnd);
			return null;
		}
		return (PlainPackageBinding) teamDecl.scope.getCurrentPackage();
	}

	/** If this is a role file answer the number of nesting levels to the
	 *  outermost team. This is useful for converting source paths
	 *  	<code>some/pack/Team/Nested/Role.java</code>
	 *  to binary paths
	 *      <code>some/pack/Team$Nested$Role.class</code>
	 *  In the given example the depth would be 2 to signal the the class file
	 *  is stored two levels up from the source file's folder.
	 */
	public int getRoleFileDepth() {
		if (!isRoleFile())
			return 0;
		int depth = 0;
		TypeDeclaration current = this.enclosingType;
		while (current != null && current.isTeam()) {
			depth ++;
			current = current.enclosingType;
		}
		return depth;
	}


	// ==== Handling of models: TeamModel, TypeModel, RoleModel
    private TeamModel teamModel = null;
    public TeamModel getTeamModel() {
        if (this.teamModel == null)
            this.teamModel = new TeamModel(this);
        if ((this.teamModel.getBinding() == null) && (this.binding != null))
            this.teamModel.setBinding(this.binding);
        return this.teamModel;
    }

    private TypeModel model = null;
    public TypeModel getModel() {
        if (this.model == null)
            this.model = new TypeModel(this);
        return this.model;
    }

    private RoleModel roleModel = null;
    public RoleModel getRoleModel() {
    	// NOTE (SH): classes nested in a role have a role model but not AccRole.
    	// assert(((modifiers & AccRole) != 0));
    	assert(isRole());
        if (this.roleModel == null)
            this.roleModel = new RoleModel(this);
        if ((this.roleModel.getBinding() == null) && (this.binding != null))
            this.roleModel.setBinding(this.binding);
        return this.roleModel;
    }
    public RoleModel getRoleModel(TeamModel aTeamModel) {
        getRoleModel();
        this.roleModel.setTeamModel(aTeamModel);
        return this.roleModel;
    }

    public void setBinding(SourceTypeBinding binding) {
        this.binding = binding;
        getModel(); // intended side-effect
        if (isTeam())
            getTeamModel(); // intended side-effect
        if (isRole())
            getRoleModel(); // intended side-effect
    }

    /**
     * Parsing of org.objectteams.Team did not recognize the team,
     * adjust it and its roles now.
     */
	public void adjustOrgObjectteamsTeam() {
		this.modifiers |= ExtraCompilerModifiers.AccTeam;
		TypeDeclaration confined = null;
		TypeDeclaration otconfined = null;
		if (this.memberTypes != null) {
			for (int i = 0; i < this.memberTypes.length; i++) {
				TypeDeclaration memberType = this.memberTypes[i];
				memberType.modifiers |= ExtraCompilerModifiers.AccRole;
				if (CharOperation.equals(memberType.name, IOTConstants.OTCONFINED))
					otconfined = memberType;
				else if (CharOperation.equals(memberType.name, IOTConstants.CONFINED))
					confined = memberType;
			}
			if (confined != null && otconfined != null) {
				// link roles that are split manually (without using RoleSplitter).
				RoleModel ifcModel = confined.getRoleModel(getTeamModel());
				RoleModel clsModel = otconfined.getRoleModel(getTeamModel());
				ifcModel._classPart = otconfined;
				clsModel._interfacePart = confined;
			}
		}
	}

    // ==== new flags and boolean queries: ====

    /** not created from source but generated for one of the following reasons:
     *  - it's a role interface created by RoleSplitter
     *  - it's copied by CopyInheritance
     *  - it's a marker interface
     *  - it's a RoFi cache
     */
	public boolean isGenerated = false;

	/** copy inheritence without an overriding source role in the current team? */
	public boolean isPurelyCopied = false;

	public boolean willCatchAbort = false;

	public final boolean isTeam() {
		return (this.modifiers & ExtraCompilerModifiers.AccTeam) != 0;
	}

    /** Is this an actual role (not a generated interface)? */
  	public boolean isSourceRole() {
  		if ((this.modifiers & ClassFileConstants.AccEnum) != 0)
  			return false;

  		if(!(this.isGenerated && isInterface()))	{
  			if((this.modifiers & ExtraCompilerModifiers.AccRole) != 0)
				return true;
  		}
  		return false;
  	}

  	/** Is this class either a role or nested in a role? */
  	public boolean isRole() {
  		if ((this.modifiers & ExtraCompilerModifiers.AccRole) != 0)
  			return true;
  		if ((this.modifiers & ClassFileConstants.AccEnum) != 0)
  			return false;
  		if (   this.enclosingType == null
  			&& this.scope != null
  			&& this.scope.parent != null)
  		{
  			if (this.scope.parent.methodScope() != null)
  				// self healing: ;-)
  				this.enclosingType = this.scope.parent.methodScope().referenceType();
  		}
  		if (this.enclosingType != null)
  			return this.enclosingType.isRole();
  		if (this.binding != null)
  			return this.binding.isRole();
  		return false;
  	}
  	public boolean isDirectRole() {
  		return (this.modifiers & ExtraCompilerModifiers.AccRole) != 0;
  	}
  	public boolean isInterface() {
  		return kind(this.modifiers) == INTERFACE_DECL;
  	}
  	/** Is this an interface that was not created by role splitting? */
  	public boolean isRegularInterface() {
  		return (this.modifiers & (AccInterface|AccSynthetic)) == AccInterface;
  	}

  	/** Beautified name for roles (identical to ReferenceBinding.sourceName()). */
	public char[] sourceName() {
	    if (isSourceRole() && RoleSplitter.isClassPartName(this.name))
	        return RoleSplitter.getInterfacePartName(this.name);
		return this.name;
	}
// Markus Witte+SH}


public TypeDeclaration(CompilationResult compilationResult){
	this.compilationResult = compilationResult;
}

/*
 *	We cause the compilation task to abort to a given extent.
 */
@Override
public void abort(int abortLevel, CategorizedProblem problem) {
//{ObjectTeams: also mark in the state that we're done:
	if (!this.willCatchAbort) { // only on exceptions that will actually fly
		switch (abortLevel) {
			case AbortCompilation :
			case AbortCompilationUnit :
				StateHelper.setStateRecursive(this.scope.referenceCompilationUnit(), ITranslationStates.STATE_FINAL, false);
				break;
			case AbortMethod:
				break;
			default :
				StateHelper.setStateRecursive(this, ITranslationStates.STATE_FINAL, false);
		}
	}
// SH}
	switch (abortLevel) {
		case AbortCompilation :
			throw new AbortCompilation(this.compilationResult, problem);
		case AbortCompilationUnit :
			throw new AbortCompilationUnit(this.compilationResult, problem);
		case AbortMethod :
			throw new AbortMethod(this.compilationResult, problem);
		default :
			throw new AbortType(this.compilationResult, problem);
	}
}

/**
 * This method is responsible for adding a <clinit> method declaration to the type method collections.
 * Note that this implementation is inserting it in first place (as VAJ or javac), and that this
 * impacts the behavior of the method ConstantPool.resetForClinit(int. int), in so far as
 * the latter will have to reset the constant pool state accordingly (if it was added first, it does
 * not need to preserve some of the method specific cached entries since this will be the first method).
 * inserts the clinit method declaration in the first position.
 *
 * @see org.eclipse.jdt.internal.compiler.codegen.ConstantPool#resetForClinit(int, int)
 */
public final void addClinit() {
	//see comment on needClassInitMethod
	if (needClassInitMethod()) {
		int length;
		AbstractMethodDeclaration[] methodDeclarations;
		if ((methodDeclarations = this.methods) == null) {
			length = 0;
			methodDeclarations = new AbstractMethodDeclaration[1];
		} else {
			length = methodDeclarations.length;
			System.arraycopy(
				methodDeclarations,
				0,
				(methodDeclarations = new AbstractMethodDeclaration[length + 1]),
				1,
				length);
		}
		Clinit clinit = new Clinit(this.compilationResult);
		methodDeclarations[0] = clinit;
		// clinit is added in first location, so as to minimize the use of ldcw (big consumer of constant inits)
		clinit.declarationSourceStart = clinit.sourceStart = this.sourceStart;
		clinit.declarationSourceEnd = clinit.sourceEnd = this.sourceEnd;
		clinit.bodyEnd = this.sourceEnd;
		this.methods = methodDeclarations;
	}
}

/*
 * INTERNAL USE ONLY - Creates a fake method declaration for the corresponding binding.
 * It is used to report errors for missing abstract methods.
 */
public MethodDeclaration addMissingAbstractMethodFor(MethodBinding methodBinding) {
	TypeBinding[] argumentTypes = methodBinding.parameters;
	int argumentsLength = argumentTypes.length;
	//the constructor
	MethodDeclaration methodDeclaration = new MethodDeclaration(this.compilationResult);
	methodDeclaration.selector = methodBinding.selector;
	methodDeclaration.sourceStart = this.sourceStart;
	methodDeclaration.sourceEnd = this.sourceEnd;
	methodDeclaration.modifiers = methodBinding.getAccessFlags() & ~ClassFileConstants.AccAbstract;

	if (argumentsLength > 0) {
		String baseName = "arg";//$NON-NLS-1$
		Argument[] arguments = (methodDeclaration.arguments = new Argument[argumentsLength]);
		for (int i = argumentsLength; --i >= 0;) {
			arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, ClassFileConstants.AccDefault);
		}
	}

	//adding the constructor in the methods list
	if (this.missingAbstractMethods == null) {
		this.missingAbstractMethods = new MethodDeclaration[] { methodDeclaration };
	} else {
		MethodDeclaration[] newMethods;
		System.arraycopy(
			this.missingAbstractMethods,
			0,
			newMethods = new MethodDeclaration[this.missingAbstractMethods.length + 1],
			1,
			this.missingAbstractMethods.length);
		newMethods[0] = methodDeclaration;
		this.missingAbstractMethods = newMethods;
	}

	//============BINDING UPDATE==========================
	methodDeclaration.binding = new MethodBinding(
			methodDeclaration.modifiers | ClassFileConstants.AccSynthetic, //methodDeclaration
			methodBinding.selector,
			methodBinding.returnType,
			argumentsLength == 0 ? Binding.NO_PARAMETERS : argumentTypes, //arguments bindings
			methodBinding.thrownExceptions, //exceptions
			this.binding); //declaringClass

	methodDeclaration.scope = new MethodScope(this.scope, methodDeclaration, true);
	methodDeclaration.bindArguments();

/*		if (binding.methods == null) {
			binding.methods = new MethodBinding[] { methodDeclaration.binding };
		} else {
			MethodBinding[] newMethods;
			System.arraycopy(
				binding.methods,
				0,
				newMethods = new MethodBinding[binding.methods.length + 1],
				1,
				binding.methods.length);
			newMethods[0] = methodDeclaration.binding;
			binding.methods = newMethods;
		}*/
	//===================================================

	return methodDeclaration;
}

/**
 *	Flow analysis for a local innertype
 *
 */
@Override
public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
	if (this.ignoreFurtherInvestigation)
		return flowInfo;
	try {
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) {
			this.bits |= ASTNode.IsReachable;
			LocalTypeBinding localType = (LocalTypeBinding) this.binding;
//{ObjectTeams: constantPoolName is set in advance for copy-inherited local types:
		  if (localType.constantPoolName() == null)
// SH}
			localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
		}
		manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
		updateMaxFieldCount(); // propagate down the max field count
		internalAnalyseCode(flowContext, flowInfo);
	} catch (AbortType e) {
		this.ignoreFurtherInvestigation = true;
	}
	return flowInfo;
}

/**
 *	Flow analysis for a member innertype
 *
 */
public void analyseCode(ClassScope enclosingClassScope) {
	if (this.ignoreFurtherInvestigation)
		return;
	try {
		// propagate down the max field count
		updateMaxFieldCount();
		internalAnalyseCode(null, FlowInfo.initial(this.maxFieldCount));
	} catch (AbortType e) {
		this.ignoreFurtherInvestigation = true;
	}
}

/**
 *	Flow analysis for a local member innertype
 *
 */
public void analyseCode(ClassScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
	if (this.ignoreFurtherInvestigation)
		return;
	try {
		if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) {
			this.bits |= ASTNode.IsReachable;
			LocalTypeBinding localType = (LocalTypeBinding) this.binding;
			localType.setConstantPoolName(currentScope.compilationUnitScope().computeConstantPoolName(localType));
		}
		manageEnclosingInstanceAccessIfNecessary(currentScope, flowInfo);
		updateMaxFieldCount(); // propagate down the max field count
		internalAnalyseCode(flowContext, flowInfo);
	} catch (AbortType e) {
		this.ignoreFurtherInvestigation = true;
	}
}

/**
 *	Flow analysis for a package member type
 *
 */
public void analyseCode(CompilationUnitScope unitScope) {
	if (this.ignoreFurtherInvestigation)
		return;
	try {
//{ObjectTeams: make sure role units fetch the maxFieldCount from the outermost team:
/* orig:
		internalAnalyseCode(null, FlowInfo.initial(this.maxFieldCount));
  :giro */
		if (this.isRoleFile()) {
			if (this.binding.enclosingType() != null)
				Dependencies.ensureBindingState(this.binding.enclosingType(), ITranslationStates.STATE_RESOLVED);
			else if (!this.compilationResult.hasErrors())
				throw new InternalCompilerError("Role file unexpectedly has no enclosing team"); //$NON-NLS-1$
		}
		int myMaxFieldCount = this.scope.outerMostClassScope().referenceType().maxFieldCount;
		internalAnalyseCode(null, FlowInfo.initial(myMaxFieldCount));
// SH}
	} catch (AbortType e) {
		this.ignoreFurtherInvestigation = true;
	}
}

/**
 * Check for constructor vs. method with no return type.
 * Answers true if at least one constructor is defined
 */
public boolean checkConstructors(Parser parser) {
	//if a constructor has not the name of the type,
	//convert it into a method with 'null' as its return type
	boolean hasConstructor = false;
	if (this.methods != null) {
		for (int i = this.methods.length; --i >= 0;) {
			AbstractMethodDeclaration am;
			if ((am = this.methods[i]).isConstructor()) {
				if (!CharOperation.equals(am.selector, this.name)) {
					// the constructor was in fact a method with no return type
					// unless an explicit constructor call was supplied
					ConstructorDeclaration c = (ConstructorDeclaration) am;
					if (c.constructorCall == null || c.constructorCall.isImplicitSuper()) { //changed to a method
						MethodDeclaration m = parser.convertToMethodDeclaration(c, this.compilationResult);
						this.methods[i] = m;
					}
				} else {
					switch (kind(this.modifiers)) {
						case TypeDeclaration.INTERFACE_DECL :
							// report the problem and continue the parsing
							parser.problemReporter().interfaceCannotHaveConstructors((ConstructorDeclaration) am);
							break;
						case TypeDeclaration.ANNOTATION_TYPE_DECL :
							// report the problem and continue the parsing
							parser.problemReporter().annotationTypeDeclarationCannotHaveConstructor((ConstructorDeclaration) am);
							break;

					}
					hasConstructor = true;
				}
			}
		}
	}
	return hasConstructor;
}

@Override
public CompilationResult compilationResult() {
	return this.compilationResult;
}


public ConstructorDeclaration createDefaultConstructorForRecord(boolean needExplicitConstructorCall, boolean needToInsert) {
	//Add to method'set, the default constuctor that just recall the
	//super constructor with no arguments
	//The arguments' type will be positionned by the TC so just use
	//the default int instead of just null (consistency purpose)

	ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
	constructor.bits |= ASTNode.IsCanonicalConstructor | ASTNode.IsImplicit;
	constructor.selector = this.name;
	constructor.modifiers = this.modifiers & ExtraCompilerModifiers.AccVisibilityMASK;
//	constructor.modifiers = this.modifiers & ClassFileConstants.AccPublic;
//	constructor.modifiers |= ClassFileConstants.AccPublic; // JLS 14 8.10.5
	constructor.arguments = getArgumentsFromComponents(this.recordComponents);

	constructor.declarationSourceStart = constructor.sourceStart =
			constructor.bodyStart = this.sourceStart;
	constructor.declarationSourceEnd =
		constructor.sourceEnd = constructor.bodyEnd =  this.sourceStart - 1;

	//the super call inside the constructor
	if (needExplicitConstructorCall) {
		constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
		constructor.constructorCall.sourceStart = this.sourceStart;
		constructor.constructorCall.sourceEnd = this.sourceEnd;
	}
/* The body of the implicitly declared canonical constructor initializes each field corresponding
	 * to a record component with the corresponding formal parameter in the order that they appear
	 * in the record component list.*/
	List<Statement> statements = new ArrayList<>();
	int l = this.recordComponents != null ? this.recordComponents.length : 0;
	if (l > 0 && this.fields != null) {
		List<String> fNames = Arrays.stream(this.fields)
				.filter(f -> f.isARecordComponent)
				.map(f ->new String(f.name))
				.collect(Collectors.toList());
		for (int i = 0; i < l; ++i) {
			RecordComponent component = this.recordComponents[i];
			if (!fNames.contains(new String(component.name)))
				continue;
			FieldReference lhs = new FieldReference(component.name, 0);
			lhs.receiver = ThisReference.implicitThis();
			statements.add(new Assignment(lhs, new SingleNameReference(component.name, 0), 0));
		}
	}
	constructor.statements = statements.toArray(new Statement[0]);

	//adding the constructor in the methods list: rank is not critical since bindings will be sorted
	if (needToInsert) {
		if (this.methods == null) {
			this.methods = new AbstractMethodDeclaration[] { constructor };
		} else {
			AbstractMethodDeclaration[] newMethods;
			System.arraycopy(
				this.methods,
				0,
				newMethods = new AbstractMethodDeclaration[this.methods.length + 1],
				1,
				this.methods.length);
			newMethods[0] = constructor;
			this.methods = newMethods;
		}
	}
	return constructor;
}


private Argument[] getArgumentsFromComponents(RecordComponent[] comps) {
	Argument[] args2 = comps == null || comps.length == 0 ? ASTNode.NO_ARGUMENTS :
		new Argument[comps.length];
	int count = 0;
	for (RecordComponent comp : comps) {
		Argument argument = new Argument(comp.name, ((long)comp.sourceStart) << 32 | comp.sourceEnd,
				comp.type, 0); // no modifiers allowed for record components - enforce
		args2[count++] = argument;
	}
	return args2;
}

public ConstructorDeclaration createDefaultConstructor(	boolean needExplicitConstructorCall, boolean needToInsert) {
	if (this.isRecord())
		return createDefaultConstructorForRecord(needExplicitConstructorCall, needToInsert);
	//Add to method'set, the default constuctor that just recall the
	//super constructor with no arguments
	//The arguments' type will be positionned by the TC so just use
	//the default int instead of just null (consistency purpose)

//{ObjectTeams: no default constructor for bound roles
//      (cf. also AstEdit.removeDefaultConstructor())
// 	    also unbound roles defer constructor creation to Dependencies.establishMethodsCreated(RoleModel)
	// if roleModel != null assume were called later than during parsing:
	//  - from CopyInheritance.copyMethod(OTConfined)
	//  - crom Dependencies.establishMethodsCreated(RoleModel)
	if (this.isDirectRole() && this.roleModel == null)
		return null;
// SH}

	//the constructor
	ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
	constructor.bits |= ASTNode.IsDefaultConstructor;
	constructor.selector = this.name;
	constructor.modifiers = this.modifiers & ExtraCompilerModifiers.AccVisibilityMASK;

	//if you change this setting, please update the
	//SourceIndexer2.buildTypeDeclaration(TypeDeclaration,char[]) method
	constructor.declarationSourceStart = constructor.sourceStart = this.sourceStart;
	constructor.declarationSourceEnd =
		constructor.sourceEnd = constructor.bodyEnd = this.sourceEnd;

	//the super call inside the constructor
	if (needExplicitConstructorCall) {
		constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
		constructor.constructorCall.sourceStart = this.sourceStart;
		constructor.constructorCall.sourceEnd = this.sourceEnd;
	}

	//adding the constructor in the methods list: rank is not critical since bindings will be sorted
	if (needToInsert) {
		if (this.methods == null) {
			this.methods = new AbstractMethodDeclaration[] { constructor };
		} else {
			AbstractMethodDeclaration[] newMethods;
			System.arraycopy(
				this.methods,
				0,
				newMethods = new AbstractMethodDeclaration[this.methods.length + 1],
				1,
				this.methods.length);
			newMethods[0] = constructor;
			this.methods = newMethods;
		}
	}
	return constructor;
}

// anonymous type constructor creation: rank is important since bindings already got sorted
public MethodBinding createDefaultConstructorWithBinding(MethodBinding inheritedConstructorBinding, boolean eraseThrownExceptions) {
	//Add to method'set, the default constuctor that just recall the
	//super constructor with the same arguments
	String baseName = "$anonymous"; //$NON-NLS-1$
	TypeBinding[] argumentTypes = inheritedConstructorBinding.parameters;
	int argumentsLength = argumentTypes.length;
	//the constructor
	ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
	constructor.selector = new char[] { 'x' }; //no maining
	constructor.sourceStart = this.sourceStart;
	constructor.sourceEnd = this.sourceEnd;
	int newModifiers = this.modifiers & ExtraCompilerModifiers.AccVisibilityMASK;
	if (inheritedConstructorBinding.isVarargs()) {
		newModifiers |= ClassFileConstants.AccVarargs;
	}
	constructor.modifiers = newModifiers;
	constructor.bits |= ASTNode.IsDefaultConstructor;

	if (argumentsLength > 0) {
		Argument[] arguments = (constructor.arguments = new Argument[argumentsLength]);
		for (int i = argumentsLength; --i >= 0;) {
			arguments[i] = new Argument((baseName + i).toCharArray(), 0L, null /*type ref*/, ClassFileConstants.AccDefault);
		}
	}
	//the super call inside the constructor
	constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
	constructor.constructorCall.sourceStart = this.sourceStart;
	constructor.constructorCall.sourceEnd = this.sourceEnd;

	if (argumentsLength > 0) {
		Expression[] args1;
		args1 = constructor.constructorCall.arguments = new Expression[argumentsLength];
		for (int i = argumentsLength; --i >= 0;) {
			args1[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
		}
	}

	//adding the constructor in the methods list
	if (this.methods == null) {
		this.methods = new AbstractMethodDeclaration[] { constructor };
	} else {
		AbstractMethodDeclaration[] newMethods;
		System.arraycopy(this.methods, 0, newMethods = new AbstractMethodDeclaration[this.methods.length + 1], 1, this.methods.length);
		newMethods[0] = constructor;
		this.methods = newMethods;
	}

	//============BINDING UPDATE==========================
	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643, align with javac on JLS 15.12.2.6
	ReferenceBinding[] thrownExceptions = eraseThrownExceptions
			? this.scope.environment().convertToRawTypes(inheritedConstructorBinding.thrownExceptions, true, true)
			: inheritedConstructorBinding.thrownExceptions;

	SourceTypeBinding sourceType = this.binding;
	constructor.binding = new MethodBinding(
			constructor.modifiers, //methodDeclaration
			argumentsLength == 0 ? Binding.NO_PARAMETERS : argumentTypes, //arguments bindings
			thrownExceptions, //exceptions
			sourceType); //declaringClass
	constructor.binding.tagBits |= (inheritedConstructorBinding.tagBits & TagBits.HasMissingType);
	constructor.binding.modifiers |= ExtraCompilerModifiers.AccIsDefaultConstructor;
	if (inheritedConstructorBinding.parameterNonNullness != null // this implies that annotation based null analysis is enabled
			&& argumentsLength > 0)
	{
		// copy nullness info from inherited constructor to the new constructor:
		int len = inheritedConstructorBinding.parameterNonNullness.length;
		System.arraycopy(inheritedConstructorBinding.parameterNonNullness, 0,
				constructor.binding.parameterNonNullness = new Boolean[len], 0, len);
	}
	// TODO(stephan): do argument types already carry sufficient info about type annotations?

	constructor.scope = new MethodScope(this.scope, constructor, true);
	constructor.bindArguments();
	constructor.constructorCall.resolve(constructor.scope);

//{ObjectTeams: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=140643
/* orig:
	MethodBinding[] methodBindings = sourceType.methods(); // trigger sorting
	int length;
	System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[(length = methodBindings.length) + 1], 1, length);
	methodBindings[0] = constructor.binding;
	if (++length > 1)
		ReferenceBinding.sortMethods(methodBindings, 0, length);	// need to resort, since could be valid methods ahead (140643) - DOM needs eager sorting
	sourceType.setMethods(methodBindings);
  :giro*/
	// we have the infrastructure so use it:
	this.binding.addMethod(constructor.binding);
// SH}
	//===================================================

	return constructor.binding;
}

/**
 * Find the matching parse node, answers null if nothing found
 */
public FieldDeclaration declarationOf(FieldBinding fieldBinding) {
	if (fieldBinding != null && this.fields != null) {
		for (int i = 0, max = this.fields.length; i < max; i++) {
			FieldDeclaration fieldDecl;
			if ((fieldDecl = this.fields[i]).binding == fieldBinding)
				return fieldDecl;
		}
	}
	return null;
}

/**
 * Find the matching parse node, answers null if nothing found
 */
public TypeDeclaration declarationOf(MemberTypeBinding memberTypeBinding) {
	if (memberTypeBinding != null && this.memberTypes != null) {
		for (int i = 0, max = this.memberTypes.length; i < max; i++) {
			TypeDeclaration memberTypeDecl;
			if (TypeBinding.equalsEquals((memberTypeDecl = this.memberTypes[i]).binding, memberTypeBinding))
				return memberTypeDecl;
		}
	}
	return null;
}

/**
 * Find the matching parse node, answers null if nothing found
 */
public AbstractMethodDeclaration declarationOf(MethodBinding methodBinding) {
	if (methodBinding != null && this.methods != null) {
		for (int i = 0, max = this.methods.length; i < max; i++) {
			AbstractMethodDeclaration methodDecl;

			if ((methodDecl = this.methods[i]).binding == methodBinding)
				return methodDecl;
		}
	}
	return null;
}

/**
 * Find the matching parse node, answers null if nothing found
 */
public RecordComponent declarationOf(RecordComponentBinding recordComponentBinding) {
	if (recordComponentBinding != null && this.recordComponents != null) {
		for (int i = 0, max = this.fields.length; i < max; i++) {
			RecordComponent recordComponent;
			if ((recordComponent = this.recordComponents[i]).binding == recordComponentBinding)
				return recordComponent;
		}
	}
	return null;
}

//{ObjectTeams:	find source of a method mapping
public AbstractMethodMappingDeclaration declarationOf(CallinCalloutBinding mappingBinding) {
	if (mappingBinding != null && this.callinCallouts != null) {
		for (int i = 0, max = this.callinCallouts.length; i < max; i++) {
			AbstractMethodMappingDeclaration mappingDecl;

			if ((mappingDecl = this.callinCallouts[i]).binding == mappingBinding)
				return mappingDecl;
		}
	}
	return null;
}
// SH}
/**
 * Finds the matching type amoung this type's member types.
 * Returns null if no type with this name is found.
 * The type name is a compound name relative to this type
 * e.g. if this type is X and we're looking for Y.X.A.B
 *     then a type name would be {X, A, B}
 */
public TypeDeclaration declarationOfType(char[][] typeName) {
	int typeNameLength = typeName.length;
	if (typeNameLength < 1 || !CharOperation.equals(typeName[0], this.name)) {
		return null;
	}
	if (typeNameLength == 1) {
		return this;
	}
	char[][] subTypeName = new char[typeNameLength - 1][];
	System.arraycopy(typeName, 1, subTypeName, 0, typeNameLength - 1);
	for (int i = 0; i < this.memberTypes.length; i++) {
		TypeDeclaration typeDecl = this.memberTypes[i].declarationOfType(subTypeName);
		if (typeDecl != null) {
			return typeDecl;
		}
	}
	return null;
}

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

/* only for records */
public ConstructorDeclaration getConstructor(Parser parser) {
	if (this.methods != null) {
		for (int i = this.methods.length; --i >= 0;) {
			AbstractMethodDeclaration am;
			if ((am = this.methods[i]).isConstructor()) {
				if (!CharOperation.equals(am.selector, this.name)) {
					// the constructor was in fact a method with no return type
					// unless an explicit constructor call was supplied
					ConstructorDeclaration c = (ConstructorDeclaration) am;
					if (c.constructorCall == null || c.constructorCall.isImplicitSuper()) { //changed to a method
						MethodDeclaration m = parser.convertToMethodDeclaration(c, this.compilationResult);
						this.methods[i] = m;
					}
				} else {
					if (am instanceof CompactConstructorDeclaration) {
						CompactConstructorDeclaration ccd = (CompactConstructorDeclaration) am;
						ccd.recordDeclaration = this;
						if (ccd.arguments == null)
							ccd.arguments = getArgumentsFromComponents(this.recordComponents);
						return ccd;
					}
					// now we are looking at a "normal" constructor
					if (this.recordComponents == null && am.arguments == null)
						return (ConstructorDeclaration) am;
				}
			}
		}
	}
	/* At this point we can only say that there is high possibility that there is a constructor
	 * If it is a CCD, then definitely it is there (except for empty one); else we need to check
	 * the bindings to say that there is a canonical constructor. To take care at binding resolution time.
	 */
	return null;
}

/**
 * Generic bytecode generation for type
 */
public void generateCode(ClassFile enclosingClassFile) {
	if ((this.bits & ASTNode.HasBeenGenerated) != 0)
		return;
	this.bits |= ASTNode.HasBeenGenerated;
//{ObjectTeams: don't generate code from types that have entered the compilation process
//              via SourceTypeConverter (at least line number positions are missing).
//              There should be no need to generate this code (except for copy inheritance??).
	if (this.isConverted && !(isTeam() && getTeamModel().containsRoFi(true)))
		return;
	// from now on treat base class problem as fatal:
	if (RoleModel.isRoleWithBaseProblem(this))
		this.ignoreFurtherInvestigation= true;
// SH}
	if (this.ignoreFurtherInvestigation) {
		if (this.binding == null)
			return;
//{ObjectTeams: don't let tsub-roles search for byte code of this or members:
		markMissingBytecode();
// SH}
		ClassFile.createProblemType(
			this,
			this.scope.referenceCompilationUnit().compilationResult);
		return;
	}
//{ObjectTeams: ensure tsuper role has byte code generated,
//				even in nested team of the same compilation unit:
	if (isRole()) {

		// search common enclosing team:
		ReferenceBinding superTeam = this.binding.enclosingType().superclass();
		ReferenceBinding prevSuper = superTeam;
		ReferenceBinding currentSuper = superTeam.enclosingType();
		ClassFile enclosingSuperClassFile = null;
		superLoop: while (currentSuper != null) {
			ReferenceBinding current = this.binding.enclosingType().enclosingType();
			enclosingSuperClassFile = enclosingClassFile.enclosingClassFile;
			while (current != null) {
				if (TypeBinding.equalsEquals(current, currentSuper))
					break superLoop;
				current = current.enclosingType();
				enclosingSuperClassFile = enclosingSuperClassFile.enclosingClassFile;
			}
			prevSuper = currentSuper;
			currentSuper = currentSuper.enclosingType();
		}
		// if source type found then generate
		if (currentSuper != null && !prevSuper.isBinaryBinding()) {
			TypeDeclaration superType = ((SourceTypeBinding)prevSuper.erasure()).scope.referenceContext;
			superType.generateCode((ClassScope)null, enclosingSuperClassFile);
		}
	}
	if (isTeam()) {
		CopyInheritance.copySyntheticTeamMethods(this);
		getTeamModel().updateDecapsAccessIds();
	}
	// value paramters:
	this.binding.computeValueParameterSlotSizes();
// SH}
	try {
		// create the result for a compiled type
		ClassFile classFile = ClassFile.getNewInstance(this.binding);
		classFile.initialize(this.binding, enclosingClassFile, false);
		if (this.binding.isMemberType()) {
			classFile.recordInnerClasses(this.binding);
		} else if (this.binding.isLocalType()) {
			enclosingClassFile.recordInnerClasses(this.binding);
			classFile.recordInnerClasses(this.binding);
		}
		TypeVariableBinding[] typeVariables = this.binding.typeVariables();
		for (int i = 0, max = typeVariables.length; i < max; i++) {
			TypeVariableBinding typeVariableBinding = typeVariables[i];
			if ((typeVariableBinding.tagBits & TagBits.ContainsNestedTypeReferences) != 0) {
				Util.recordNestedType(classFile, typeVariableBinding);
			}
		}

		// generate all fiels
		classFile.addFieldInfos();
//{ObjectTeams: public role fields need accessors:
		if (isRole() && this.fields != null) {
			for (FieldDeclaration field : this.fields) {
				if (   !(field instanceof Initializer) // initializer doesn't have a binding set.
					&& !field.isGenerated
					&& field.binding.isPublic())
				{
					// prepare for accessed via externalized receiver:
					SourceTypeBinding enclosingTeam = (SourceTypeBinding)this.binding.enclosingType();
					enclosingTeam.addSyntheticMethod(field.binding, true, false/*superAccess*/, true/*externalizedReceiver*/);
					enclosingTeam.addSyntheticMethod(field.binding, false, false/*superAccess*/, true/*externalizedReceiver*/);
				}
			}
		}
// SH}

//{ObjectTeams: for teams get all members, including binary roles read via the RoFiCache
		if (isTeam()) {
			ReferenceBinding[] members = getTeamModel().getKnownRoles();
			for (int i = 0; i < members.length; i++)
				classFile.recordInnerClasses(members[i]);
		}
		new BytecodeTransformer().checkCopyNonWideConstants(this.scope, classFile);
// SH}
		if (this.memberTypes != null) {
//{ObjectTeams: FIXME(SH): should we need sorting? [need super-types first for copy inheritance	in nested teams]
//			if (this.isTeam())
//				sortMemberTypes();
// SH}
			for (int i = 0, max = this.memberTypes.length; i < max; i++) {
				TypeDeclaration memberType = this.memberTypes[i];
//{ObjectTeams: roles are already handled above
			  if (!memberType.isRole())
// SH}
				classFile.recordInnerClasses(memberType.binding);
				memberType.generateCode(this.scope, classFile);
			}
		}
		// generate all methods
		classFile.setForMethodInfos();
		if (this.methods != null) {
			for (int i = 0, max = this.methods.length; i < max; i++) {
//{ObjectTeams: not all methods have statements:
			  if (needToProcess(this.methods[i]))
// SH}
				this.methods[i].generateCode(this.scope, classFile);
			}
		}
		// generate all synthetic and abstract methods
		classFile.addSpecialMethods(this);

		if (this.ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors
			throw new AbortType(this.scope.referenceCompilationUnit().compilationResult, null);
		}
//{ObjectTeams: role files and copy inheritance:
		// store a role file cache?
		if (isTeam())
			getTeamModel().generateRoFiCache(classFile);

		// support for JSR-045:
		char[] smap = getSMAP();
		if (smap != null)
		{
			getModel().addAttribute(InlineAttribute.sourceDebugExtensionAttribute(smap));
		}
// SH}

		// finalize the compiled type result
		classFile.addAttributes();
		this.scope.referenceCompilationUnit().compilationResult.record(
			this.binding.constantPoolName(),
			classFile);
	} catch (AbortType e) {
		if (this.binding == null)
			return;
		ClassFile.createProblemType(
			this,
			this.scope.referenceCompilationUnit().compilationResult);
	}
//{ObjectTeams: mark as done:
	finally {
		if (this.isTeam())
			this.teamModel.setState(ITranslationStates.STATE_BYTE_CODE_GENERATED);
	}
// SH}
}

//{ObjectTeams: don't let tsub-roles search for byte code of this or members:
private void markMissingBytecode() {
	// descend into all methods and nested types (members and local types)
    traverse(new ASTVisitor() {
    	@Override
		public boolean visit(MethodDeclaration method, ClassScope classScope) {
    		if (method.binding != null)
    			method.binding.bytecodeMissing = true;
    		return true;
    	}
    	@Override
		public boolean visit(ConstructorDeclaration ctor, ClassScope classScope) {
    		if (ctor.binding != null)
    			ctor.binding.bytecodeMissing = true;
    		return true;
    	}
    	@Override
		public boolean visit(TypeDeclaration type, ClassScope classScope) {
    		type.tagAsHavingErrors();
    		return true;
    	}
        @Override
		public boolean visit(TypeDeclaration type, BlockScope blockScope) {
    		type.tagAsHavingErrors();
    		return true;
    	}
	}, this.scope);
}
// SH}

//{ObjectTeams: trigger for smap generation
private char[] getSMAP() {

    //if type is an interface don't generate anything
    if (isInterface())
		return null;

    AbstractSmapGenerator generator = createSmapGenerator();

    if (generator == null)
        return null;

    generator.addStratum(ISMAPConstants.OTJ_STRATUM_NAME);
    generator.setDefaultStratum(ISMAPConstants.OTJ_STRATUM_NAME);

    return generator.generate();
}

protected AbstractSmapGenerator createSmapGenerator()
{
    if (isRole())
        return new RoleSmapGenerator(this);

    if (isTeam())
        return new TeamSmapGenerator(this);

    // NOTE: currently no special treatment for nested team (team&role)

    return null;
}
//ike}


/**
 * Bytecode generation for a local inner type (API as a normal statement code gen)
 */
@Override
public void generateCode(BlockScope blockScope, CodeStream codeStream) {
	if ((this.bits & ASTNode.IsReachable) == 0) {
		return;
	}
	if ((this.bits & ASTNode.HasBeenGenerated) != 0) return;
	int pc = codeStream.position;
	if (this.binding != null) {
		SyntheticArgumentBinding[] enclosingInstances = ((NestedTypeBinding) this.binding).syntheticEnclosingInstances();
		for (int i = 0, slotSize = 0, count = enclosingInstances == null ? 0 : enclosingInstances.length; i < count; i++){
			SyntheticArgumentBinding enclosingInstance = enclosingInstances[i];
			enclosingInstance.resolvedPosition = ++slotSize; // shift by 1 to leave room for aload0==this
			if (slotSize > 0xFF) { // no more than 255 words of arguments
				blockScope.problemReporter().noMoreAvailableSpaceForArgument(enclosingInstance, blockScope.referenceType());
			}
		}
	}
	generateCode(codeStream.classFile);
	codeStream.recordPositionsFrom(pc, this.sourceStart);
}

/**
 * Bytecode generation for a member inner type
 */
public void generateCode(ClassScope classScope, ClassFile enclosingClassFile) {
	if ((this.bits & ASTNode.HasBeenGenerated) != 0) return;
//{ObjectTeams: ensure intermediate steps for role files:
	if (this.binding != null)
		Dependencies.ensureBindingState(this.binding, ITranslationStates.STATE_BYTE_CODE_GENERATED-1);
// SH}
	if (this.binding != null) {
		SyntheticArgumentBinding[] enclosingInstances = ((NestedTypeBinding) this.binding).syntheticEnclosingInstances();
		for (int i = 0, slotSize = 0, count = enclosingInstances == null ? 0 : enclosingInstances.length; i < count; i++){
			SyntheticArgumentBinding enclosingInstance = enclosingInstances[i];
			enclosingInstance.resolvedPosition = ++slotSize; // shift by 1 to leave room for aload0==this
			if (slotSize > 0xFF) { // no more than 255 words of arguments
				classScope.problemReporter().noMoreAvailableSpaceForArgument(enclosingInstance, classScope.referenceType());
			}
		}
	}
	generateCode(enclosingClassFile);
}

/**
 * Bytecode generation for a package member
 */
public void generateCode(CompilationUnitScope unitScope) {
	generateCode((ClassFile) null);
}

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

/**
 *	Common flow analysis for all types
 */
private void internalAnalyseCode(FlowContext flowContext, FlowInfo flowInfo) {
	checkYieldUsage();
//{ObjectTeams: postponed from resolve() to also catch import usage from late statement generators.
	if (isRoleFile() && !this.binding.isSynthInterface())
		if (!this.compilationResult.hasSyntaxError)
			this.scope.referenceCompilationUnit().checkUnusedImports();
	if (this.scope instanceof OTClassScope)
		((OTClassScope)this.scope).checkUnusedImports();
// SH}
	if (!this.binding.isUsed() && this.binding.isOrEnclosedByPrivateType()) {
		if (!this.scope.referenceCompilationUnit().compilationResult.hasSyntaxError) {
			this.scope.problemReporter().unusedPrivateType(this);
		}
	}

	// https://bugs.eclipse.org/bugs/show_bug.cgi?id=385780
	if (this.typeParameters != null &&
			!this.scope.referenceCompilationUnit().compilationResult.hasSyntaxError) {
		for (int i = 0, length = this.typeParameters.length; i < length; ++i) {
			TypeParameter typeParameter = this.typeParameters[i];
//{ObjectTeams: exclude:
		  if (!(typeParameter instanceof TypeValueParameter))
// SH}
			if ((typeParameter.binding.modifiers & ExtraCompilerModifiers.AccLocallyUsed) == 0) {
				this.scope.problemReporter().unusedTypeParameter(typeParameter);
			}
		}
	}

	// for local classes we use the flowContext as our parent, but never use an initialization context for this purpose
	// see Bug 360328 - [compiler][null] detect null problems in nested code (local class inside a loop)
	FlowContext parentContext = (flowContext instanceof InitializationFlowContext) ? null : flowContext;
	InitializationFlowContext initializerContext = new InitializationFlowContext(parentContext, this, flowInfo, flowContext, this.initializerScope);
	// no static initializer in local classes, thus no need to set parent:
	InitializationFlowContext staticInitializerContext = new InitializationFlowContext(null, this, flowInfo, flowContext, this.staticInitializerScope);
	FlowInfo nonStaticFieldInfo = flowInfo.unconditionalFieldLessCopy();
	FlowInfo staticFieldInfo = flowInfo.unconditionalFieldLessCopy();
	if (this.fields != null) {
		for (int i = 0, count = this.fields.length; i < count; i++) {
			FieldDeclaration field = this.fields[i];
			if (field.isStatic()) {
				if ((staticFieldInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0)
					field.bits &= ~ASTNode.IsReachable;

				/*if (field.isField()){
					staticInitializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
				} else {*/
				staticInitializerContext.handledExceptions = Binding.ANY_EXCEPTION; // tolerate them all, and record them
				/*}*/
				staticFieldInfo = field.analyseCode(this.staticInitializerScope, staticInitializerContext, staticFieldInfo);
				// in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
				// branch, since the previous initializer already got the blame.
				if (staticFieldInfo == FlowInfo.DEAD_END) {
					this.staticInitializerScope.problemReporter().initializerMustCompleteNormally(field);
					staticFieldInfo = FlowInfo.initial(this.maxFieldCount).setReachMode(FlowInfo.UNREACHABLE_OR_DEAD);
				}
			} else {
				if ((nonStaticFieldInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0)
					field.bits &= ~ASTNode.IsReachable;

				/*if (field.isField()){
					initializerContext.handledExceptions = NoExceptions; // no exception is allowed jls8.3.2
				} else {*/
					initializerContext.handledExceptions = Binding.ANY_EXCEPTION; // tolerate them all, and record them
				/*}*/
				nonStaticFieldInfo = field.analyseCode(this.initializerScope, initializerContext, nonStaticFieldInfo);
				// in case the initializer is not reachable, use a reinitialized flowInfo and enter a fake reachable
				// branch, since the previous initializer already got the blame.
				if (nonStaticFieldInfo == FlowInfo.DEAD_END) {
					this.initializerScope.problemReporter().initializerMustCompleteNormally(field);
					nonStaticFieldInfo = FlowInfo.initial(this.maxFieldCount).setReachMode(FlowInfo.UNREACHABLE_OR_DEAD);
				}
			}
		}
	}
//{ObjectTeams: manage synthetics for value parameters:
	if (this.typeParameters != null) {
		// type value parameters are non static fields, which are a-priori assigned.
		nonStaticFieldInfo = TypeValueParameter.analyseCode(this.typeParameters, this.initializerScope, flowContext, nonStaticFieldInfo);
	}
	// analyse member types in topological order (super before sub):
	Sorting.sortMemberTypes(this);
// SH}
	if (this.memberTypes != null) {
		for (int i = 0, count = this.memberTypes.length; i < count; i++) {
			if (flowContext != null){ // local type
				this.memberTypes[i].analyseCode(this.scope, flowContext, nonStaticFieldInfo.copy().setReachMode(flowInfo.reachMode())); // reset reach mode in case initializers did abrupt completely
			} else {
				this.memberTypes[i].analyseCode(this.scope);
			}
		}
	}
	if (this.scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK9) {
		// synthesize <clinit> if one is not present. Required to initialize
		// synthetic final fields as modifying final fields outside of a <clinit>
		// is disallowed in Java 9
//{ObjectTeams: robustness:
/* orig:
		if (this.methods == null || !this.methods[0].isClinit()) {
  :giro */
		if (this.methods == null || this.methods.length == 0 || !this.methods[0].isClinit()) {
// SH}
			Clinit clinit = new Clinit(this.compilationResult);
			clinit.declarationSourceStart = clinit.sourceStart = this.sourceStart;
			clinit.declarationSourceEnd = clinit.sourceEnd = this.sourceEnd;
			clinit.bodyEnd = this.sourceEnd;
			int length = this.methods == null ? 0 : this.methods.length;
			AbstractMethodDeclaration[] methodDeclarations = new AbstractMethodDeclaration[length + 1];
			methodDeclarations[0] = clinit;
			if (this.methods != null)
				System.arraycopy(this.methods, 0, methodDeclarations, 1, length);
		}
	}
//{ObjectTeams: RoFi with incomplete method bodies don't analyze:
	if (this.compilationUnit == null || this.compilationUnit.parseMethodBodies)
// SH}
	if (this.methods != null) {
		UnconditionalFlowInfo outerInfo = flowInfo.unconditionalFieldLessCopy();
		FlowInfo constructorInfo = nonStaticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo);
		SimpleSetOfCharArray jUnitMethodSourceValues = getJUnitMethodSourceValues();
		for (int i = 0, count = this.methods.length; i < count; i++) {
			AbstractMethodDeclaration method = this.methods[i];
			if (method.ignoreFurtherInvestigation)
				continue;
//{ObjectTeams: have statements to analyze?
			if (!(needToProcess(method)))
				continue;
// SH}
			if (method.isInitializationMethod()) {
				// pass down the appropriate initializerContext:
				if (method.isStatic()) { // <clinit>
					((Clinit)method).analyseCode(
						this.scope,
						staticInitializerContext,
						staticFieldInfo.unconditionalInits().discardNonFieldInitializations().addInitializationsFrom(outerInfo));
				} else { // constructor
					((ConstructorDeclaration)method).analyseCode(this.scope, initializerContext, constructorInfo.copy(), flowInfo.reachMode());
				}
			} else { // regular method
				// JUnit 5 only accepts methods without arguments for method sources
				if (method.arguments == null && jUnitMethodSourceValues.includes(method.selector) && method.binding != null) {
					method.binding.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
				}
				// pass down the parentContext (NOT an initializer context, see above):
				((MethodDeclaration)method).analyseCode(this.scope, parentContext, flowInfo.copy());
			}
		}
	}
	// enable enum support ?
	if (this.binding.isEnum() && !this.binding.isAnonymousType()) {
		this.enumValuesSyntheticfield = this.binding.addSyntheticFieldForEnumValues();
	}
//{ObjectTeams: callins and precedence:
	mergePrecedences();
	// now check for replace callin bindings with missing base call result:
	if (this.callinCallouts != null)  {
		WeavingScheme weavingScheme = this.initializerScope.compilerOptions().weavingScheme;
		for (int i = 0; i < this.callinCallouts.length; i++) {
			if (this.callinCallouts[i].isReplaceCallin())
				((CallinMappingDeclaration)this.callinCallouts[i]).analyseDetails(this, weavingScheme);
		}
	}
// SH}
}

//{ObjectTeams:
// analyseCode and generateCode only process methods with statements plus default ctors
private boolean needToProcess(AbstractMethodDeclaration method) {
	return    method.hasParsedStatements
		   // different reasons, why it may be normal for a method to have no statements:
	       || method.isDefaultConstructor() || method.isCanonicalConstructor() || method.isClinit() || method.isAbstract()
	       || method.isCopied;
}

/**
 * After precedences of this type and super types are resolved,
 * try to merge them (inherited & defined in different roles)
 * and check for duplicates.
 */
private void mergePrecedences() {
	// merge precedences:
	PrecedenceBinding[] precedenceBindings
							= this.binding.precedences
							= PrecedenceDeclaration.mergePrecedences(this);

	// outermost team writes the byte code attribute:
	if (precedenceBindings != PrecedenceBinding.NoPrecedences) {
		if (   isTeam()
			&& (   this.enclosingType == null
				|| !this.enclosingType.isTeam()))
		{
			this.model = getTeamModel();
			for (int i = 0; i < precedenceBindings.length; i++) {
				// includes flattening of class based precedences and elimination of overrides:
				CallinCalloutBinding[] callins = precedenceBindings[i].callins(true);
				this.model.addAttribute(new CallinPrecedenceAttribute(this.binding, callins));
			}
		}
	}

	// check for success only after everything is copied, merged and flattened:
	if (isTeam()
		&& (    this.enclosingType == null
			|| !this.enclosingType.isTeam())) // only check outer-most team.
		PrecedenceBinding.checkDuplicates(this);
}
// SH}

private void checkYieldUsage() {
	long sourceLevel = this.scope.compilerOptions().sourceLevel;
	if (sourceLevel < ClassFileConstants.JDK14 || this.name == null ||
			!("yield".equals(new String(this.name)))) //$NON-NLS-1$
		return;
	if (sourceLevel >= ClassFileConstants.JDK14) {
		this.scope.problemReporter().switchExpressionsYieldTypeDeclarationError(this);
	} else {
		this.scope.problemReporter().switchExpressionsYieldTypeDeclarationWarning(this);
	}
}

private SimpleSetOfCharArray getJUnitMethodSourceValues() {
	SimpleSetOfCharArray junitMethodSourceValues = new SimpleSetOfCharArray();
	for (AbstractMethodDeclaration methodDeclaration : this.methods) {
		if (methodDeclaration.annotations != null) {
			for (Annotation annotation : methodDeclaration.annotations) {
				if (annotation.resolvedType != null && annotation.resolvedType.id == TypeIds.T_OrgJunitJupiterParamsProviderMethodSource) {
					addJUnitMethodSourceValues(junitMethodSourceValues, annotation, methodDeclaration.selector);
				}
			}
		}
	}
	return junitMethodSourceValues;
}

private void addJUnitMethodSourceValues(SimpleSetOfCharArray junitMethodSourceValues, Annotation annotation, char[] methodName) {
	for (MemberValuePair memberValuePair : annotation.memberValuePairs()) {
		if (CharOperation.equals(memberValuePair.name, TypeConstants.VALUE)) {
			Expression value = memberValuePair.value;
			if (value instanceof ArrayInitializer) { // e.g. @MethodSource({ "someMethod" })
				ArrayInitializer arrayInitializer = (ArrayInitializer) value;
				for (Expression arrayValue : arrayInitializer.expressions) {
					junitMethodSourceValues.add(getValueAsChars(arrayValue));
				}
			} else {
				junitMethodSourceValues.add(getValueAsChars(value));
			}
			return;
		}
	}
	// value member not specified (i.e. marker annotation): JUnit 5 defaults to the test method's name
	junitMethodSourceValues.add(methodName);
}

private char[] getValueAsChars(Expression value) {
	if (value instanceof StringLiteral) { // e.g. "someMethod"
		return ((StringLiteral) value).source;
	} else if (value.constant instanceof StringConstant) { // e.g. SOME_CONSTANT + "value"
		return ((StringConstant) value.constant).stringValue().toCharArray();
	}
	return CharOperation.NO_CHAR;
}

public final static int kind(int flags) {
	switch (flags & (ClassFileConstants.AccInterface|ClassFileConstants.AccAnnotation|ClassFileConstants.AccEnum|ExtraCompilerModifiers.AccRecord)) {
		case ClassFileConstants.AccInterface :
			return TypeDeclaration.INTERFACE_DECL;
		case ClassFileConstants.AccInterface|ClassFileConstants.AccAnnotation :
			return TypeDeclaration.ANNOTATION_TYPE_DECL;
		case ClassFileConstants.AccEnum :
			return TypeDeclaration.ENUM_DECL;
		case ExtraCompilerModifiers.AccRecord :
			return TypeDeclaration.RECORD_DECL;
		default :
			return TypeDeclaration.CLASS_DECL;
	}
}

public boolean isRecord() {
	return (this.modifiers & ExtraCompilerModifiers.AccRecord) != 0;
}

/*
 * Access emulation for a local type
 * force to emulation of access to direct enclosing instance.
 * By using the initializer scope, we actually only request an argument emulation, the
 * field is not added until actually used. However we will force allocations to be qualified
 * with an enclosing instance.
 * 15.9.2
 */
public void manageEnclosingInstanceAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) != 0) return;
	NestedTypeBinding nestedType = (NestedTypeBinding) this.binding;

	MethodScope methodScope = currentScope.methodScope();
	if (!methodScope.isStatic && !methodScope.isConstructorCall){
		nestedType.addSyntheticArgumentAndField(nestedType.enclosingType());
	}
	// add superclass enclosing instance arg for anonymous types (if necessary)
	if (nestedType.isAnonymousType()) {
		ReferenceBinding superclassBinding = (ReferenceBinding)nestedType.superclass.erasure();
		if (superclassBinding.enclosingType() != null && !superclassBinding.isStatic()) {
			if (!superclassBinding.isLocalType()
					|| ((NestedTypeBinding)superclassBinding).getSyntheticField(superclassBinding.enclosingType(), true) != null
					|| superclassBinding.isMemberType()){
				nestedType.addSyntheticArgument(superclassBinding.enclosingType());
			}
		}
		// From 1.5 on, provide access to enclosing instance synthetic constructor argument when declared inside constructor call
		// only for direct anonymous type
		//public class X {
		//	void foo() {}
		//	class M {
		//		M(Object o) {}
		//		M() { this(new Object() { void baz() { foo(); }}); } // access to #foo() indirects through constructor synthetic arg: val$this$0
		//	}
		//}
		if (!methodScope.isStatic && methodScope.isConstructorCall && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5) {
			ReferenceBinding enclosing = nestedType.enclosingType();
			if (enclosing.isNestedType()) {
				NestedTypeBinding nestedEnclosing = (NestedTypeBinding)enclosing;
//					if (nestedEnclosing.findSuperTypeErasingTo(nestedEnclosing.enclosingType()) == null) { // only if not inheriting
					SyntheticArgumentBinding syntheticEnclosingInstanceArgument = nestedEnclosing.getSyntheticArgument(nestedEnclosing.enclosingType(), true, false);
					if (syntheticEnclosingInstanceArgument != null) {
						nestedType.addSyntheticArgumentAndField(syntheticEnclosingInstanceArgument);
					}
				}
//				}
		}
	}
}

/**
 * Access emulation for a local member type
 * force to emulation of access to direct enclosing instance.
 * By using the initializer scope, we actually only request an argument emulation, the
 * field is not added until actually used. However we will force allocations to be qualified
 * with an enclosing instance.
 *
 * Local member cannot be static.
 */
public void manageEnclosingInstanceAccessIfNecessary(ClassScope currentScope, FlowInfo flowInfo) {
	if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) {
	NestedTypeBinding nestedType = (NestedTypeBinding) this.binding;
	nestedType.addSyntheticArgumentAndField(this.binding.enclosingType());
	}
}

/**
 * A <clinit> will be requested as soon as static fields or assertions are present. It will be eliminated during
 * classfile creation if no bytecode was actually produced based on some optimizations/compiler settings.
 */
public final boolean needClassInitMethod() {
	// always need a <clinit> when assertions are present
	if ((this.bits & ASTNode.ContainsAssertion) != 0)
		return true;

	switch (kind(this.modifiers)) {
		case TypeDeclaration.INTERFACE_DECL:
		case TypeDeclaration.ANNOTATION_TYPE_DECL:
			return this.fields != null; // fields are implicitly statics
		case TypeDeclaration.ENUM_DECL:
			return true; // even if no enum constants, need to set $VALUES array
	}
	if (this.fields != null) {
		for (int i = this.fields.length; --i >= 0;) {
			FieldDeclaration field = this.fields[i];
			//need to test the modifier directly while there is no binding yet
			if ((field.modifiers & ClassFileConstants.AccStatic) != 0)
				return true; // TODO (philippe) shouldn't it check whether field is initializer or has some initial value ?
		}
	}
	return false;
}

public void parseMethods(Parser parser, CompilationUnitDeclaration unit) {
	//connect method bodies
	if (unit.ignoreMethodBodies)
		return;

//{ObjectTeams: enable OT keywords?
	if (isTeam() || isRoleFile())
		parser.scanner.enterOTSource();
// SH}
	//members
	if (this.memberTypes != null) {
		int length = this.memberTypes.length;
		for (int i = 0; i < length; i++) {
			TypeDeclaration typeDeclaration = this.memberTypes[i];
//{ObjectTeams: don't parse role files via containing team, but let Dependencies do the job.
		  if (!typeDeclaration.isRoleFile()) {
// orig:
			typeDeclaration.parseMethods(parser, unit);
			this.bits |= (typeDeclaration.bits & ASTNode.HasSyntaxErrors);
// :giro
		  }
// SH}
		}
	}

	//methods
	if (this.methods != null) {
		int length = this.methods.length;
		for (int i = 0; i < length; i++) {
			AbstractMethodDeclaration abstractMethodDeclaration = this.methods[i];
			abstractMethodDeclaration.parseStatements(parser, unit);
			this.bits |= (abstractMethodDeclaration.bits & ASTNode.HasSyntaxErrors);
		}
	}

	//initializers
	if (this.fields != null) {
		int length = this.fields.length;
		for (int i = 0; i < length; i++) {
			final FieldDeclaration fieldDeclaration = this.fields[i];
			switch(fieldDeclaration.getKind()) {
				case AbstractVariableDeclaration.INITIALIZER:
					((Initializer) fieldDeclaration).parseStatements(parser, this, unit);
					this.bits |= (fieldDeclaration.bits & ASTNode.HasSyntaxErrors);
					break;
			}
		}
	}
//{ObjectTeams: method mappings:
	if (this.callinCallouts != null) {
		int length = this.callinCallouts.length;
		for (int i = 0; i < length; i++) {
			this.callinCallouts[i].parseParamMappings(parser, unit);
		}
	}
// SH}
}

@Override
public StringBuffer print(int indent, StringBuffer output) {
	if (this.javadoc != null) {
		this.javadoc.print(indent, output);
	}
	if ((this.bits & ASTNode.IsAnonymousType) == 0) {
		printIndent(indent, output);
		printHeader(0, output);
	}
	return printBody(indent, output);
}

public StringBuffer printBody(int indent, StringBuffer output) {
	output.append(" {"); //$NON-NLS-1$
//{ObjectTeams: precedence declarations:
	if (this.precedences != null) {
		for (int i = 0; i < this.precedences.length; i++) {
			if (this.precedences[i] != null) {
				output.append('\n');
				this.precedences[i].print(indent + 1, output);
			}
		}
	}
// SH}
	if (this.memberTypes != null) {
		for (int i = 0; i < this.memberTypes.length; i++) {
			if (this.memberTypes[i] != null) {
				output.append('\n');
				this.memberTypes[i].print(indent + 1, output);
			}
		}
	}
	if (this.fields != null) {
		for (int fieldI = 0; fieldI < this.fields.length; fieldI++) {
			if (this.fields[fieldI] != null) {
				output.append('\n');
				this.fields[fieldI].print(indent + 1, output);
			}
		}
	}
	if (this.methods != null) {
		for (int i = 0; i < this.methods.length; i++) {
			if (this.methods[i] != null) {
				output.append('\n');
				this.methods[i].print(indent + 1, output);
			}
		}
	}
//{ObjectTeams: print method mappings:
	 if (this.callinCallouts != null) {
		 for (int i = 0; i < this.callinCallouts.length; i++) {
			 if (this.callinCallouts[i] != null) {
				 output.append("\n"); //$NON-NLS-1$
				 this.callinCallouts[i].print(indent + 1,output);
			 }
		 }
	 }
//Markus Witte}
	output.append('\n');
	return printIndent(indent, output).append('}');
}

public StringBuffer printHeader(int indent, StringBuffer output) {
//{ObjectTeams: workaround conflict wrt AccDefaultMethod vs. AccTeam:
/* orig:
	printModifiers(this.modifiers, output);
  :giro */
	printModifiers(this.modifiers & ExtraCompilerModifiers.AccJustFlag, output);
// SH}
	if (this.annotations != null) {
		printAnnotations(this.annotations, output);
		output.append(' ');
	}
//{ObjectTeams: role/team:
	printTypeKind(this.modifiers, output);
// SH}

	switch (kind(this.modifiers)) {
		case TypeDeclaration.CLASS_DECL :
			output.append("class "); //$NON-NLS-1$
			break;
		case TypeDeclaration.INTERFACE_DECL :
			output.append("interface "); //$NON-NLS-1$
			break;
		case TypeDeclaration.ENUM_DECL :
			output.append("enum "); //$NON-NLS-1$
			break;
		case TypeDeclaration.ANNOTATION_TYPE_DECL :
			output.append("@interface "); //$NON-NLS-1$
			break;
		case TypeDeclaration.RECORD_DECL :
			output.append("record "); //$NON-NLS-1$
			break;
	}
	output.append(this.name);
	if (this.isRecord()) {
		output.append('(');
		if (this.nRecordComponents > 0 && this.fields != null) {
			for (int i = 0; i < this.nRecordComponents; i++) {
				if (i > 0) output.append(", "); //$NON-NLS-1$
				output.append(this.fields[i].type.getTypeName()[0]);
				output.append(' ');
				output.append(this.fields[i].name);
			}
		}
		output.append(')');
	}
	if (this.typeParameters != null) {
		output.append("<");//$NON-NLS-1$
		for (int i = 0; i < this.typeParameters.length; i++) {
			if (i > 0) output.append( ", "); //$NON-NLS-1$
			this.typeParameters[i].print(0, output);
		}
		output.append(">");//$NON-NLS-1$
	}

	if (!this.isRecord() && this.superclass != null) {
		output.append(" extends ");  //$NON-NLS-1$
		this.superclass.print(0, output);
	}
	if (this.superInterfaces != null && this.superInterfaces.length > 0) {
		switch (kind(this.modifiers)) {
			case TypeDeclaration.CLASS_DECL :
			case TypeDeclaration.ENUM_DECL :
			case TypeDeclaration.RECORD_DECL :
				output.append(" implements "); //$NON-NLS-1$
				break;
			case TypeDeclaration.INTERFACE_DECL :
			case TypeDeclaration.ANNOTATION_TYPE_DECL :
				output.append(" extends "); //$NON-NLS-1$
				break;
		}
		for (int i = 0; i < this.superInterfaces.length; i++) {
			if (i > 0) output.append( ", "); //$NON-NLS-1$
			this.superInterfaces[i].print(0, output);
		}
	}
//{ObjectTeams: print playedBy
	if (this.baseclass != null)
	{
		  output.append(" playedBy "); //$NON-NLS-1$
		  this.baseclass.print(0,output);
	}
//}
	if (this.permittedTypes != null && this.permittedTypes.length > 0) {
		output.append(" permits "); //$NON-NLS-1$
		for (int i = 0; i < this.permittedTypes.length; i++) {
			if (i > 0) output.append( ", "); //$NON-NLS-1$
			this.permittedTypes[i].print(0, output);
		}
	}
	return output;
}

@Override
public StringBuffer printStatement(int tab, StringBuffer output) {
	return print(tab, output);
}

/*
 * Keep track of number of lambda/method reference expressions in this type declaration.
 * Return the 0 based "ordinal" in the TypeDeclaration.
 */
public int record(FunctionalExpression expression) {
	return this.functionalExpressionsCount++;
}

public void resolve() {
//{ObjectTeams:
	// signaling:
	StateHelper.startProcessing(this, ITranslationStates.STATE_RESOLVED, 0);
	// warnings in ROFI:
	if (isRoleFile() && isSourceRole())
		this.compilationUnit.reportNLSProblems();
// SH}
	SourceTypeBinding sourceType = this.binding;
	if (sourceType == null) {
		this.ignoreFurtherInvestigation = true;
		return;
	}
	try {
		if (CharOperation.equals(this.name, TypeConstants.VAR)) {
			if (this.scope.compilerOptions().sourceLevel < ClassFileConstants.JDK10) {
				this.scope.problemReporter().varIsReservedTypeNameInFuture(this);
			} else {
				this.scope.problemReporter().varIsReservedTypeName(this);
			}
		}
		this.scope.problemReporter().validateRestrictedKeywords(this.name, this);
		// resolve annotations and check @Deprecated annotation
		long annotationTagBits = sourceType.getAnnotationTagBits();
		if ((annotationTagBits & TagBits.AnnotationDeprecated) == 0
				&& (sourceType.modifiers & ClassFileConstants.AccDeprecated) != 0
				&& this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
			this.scope.problemReporter().missingDeprecatedAnnotationForType(this);
		}
		if ((annotationTagBits & TagBits.AnnotationFunctionalInterface) != 0) {
			if(!this.binding.isFunctionalInterface(this.scope)) {
				this.scope.problemReporter().notAFunctionalInterface(this);
			}
		}
//{ObjectTeams: check @Override annotation:
		boolean hasOverrideAnnotation = (this.binding.tagBits & TagBits.AnnotationOverride) != 0;
		if (isSourceRole()) {
			boolean hasTSuper =    (this.binding.modifiers & ExtraCompilerModifiers.AccOverriding) != 0
								|| this.roleModel.getTSuperRoleBindings().length > 0;
			if (hasOverrideAnnotation && !hasTSuper)
				this.scope.problemReporter().roleMustOverride(this);
			else if (hasTSuper && !hasOverrideAnnotation)
				this.scope.problemReporter().missingOverrideAnnotationForRole(this);
		} // @Override on non-role types is detected by Annotation.resolveType
// SH}

		if ((this.bits & ASTNode.UndocumentedEmptyBlock) != 0) {
			this.scope.problemReporter().undocumentedEmptyBlock(this.bodyStart-1, this.bodyEnd);
		}
		boolean needSerialVersion =
						this.scope.compilerOptions().getSeverity(CompilerOptions.MissingSerialVersion) != ProblemSeverities.Ignore
						&& sourceType.isClass()
						&& !sourceType.isRecord()
						&& sourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoExternalizable, false /*Externalizable is not a class*/) == null
						&& sourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaIoSerializable, false /*Serializable is not a class*/) != null;

		if (needSerialVersion) {
			// if Object writeReplace() throws java.io.ObjectStreamException is present, then no serialVersionUID is needed
			// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=101476
			CompilationUnitScope compilationUnitScope = this.scope.compilationUnitScope();
			MethodBinding methodBinding = sourceType.getExactMethod(TypeConstants.WRITEREPLACE, Binding.NO_TYPES, compilationUnitScope);
			ReferenceBinding[] throwsExceptions;
			needSerialVersion =
				methodBinding == null
					|| !methodBinding.isValidBinding()
					|| methodBinding.returnType.id != TypeIds.T_JavaLangObject
					|| (throwsExceptions = methodBinding.thrownExceptions).length != 1
					|| throwsExceptions[0].id != TypeIds.T_JavaIoObjectStreamException;
			if (needSerialVersion) {
				// check the presence of an implementation of the methods
				// private void writeObject(java.io.ObjectOutputStream out) throws IOException
				// private void readObject(java.io.ObjectInputStream out) throws IOException
				boolean hasWriteObjectMethod = false;
				boolean hasReadObjectMethod = false;
				TypeBinding argumentTypeBinding = this.scope.getType(TypeConstants.JAVA_IO_OBJECTOUTPUTSTREAM, 3);
				if (argumentTypeBinding.isValidBinding()) {
					methodBinding = sourceType.getExactMethod(TypeConstants.WRITEOBJECT, new TypeBinding[] { argumentTypeBinding }, compilationUnitScope);
					hasWriteObjectMethod = methodBinding != null
							&& methodBinding.isValidBinding()
							&& methodBinding.modifiers == ClassFileConstants.AccPrivate
							&& methodBinding.returnType == TypeBinding.VOID
							&& (throwsExceptions = methodBinding.thrownExceptions).length == 1
							&& throwsExceptions[0].id == TypeIds.T_JavaIoException;
				}
				argumentTypeBinding = this.scope.getType(TypeConstants.JAVA_IO_OBJECTINPUTSTREAM, 3);
				if (argumentTypeBinding.isValidBinding()) {
					methodBinding = sourceType.getExactMethod(TypeConstants.READOBJECT, new TypeBinding[] { argumentTypeBinding }, compilationUnitScope);
					hasReadObjectMethod = methodBinding != null
							&& methodBinding.isValidBinding()
							&& methodBinding.modifiers == ClassFileConstants.AccPrivate
							&& methodBinding.returnType == TypeBinding.VOID
							&& (throwsExceptions = methodBinding.thrownExceptions).length == 1
							&& throwsExceptions[0].id == TypeIds.T_JavaIoException;
				}
				needSerialVersion = !hasWriteObjectMethod || !hasReadObjectMethod;
			}
		}
		// generics (and non static generic members) cannot extend Throwable
		if (sourceType.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangThrowable, true) != null) {
			ReferenceBinding current = sourceType;
			checkEnclosedInGeneric : do {
				if (current.isGenericType()) {
					this.scope.problemReporter().genericTypeCannotExtendThrowable(this);
					break checkEnclosedInGeneric;
				}
				if (current.isStatic()) break checkEnclosedInGeneric;
				if (current.isLocalType()) {
					NestedTypeBinding nestedType = (NestedTypeBinding) current.erasure();
					if (nestedType.scope.methodScope().isStatic) break checkEnclosedInGeneric;
				}
			} while ((current = current.enclosingType()) != null);
		}
//{ObjectTeams: resolve precedence declarations
		if (this.precedences != null && this.precedences.length > 0)
		{
			if (isTeam() || isRole()) {
				this.binding.precedences = new PrecedenceBinding[this.precedences.length];
				// process back to front because addResolvedPrecedenceDeclaration will always insert at front:
				for (int i = this.precedences.length-1; i>=0; i--)
					this.binding.precedences[i] = this.precedences[i].resolve(this);
			} else {
				this.scope.problemReporter().precedenceInRegularClass(this, this.precedences);
			}
		}
// SH}
		// this.maxFieldCount might already be set
		int localMaxFieldCount = 0;
		int lastVisibleFieldID = -1;
		boolean hasEnumConstants = false;
		FieldDeclaration[] enumConstantsWithoutBody = null;

//{ObjectTeams: don't cache count, array may grow during this loop!
		int resolvedMemberCount = 0; // but remember for later :)
// orig:
		if (this.memberTypes != null) {
/*
			for (int i = 0, count = this.memberTypes.length; i < count; i++) {
  :giro */
			resolvedMemberCount = this.memberTypes.length;
			for (int i = 0; i < this.memberTypes.length; i++) {
// SH}
				this.memberTypes[i].resolve(this.scope);
			}
		}
//{ObjectTeams:	should we work at all?
	    Config config = Config.getConfig();
	    boolean fieldsAndMethods = config != null && config.verifyMethods;
	    boolean hasFinalFieldInit = false;
	  if (fieldsAndMethods) {
// SH}
		if (this.recordComponents != null) {
			for (RecordComponent rc : this.recordComponents) {
				rc.resolve(this.initializerScope);
			}
		}
		if (this.fields != null) {
			for (int i = 0, count = this.fields.length; i < count; i++) {
				FieldDeclaration field = this.fields[i];
				switch(field.getKind()) {
					case AbstractVariableDeclaration.ENUM_CONSTANT:
						hasEnumConstants = true;
						if (!(field.initialization instanceof QualifiedAllocationExpression)) {
							if (enumConstantsWithoutBody == null)
								enumConstantsWithoutBody = new FieldDeclaration[count];
							enumConstantsWithoutBody[i] = field;
						}
						//$FALL-THROUGH$
					case AbstractVariableDeclaration.FIELD:
						FieldBinding fieldBinding = field.binding;
						if (fieldBinding == null) {
							// still discover secondary errors
							if (field.initialization != null) field.initialization.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
							this.ignoreFurtherInvestigation = true;
							continue;
						}
						if (needSerialVersion
								&& ((fieldBinding.modifiers & (ClassFileConstants.AccStatic | ClassFileConstants.AccFinal)) == (ClassFileConstants.AccStatic | ClassFileConstants.AccFinal))
								&& CharOperation.equals(TypeConstants.SERIALVERSIONUID, fieldBinding.name)
								&& TypeBinding.equalsEquals(TypeBinding.LONG, fieldBinding.type)) {
							needSerialVersion = false;
						}
						localMaxFieldCount++;
						lastVisibleFieldID = field.binding.id;
//{ObjectTeams: has init?
						if (field.initialization != null && field.isFinal())
							hasFinalFieldInit = true;
// SH}
						break;

					case AbstractVariableDeclaration.INITIALIZER:
						 ((Initializer) field).lastVisibleFieldID = lastVisibleFieldID + 1;
						break;
				}
				field.resolve(field.isStatic() ? this.staticInitializerScope : this.initializerScope);
			}
		}
//{ObjectTeams: also count type value parameters into maxFieldCount
		if (this.typeParameters != null)
			TypeValueParameter.updateMaxFieldCount(this);
		if (hasFinalFieldInit && isRole())
	        WordValueAttribute.addClassFlags(getRoleModel(), IOTConstants.OT_CLASS_HAS_FINAL_FIELD_INITS);
	  }
// SH}
		if (this.maxFieldCount < localMaxFieldCount) {
			this.maxFieldCount = localMaxFieldCount;
		}
		if (needSerialVersion) {
			//check that the current type doesn't extend javax.rmi.CORBA.Stub
			TypeBinding javaxRmiCorbaStub = this.scope.getType(TypeConstants.JAVAX_RMI_CORBA_STUB, 4);
			if (javaxRmiCorbaStub.isValidBinding()) {
				ReferenceBinding superclassBinding = this.binding.superclass;
				loop: while (superclassBinding != null) {
					if (TypeBinding.equalsEquals(superclassBinding, javaxRmiCorbaStub)) {
						needSerialVersion = false;
						break loop;
					}
					superclassBinding = superclassBinding.superclass();
				}
			}
			if (needSerialVersion) {
				this.scope.problemReporter().missingSerialVersion(this);
			}
		}

		// check extends/implements for annotation type
		switch(kind(this.modifiers)) {
			case TypeDeclaration.ANNOTATION_TYPE_DECL :
				if (this.superclass != null) {
					this.scope.problemReporter().annotationTypeDeclarationCannotHaveSuperclass(this);
				}
				if (this.superInterfaces != null) {
					this.scope.problemReporter().annotationTypeDeclarationCannotHaveSuperinterfaces(this);
				}
				break;
			case TypeDeclaration.ENUM_DECL :
				// check enum abstract methods
				if (this.binding.isAbstract()) {
					if (!hasEnumConstants) {
						for (int i = 0, count = this.methods.length; i < count; i++) {
							final AbstractMethodDeclaration methodDeclaration = this.methods[i];
							if (methodDeclaration.isAbstract() && methodDeclaration.binding != null)
								this.scope.problemReporter().enumAbstractMethodMustBeImplemented(methodDeclaration);
						}
					} else if (enumConstantsWithoutBody != null) {
						for (int i = 0, count = this.methods.length; i < count; i++) {
							final AbstractMethodDeclaration methodDeclaration = this.methods[i];
							if (methodDeclaration.isAbstract() && methodDeclaration.binding != null) {
								for (int f = 0, l = enumConstantsWithoutBody.length; f < l; f++)
									if (enumConstantsWithoutBody[f] != null)
										this.scope.problemReporter().enumConstantMustImplementAbstractMethod(methodDeclaration, enumConstantsWithoutBody[f]);
							}
						}
					}
				}
				break;
		}

		int missingAbstractMethodslength = this.missingAbstractMethods == null ? 0 : this.missingAbstractMethods.length;
		int methodsLength = this.methods == null ? 0 : this.methods.length;
		if ((methodsLength + missingAbstractMethodslength) > 0xFFFF) {
			this.scope.problemReporter().tooManyMethods(this);
		}
//{ObjectTeams: flag that from now on all added methods need to be resolved:
		// TODO(SH): this should cooperate with the incremental image builder,
		//           such as to cause one more loop of compilation, hopefully
		//           containing all required sources that time...
		if (StateMemento.hasMethodResolveStarted(this.binding)) {
			// FIXME(SH): introduced in r10641 this abort does not cooperate well with lateRolesCatchUp()
			//            haven't seen it in ages, can it be removed??
			this.scope.problemReporter().abortDueToInternalError("circular compilation dependency"); //$NON-NLS-1$
			return;
		}
        StateMemento.methodResolveStart(this.binding);
        // any role types found during field resolve? If so, catch up now:
    	if (this.memberTypes != null && this.memberTypes.length > resolvedMemberCount
    			&& this.teamModel != null)
    	{
    		Dependencies.lateRolesCatchup(this.teamModel);
    	}
// SH}
//{ObjectTeams: should we work?
      if (fieldsAndMethods) {
// SH}
		if (this.methods != null) {
			for (int i = 0, count = this.methods.length; i < count; i++) {
				this.methods[i].resolve(this.scope);
			}
		}
//{ObjectTeams:
      }
// SH}
		// Resolve javadoc
		if (this.javadoc != null) {
			if (this.scope != null && (this.name != TypeConstants.PACKAGE_INFO_NAME)) {
				// if the type is package-info, the javadoc was resolved as part of the compilation unit javadoc
				this.javadoc.resolve(this.scope);
			}
		} else if (!sourceType.isLocalType()) {
			// Set javadoc visibility
			int visibility = sourceType.modifiers & ExtraCompilerModifiers.AccVisibilityMASK;
			ProblemReporter reporter = this.scope.problemReporter();
			int severity = reporter.computeSeverity(IProblem.JavadocMissing);
//{ObjectTeams: not for generated or copied types
			if (this.isGenerated || this.isPurelyCopied)
				severity = ProblemSeverities.Ignore;
// SH}
			if (severity != ProblemSeverities.Ignore) {
				if (this.enclosingType != null) {
					visibility = Util.computeOuterMostVisibility(this.enclosingType, visibility);
				}
				int javadocModifiers = (this.binding.modifiers & ~ExtraCompilerModifiers.AccVisibilityMASK) | visibility;
				reporter.javadocMissing(this.sourceStart, this.sourceEnd, severity, javadocModifiers);
			}
		}
		updateNestInfo();
		FieldDeclaration[] fieldsDecls = this.fields;
		if (fieldsDecls != null) {
			for (FieldDeclaration fieldDeclaration : fieldsDecls)
				fieldDeclaration.resolveJavadoc(this.initializerScope);
		}
		AbstractMethodDeclaration[] methodDecls = this.methods;
		if (methodDecls != null) {
			for (AbstractMethodDeclaration methodDeclaration : methodDecls)
				methodDeclaration.resolveJavadoc();
		}
	} catch (AbortType e) {
		this.ignoreFurtherInvestigation = true;
		return;
	}
}

/**
 * Resolve a local type declaration
 */
@Override
public void resolve(BlockScope blockScope) {

	// need to build its scope first and proceed with binding's creation
	if ((this.bits & ASTNode.IsAnonymousType) == 0) {
		// check collision scenarii
		Binding existing = blockScope.getType(this.name);
		if (existing instanceof ReferenceBinding
				&& existing != this.binding
				&& existing.isValidBinding()) {
			ReferenceBinding existingType = (ReferenceBinding) existing;
			if (existingType instanceof TypeVariableBinding) {
				blockScope.problemReporter().typeHiding(this, (TypeVariableBinding) existingType);
				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=312989, check for collision with enclosing type.
				Scope outerScope = blockScope.parent;
checkOuterScope:while (outerScope != null) {
					Binding existing2 = outerScope.getType(this.name);
					if (existing2 instanceof TypeVariableBinding && existing2.isValidBinding()) {
						TypeVariableBinding tvb = (TypeVariableBinding) existingType;
						Binding declaringElement = tvb.declaringElement;
						if (declaringElement instanceof ReferenceBinding
								&& CharOperation.equals(((ReferenceBinding) declaringElement).sourceName(), this.name)) {
							blockScope.problemReporter().typeCollidesWithEnclosingType(this);
							break checkOuterScope;
						}
					} else if (existing2 instanceof ReferenceBinding
							&& existing2.isValidBinding()
							&& outerScope.isDefinedInType((ReferenceBinding) existing2)) {
							blockScope.problemReporter().typeCollidesWithEnclosingType(this);
							break checkOuterScope;
					} else if (existing2 == null) {
						break checkOuterScope;
					}
					outerScope = outerScope.parent;
				}
			} else if (existingType instanceof LocalTypeBinding
						&& ((LocalTypeBinding) existingType).scope.methodScope() == blockScope.methodScope()) {
					// dup in same method
					blockScope.problemReporter().duplicateNestedType(this);
			} else if (existingType instanceof LocalTypeBinding && blockScope.isLambdaSubscope()
					&& blockScope.enclosingLambdaScope().enclosingMethodScope() == ((LocalTypeBinding) existingType).scope.methodScope()) {
				blockScope.problemReporter().duplicateNestedType(this);
			} else if (blockScope.isDefinedInType(existingType)) {
				//	collision with enclosing type
				blockScope.problemReporter().typeCollidesWithEnclosingType(this);
			} else if (blockScope.isDefinedInSameUnit(existingType)){ // only consider hiding inside same unit
				// hiding sibling
				blockScope.problemReporter().typeHiding(this, existingType);
			}
		}
		blockScope.addLocalType(this);
	}

	if (this.binding != null) {
		// remember local types binding for innerclass emulation propagation
		blockScope.referenceCompilationUnit().record((LocalTypeBinding)this.binding);

//{ObjectTeams: trigger intermediate steps:
		Dependencies.ensureBindingState(this.binding, ITranslationStates.STATE_RESOLVED-1);
// SH}
		// binding is not set if the receiver could not be created
		resolve();
		updateMaxFieldCount();
	}
}

/**
 * Resolve a member type declaration (can be a local member)
 */
public void resolve(ClassScope upperScope) {
//{ObjectTeams: role files may be resolved already
	if (isRoleFile())
		if (this.roleModel.getState() >= ITranslationStates.STATE_RESOLVED)
			return;
// SH}
	// member scopes are already created
	// request the construction of a binding if local member type

	if (this.binding != null && this.binding instanceof LocalTypeBinding) {
		// remember local types binding for innerclass emulation propagation
		upperScope.referenceCompilationUnit().record((LocalTypeBinding)this.binding);
	}
	resolve();
	updateMaxFieldCount();
}

/**
 * Resolve a top level type declaration
 */
public void resolve(CompilationUnitScope upperScope) {
	// top level : scope are already created
	resolve();
	updateMaxFieldCount();
}

@Override
public void tagAsHavingErrors() {
//{ObjectTeams: tag class and interface part:
  if (isRole() && this.roleModel != null)
	this.roleModel.setErrorFlag(true); // both parts
  else
// SH}
	this.ignoreFurtherInvestigation = true;
}

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

//{ObjectTeams: untag class and interface part:
@Override
public void resetErrorFlag() {
	if (isRole() && this.roleModel != null)
		this.roleModel.setErrorFlag(false); // both parts
	else
		this.ignoreFurtherInvestigation = false;
}
// SH}

//{ObjectTeams: push precedence declaration out to the team:
public void addResolvedPrecedence(char[] roleName, PrecedenceBinding precBinding)
{
	if (this.enclosingType != null) {
		this.enclosingType.addResolvedPrecedence(this.name, precBinding);
		return;
	}
	if (this.binding.precedences == PrecedenceBinding.NoPrecedences) {
		this.binding.precedences = new PrecedenceBinding[] { precBinding };
	} else {
		// insert at front to account for ordering according to 4.8(d):
		// - inner before outer
		// - textual order (same nesting level)
		int len = this.binding.precedences.length;
		System.arraycopy(
				this.binding.precedences, 0,
				this.binding.precedences = new PrecedenceBinding[len+1], 1,
				len);
		this.binding.precedences[0] = precBinding;
	}
}
// SH}
/**
 *	Iteration for a package member type
 *
 */
public void traverse(ASTVisitor visitor, CompilationUnitScope unitScope) {
	try {
		if (visitor.visit(this, unitScope)) {
			if (this.javadoc != null) {
				this.javadoc.traverse(visitor, this.scope);
			}
			if (this.annotations != null) {
				int annotationsLength = this.annotations.length;
				for (int i = 0; i < annotationsLength; i++)
					this.annotations[i].traverse(visitor, this.staticInitializerScope);
			}
			if (this.superclass != null)
				this.superclass.traverse(visitor, this.scope);
//{ObjectTeams
			if (this.baseclass != null)
				 this.baseclass.traverse(visitor, this.scope);
// Markus Witte}
			if (this.superInterfaces != null) {
				int length = this.superInterfaces.length;
				for (int i = 0; i < length; i++)
					this.superInterfaces[i].traverse(visitor, this.scope);
			}
			if (this.permittedTypes != null) {
				int length = this.permittedTypes.length;
				for (int i = 0; i < length; i++)
					this.permittedTypes[i].traverse(visitor, this.scope);
			}
			if (this.typeParameters != null) {
				int length = this.typeParameters.length;
				for (int i = 0; i < length; i++) {
					this.typeParameters[i].traverse(visitor, this.scope);
				}
			}
			if (this.recordComponents != null) {
				int length = this.recordComponents.length;
				for (int i = 0; i < length; i++)
					this.recordComponents[i].traverse(visitor, this.initializerScope);
			}
			if (this.memberTypes != null) {
				int length = this.memberTypes.length;
				for (int i = 0; i < length; i++)
					this.memberTypes[i].traverse(visitor, this.scope);
			}
			if (this.fields != null) {
				int length = this.fields.length;
				for (int i = 0; i < length; i++) {
					FieldDeclaration field;
					if ((field = this.fields[i]).isStatic()) {
						field.traverse(visitor, this.staticInitializerScope);
					} else {
						field.traverse(visitor, this.initializerScope);
					}
				}
			}
			if (this.methods != null) {
				int length = this.methods.length;
				for (int i = 0; i < length; i++)
					this.methods[i].traverse(visitor, this.scope);
			}
//{ObjectTeams
			if(this.callinCallouts != null) {
				int methodBindingsLength = this.callinCallouts.length;
				for(int idx = 0; idx < methodBindingsLength; idx++)
					this.callinCallouts[idx].traverse(visitor,  this.scope);
			}
// Joachim Haensel}
		}
		visitor.endVisit(this, unitScope);
	} catch (AbortType e) {
		// silent abort
	}
}

/**
 *	Iteration for a local inner type
 */
@Override
public void traverse(ASTVisitor visitor, BlockScope blockScope) {
	try {
		if (visitor.visit(this, blockScope)) {
			if (this.javadoc != null) {
				this.javadoc.traverse(visitor, this.scope);
			}
			if (this.annotations != null) {
				int annotationsLength = this.annotations.length;
				for (int i = 0; i < annotationsLength; i++)
					this.annotations[i].traverse(visitor, this.staticInitializerScope);
			}
			if (this.superclass != null)
				this.superclass.traverse(visitor, this.scope);
			if (this.superInterfaces != null) {
				int length = this.superInterfaces.length;
				for (int i = 0; i < length; i++)
					this.superInterfaces[i].traverse(visitor, this.scope);
			}
			if (this.permittedTypes != null) {
				int length = this.permittedTypes.length;
				for (int i = 0; i < length; i++)
					this.permittedTypes[i].traverse(visitor, this.scope);
			}
			if (this.typeParameters != null) {
				int length = this.typeParameters.length;
				for (int i = 0; i < length; i++) {
					this.typeParameters[i].traverse(visitor, this.scope);
				}
			}
			if (this.recordComponents != null) {
				int length = this.recordComponents.length;
				for (int i = 0; i < length; i++)
					this.recordComponents[i].traverse(visitor, this.initializerScope);
			}
			if (this.memberTypes != null) {
				int length = this.memberTypes.length;
				for (int i = 0; i < length; i++)
					this.memberTypes[i].traverse(visitor, this.scope);
			}
			if (this.fields != null) {
				int length = this.fields.length;
				for (int i = 0; i < length; i++) {
					FieldDeclaration field = this.fields[i];
					if (field.isStatic() && !field.isFinal()) {
						// local type cannot have static fields that are not final, https://bugs.eclipse.org/bugs/show_bug.cgi?id=244544
					} else {
						field.traverse(visitor, this.initializerScope);
					}
				}
			}
			if (this.methods != null) {
				int length = this.methods.length;
				for (int i = 0; i < length; i++)
					this.methods[i].traverse(visitor, this.scope);
			}
			// Note(SH): local innertypes can't have callinCallouts
		}
		visitor.endVisit(this, blockScope);
	} catch (AbortType e) {
		// silent abort
	}
}

/**
 *	Iteration for a member innertype
 *
 */
public void traverse(ASTVisitor visitor, ClassScope classScope) {
	try {
		if (visitor.visit(this, classScope)) {
			if (this.javadoc != null) {
				this.javadoc.traverse(visitor, this.scope);
			}
			if (this.annotations != null) {
				int annotationsLength = this.annotations.length;
				for (int i = 0; i < annotationsLength; i++)
					this.annotations[i].traverse(visitor, this.staticInitializerScope);
			}
			if (this.superclass != null)
				this.superclass.traverse(visitor, this.scope);
			if (this.superInterfaces != null) {
				int length = this.superInterfaces.length;
				for (int i = 0; i < length; i++)
					this.superInterfaces[i].traverse(visitor, this.scope);
			}
			if (this.permittedTypes != null) {
				int length = this.permittedTypes.length;
				for (int i = 0; i < length; i++)
					this.permittedTypes[i].traverse(visitor, this.scope);
			}
			if (this.typeParameters != null) {
				int length = this.typeParameters.length;
				for (int i = 0; i < length; i++) {
					this.typeParameters[i].traverse(visitor, this.scope);
				}
			}
			if (this.recordComponents != null) {
				int length = this.recordComponents.length;
				for (int i = 0; i < length; i++)
					this.recordComponents[i].traverse(visitor, this.initializerScope);
			}
			if (this.memberTypes != null) {
				int length = this.memberTypes.length;
				for (int i = 0; i < length; i++)
					this.memberTypes[i].traverse(visitor, this.scope);
			}
			if (this.fields != null) {
				int length = this.fields.length;
				for (int i = 0; i < length; i++) {
					FieldDeclaration field;
					if ((field = this.fields[i]).isStatic()) {
						field.traverse(visitor, this.staticInitializerScope);
					} else {
						field.traverse(visitor, this.initializerScope);
					}
				}
			}
			if (this.methods != null) {
				int length = this.methods.length;
				for (int i = 0; i < length; i++)
					this.methods[i].traverse(visitor, this.scope);
			}
//{ObjectTeams:	method mappings:
			if (this.callinCallouts != null) {
				int callinCalloutsLength = this.callinCallouts.length;
				for (int i = 0; i < callinCalloutsLength; i++)
					this.callinCallouts[i].traverse(visitor, this.scope);
			}
// SH}
		}
		visitor.endVisit(this, classScope);
	} catch (AbortType e) {
		// silent abort
	}
}

/**
 * MaxFieldCount's computation is necessary so as to reserve space for
 * the flow info field portions. It corresponds to the maximum amount of
 * fields this class or one of its innertypes have.
 *
 * During name resolution, types are traversed, and the max field count is recorded
 * on the outermost type. It is then propagated down during the flow analysis.
 *
 * This method is doing either up/down propagation.
 */
void updateMaxFieldCount() {
	if (this.binding == null)
		return; // error scenario
	TypeDeclaration outerMostType = this.scope.outerMostClassScope().referenceType();
	if (this.maxFieldCount > outerMostType.maxFieldCount) {
		outerMostType.maxFieldCount = this.maxFieldCount; // up
	} else {
		this.maxFieldCount = outerMostType.maxFieldCount; // down
	}
}

private SourceTypeBinding findNestHost() {
	ClassScope classScope = this.scope.enclosingTopMostClassScope();
	return classScope != null ? classScope.referenceContext.binding : null;
}

void updateNestInfo() {
	if (this.binding == null)
		return;
	SourceTypeBinding nestHost = findNestHost();
	if (nestHost != null && !this.binding.equals(nestHost)) {// member
		this.binding.setNestHost(nestHost);
		nestHost.addNestMember(this.binding);
	}
}
public boolean isPackageInfo() {
	return CharOperation.equals(this.name,  TypeConstants.PACKAGE_INFO_NAME);
}
/**
 * Returns whether the type is a secondary one or not.
 */
public boolean isSecondary() {
	return (this.bits & ASTNode.IsSecondaryType) != 0;
}

//{ObjectTeams
/**
 * If a role has an invalid playedBy binding, do not stop to process
 * the role class, just skip all its method bindings.
 */
public void pushDownBindingProblem() {
    this.ignoreFurtherInvestigation = false;
    if (this.callinCallouts != null)
        for (int i=0;i<this.callinCallouts.length;i++)
            this.callinCallouts[i].ignoreFurtherInvestigation = true;
    // these bindings are not useful, simply delete them:
    this.binding.callinCallouts = Binding.NO_CALLIN_CALLOUT_BINDINGS;
}
/**
 * Remove unwanted elements created during dietParse: fields, methods, methodMappings
 */
public void removeDetails() {
	this.fields = null;
	this.methods = null;
	this.callinCallouts = null;
	if (this.memberTypes != null)
		for (int i = 0; i < this.memberTypes.length; i++)
			this.memberTypes[i].removeDetails();
}
public void cleanupModels() {
	if (this.roleModel != null) {
		this.roleModel.cleanup();
		this.roleModel.setState(ITranslationStates.STATE_FINAL);
	}
	if (this.teamModel != null) {
		this.teamModel.cleanup();
		this.teamModel.setState(ITranslationStates.STATE_FINAL);
	}
	if (this.model != null) {
		this.model.cleanup();
		this.model.setState(ITranslationStates.STATE_FINAL);
	}
	// TODO (SH): when do we know, we can free the byte code?
	// need to find out, when all tsub-roles are done (which is impossible)!
	// don't: model.forgetByteCode();
}
// SH}
}
