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

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;

import org.eclipse.wst.jsdt.core.JavaScriptCore;
import org.eclipse.wst.jsdt.core.UnimplementedException;
import org.eclipse.wst.jsdt.core.compiler.CharOperation;
import org.eclipse.wst.jsdt.core.infer.InferredAttribute;
import org.eclipse.wst.jsdt.core.infer.InferredMethod;
import org.eclipse.wst.jsdt.core.infer.InferredType;
import org.eclipse.wst.jsdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.wst.jsdt.internal.compiler.ast.Argument;
import org.eclipse.wst.jsdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.wst.jsdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.wst.jsdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.wst.jsdt.internal.compiler.ast.TypeParameter;
import org.eclipse.wst.jsdt.internal.compiler.ast.TypeReference;
import org.eclipse.wst.jsdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.wst.jsdt.internal.compiler.impl.Constant;
import org.eclipse.wst.jsdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.wst.jsdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.wst.jsdt.internal.compiler.util.Util;

public class SourceTypeBinding extends ReferenceBinding {
	public ReferenceBinding superclass;
	public ReferenceBinding[] superInterfaces= Binding.NO_SUPERINTERFACES;
	protected FieldBinding[] fields;
	protected MethodBinding[] methods;
	public ReferenceBinding[] memberTypes=Binding.NO_MEMBER_TYPES;
    public TypeVariableBinding[] typeVariables=Binding.NO_TYPE_VARIABLES;

	public Scope scope;
	public ClassScope  classScope;


	// Synthetics are separated into 5 categories: methods, super methods, fields, class literals, changed declaring type bindings and bridge methods
	public final static int METHOD_EMUL = 0;
	public final static int FIELD_EMUL = 1;
	public final static int CLASS_LITERAL_EMUL = 2;
	public final static int RECEIVER_TYPE_EMUL = 3;
	HashMap[] synthetics;
	char[] genericReferenceTypeSignature;
	
	public SourceTypeBinding nextType;

	private SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder

public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage,  Scope scope) {
	this.compoundName = compoundName;
	this.fPackage = fPackage;
	this.fileName = scope.referenceCompilationUnit().getFileName();
	if (scope instanceof ClassScope)
	{
		this.classScope=(ClassScope)scope;
		if (this.classScope.referenceContext!=null) {
			this.modifiers = this.classScope.referenceContext.modifiers;
			this.sourceName = this.classScope.referenceContext.name;
		}
		else
		{
			this.sourceName = this.classScope.inferredType.getName();

			this.modifiers=ClassFileConstants.AccPublic;
		}
	}
	this.scope = scope;

	// expect the fields & methods to be initialized correctly later
	this.fields = Binding.NO_FIELDS;
	this.methods = Binding.NO_METHODS;

	computeId();

}

protected SourceTypeBinding()
{
	
}

void buildFieldsAndMethods() {
	buildFields();
	buildMethods();

}

public InferredType getInferredType() {
	if (this.nextType!=null)
		throw new UnimplementedException("should not get here"); //$NON-NLS-1$
	ClassScope classScope = scope.classScope();
	return classScope.inferredType;
}

private void buildFields() {
	FieldBinding prototype = new FieldBinding(TypeConstants.PROTOTYPE, TypeBinding.UNKNOWN, modifiers | ExtraCompilerModifiers.AccUnresolved, this,null);
	InferredType inferredType=this.classScope.inferredType;
	int size = inferredType.numberAttributes;
	if (size == 0) {
		 setFields(new FieldBinding[]{prototype});
		return;
	}

	// iterate the field declarations to create the bindings, lose all duplicates
	FieldBinding[] fieldBindings = new FieldBinding[size+1];
	HashtableOfObject knownFieldNames = new HashtableOfObject(size);
	boolean duplicate = false;
	int count = 0;
	for (int i = 0; i < size; i++) {
		InferredAttribute field = inferredType.attributes[i];
		int modifiers=0;
		if (field.isStatic)
			modifiers|=ClassFileConstants.AccStatic;
			InferredType fieldType = field.type;
			TypeBinding fieldTypeBinding=null;
			if(fieldType!=null) {
				//fieldTypeBinding = BaseTypeBinding.UNKNOWN;
//				fieldTypeBinding = scope.getType(fieldType.getName());
				fieldTypeBinding = fieldType.resolveType(scope, field.node);
			}
			if (fieldTypeBinding==null)
				fieldTypeBinding = TypeBinding.UNKNOWN;
			
			FieldBinding fieldBinding = new FieldBinding(field, fieldTypeBinding, modifiers | ExtraCompilerModifiers.AccUnresolved, this);
			fieldBinding.id = count;
			// field's type will be resolved when needed for top level types
//			checkAndSetModifiersForField(fieldBinding, field);

			if (knownFieldNames.containsKey(field.name)) {
				duplicate = true;
				FieldBinding previousBinding = (FieldBinding) knownFieldNames.get(field.name);
				if (previousBinding != null) {
					for (int f = 0; f < i; f++) {
						InferredAttribute previousField = inferredType.attributes[f];
						if (previousField.binding == previousBinding) {
							scope.problemReporter().duplicateFieldInType(this, previousField);
							previousField.binding = null;
							break;
						}
					}
				}
				knownFieldNames.put(field.name, null); // ensure that the duplicate field is found & removed
				scope.problemReporter().duplicateFieldInType(this, field);
				field.binding = null;
			} else {
				knownFieldNames.put(field.name, fieldBinding);
				// remember that we have seen a field with this name
				if (fieldBinding != null)
					fieldBindings[count++] = fieldBinding;
			}
	}
	fieldBindings[count++]=prototype;
	// remove duplicate fields
	if (duplicate) {
		FieldBinding[] newFieldBindings = new FieldBinding[fieldBindings.length];
		// we know we'll be removing at least 1 duplicate name
		size = count;
		count = 0;
		for (int i = 0; i < size; i++) {
			FieldBinding fieldBinding = fieldBindings[i];
			if (knownFieldNames.get(fieldBinding.name) != null) {
				fieldBinding.id = count;
				newFieldBindings[count++] = fieldBinding;
			}
		}
		fieldBindings = newFieldBindings;
	}
	if (count != fieldBindings.length)
		System.arraycopy(fieldBindings, 0, fieldBindings = new FieldBinding[count], 0, count);
	setFields(fieldBindings);
}


private void buildMethods() {
	InferredType inferredType=this.classScope.inferredType;
	int size = (inferredType.methods!=null)?inferredType.methods.size() :0;

	if (size==0 ) {
		setMethods(Binding.NO_METHODS);
		return;
	}

	int count =  0;
	MethodBinding[] methodBindings = new MethodBinding[size];
	// create bindings for source methods
	for (int i = 0; i < size; i++) {
		 InferredMethod method = (InferredMethod)inferredType.methods.get(i);
			MethodScope scope = new MethodScope(this.scope, (MethodDeclaration)method.getFunctionDeclaration(), false);
			MethodBinding methodBinding = scope.createMethod(method,this);
			method.methodBinding=methodBinding;
			if (methodBinding != null) // is null if binding could not be created
				methodBindings[count++] = methodBinding;
	}
	if (count != methodBindings.length)
		System.arraycopy(methodBindings, 0, methodBindings = new MethodBinding[count], 0, count);
	tagBits &= ~TagBits.AreMethodsSorted; // in case some static imports reached already into this type
	setMethods(methodBindings);
}



//private void addDefaultAbstractMethods() {
//	if ((this.tagBits & TagBits.KnowsDefaultAbstractMethods) != 0) return;
//
//	this.tagBits |= TagBits.KnowsDefaultAbstractMethods;
//	if (isClass() && isAbstract()) {
//		if (this.scope.compilerOptions().targetJDK >= ClassFileConstants.JDK1_2)
//			return; // no longer added for post 1.2 targets
//
//		ReferenceBinding[] itsInterfaces = superInterfaces();
//		if (itsInterfaces != Binding.NO_SUPERINTERFACES) {
//			FunctionBinding[] defaultAbstracts = null;
//			int defaultAbstractsCount = 0;
//			ReferenceBinding[] interfacesToVisit = itsInterfaces;
//			int nextPosition = interfacesToVisit.length;
//			for (int i = 0; i < nextPosition; i++) {
//				ReferenceBinding superType = interfacesToVisit[i];
//				if (superType.isValidBinding()) {
//					FunctionBinding[] superMethods = superType.methods();
//					nextAbstractMethod: for (int m = superMethods.length; --m >= 0;) {
//						FunctionBinding method = superMethods[m];
//						// explicitly implemented ?
//						if (implementsMethod(method))
//							continue nextAbstractMethod;
//						if (defaultAbstractsCount == 0) {
//							defaultAbstracts = new FunctionBinding[5];
//						} else {
//							// already added as default abstract ?
//							for (int k = 0; k < defaultAbstractsCount; k++) {
//								FunctionBinding alreadyAdded = defaultAbstracts[k];
//								if (CharOperation.equals(alreadyAdded.selector, method.selector) && alreadyAdded.areParametersEqual(method))
//									continue nextAbstractMethod;
//							}
//						}
//						FunctionBinding defaultAbstract = new FunctionBinding(
//								method.modifiers | ExtraCompilerModifiers.AccDefaultAbstract,
//								method.selector,
//								method.returnType,
//								method.parameters,
//								method.thrownExceptions,
//								this);
//						if (defaultAbstractsCount == defaultAbstracts.length)
//							System.arraycopy(defaultAbstracts, 0, defaultAbstracts = new FunctionBinding[2 * defaultAbstractsCount], 0, defaultAbstractsCount);
//						defaultAbstracts[defaultAbstractsCount++] = defaultAbstract;
//					}
//
//					if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) {
//						int itsLength = itsInterfaces.length;
//						if (nextPosition + itsLength >= interfacesToVisit.length)
//							System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
//						nextInterface : for (int a = 0; a < itsLength; a++) {
//							ReferenceBinding next = itsInterfaces[a];
//							for (int b = 0; b < nextPosition; b++)
//								if (next == interfacesToVisit[b]) continue nextInterface;
//							interfacesToVisit[nextPosition++] = next;
//						}
//					}
//				}
//			}
//			if (defaultAbstractsCount > 0) {
//				int length = this.methods.length;
//				System.arraycopy(this.methods, 0, this.methods = new FunctionBinding[length + defaultAbstractsCount], 0, length);
//				System.arraycopy(defaultAbstracts, 0, this.methods, length, defaultAbstractsCount);
//				// re-sort methods
//				length = length + defaultAbstractsCount;
//				if (length > 1)
//					ReferenceBinding.sortMethods(this.methods, 0, length);
//				// this.tagBits |= TagBits.AreMethodsSorted; -- already set in #methods()
//			}
//		}
//	}
//}
/* Add a new synthetic field for <actualOuterLocalVariable>.
*	Answer the new field or the existing field if one already existed.
*/
public FieldBinding addSyntheticFieldForInnerclass(LocalVariableBinding actualOuterLocalVariable) {
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
		this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(5);

	FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(actualOuterLocalVariable);
	if (synthField == null) {
		synthField = new SyntheticFieldBinding(
			CharOperation.concat(TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX, actualOuterLocalVariable.name),
			actualOuterLocalVariable.type,
			ClassFileConstants.AccPrivate | ClassFileConstants.AccFinal | ClassFileConstants.AccSynthetic,
			this,
			Constant.NotAConstant,
			this.synthetics[SourceTypeBinding.FIELD_EMUL].size());
		this.synthetics[SourceTypeBinding.FIELD_EMUL].put(actualOuterLocalVariable, synthField);
	}

	// ensure there is not already such a field defined by the user
	boolean needRecheck;
	int index = 1;
	do {
		needRecheck = false;
		FieldBinding existingField;
		if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
			TypeDeclaration typeDecl = this.classScope.referenceContext;
			for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
				FieldDeclaration fieldDecl = typeDecl.fields[i];
				if (fieldDecl.binding == existingField) {
					synthField.name = CharOperation.concat(
						TypeConstants.SYNTHETIC_OUTER_LOCAL_PREFIX,
						actualOuterLocalVariable.name,
						("$" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
					needRecheck = true;
					break;
				}
			}
		}
	} while (needRecheck);
	return synthField;
}
/* Add a new synthetic field for <enclosingType>.
*	Answer the new field or the existing field if one already existed.
*/
public FieldBinding addSyntheticFieldForInnerclass(ReferenceBinding enclosingType) {
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
		this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(5);

	FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(enclosingType);
	if (synthField == null) {
		synthField = new SyntheticFieldBinding(
			CharOperation.concat(
				TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX,
				String.valueOf(enclosingType.depth()).toCharArray()),
			enclosingType,
			ClassFileConstants.AccDefault | ClassFileConstants.AccFinal | ClassFileConstants.AccSynthetic,
			this,
			Constant.NotAConstant,
			this.synthetics[SourceTypeBinding.FIELD_EMUL].size());
		this.synthetics[SourceTypeBinding.FIELD_EMUL].put(enclosingType, synthField);
	}
	// ensure there is not already such a field defined by the user
	boolean needRecheck;
	do {
		needRecheck = false;
		FieldBinding existingField;
		if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
			TypeDeclaration typeDecl = this.classScope.referenceContext;
			for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
				FieldDeclaration fieldDecl = typeDecl.fields[i];
				if (fieldDecl.binding == existingField) {
					if (this.scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5) {
						synthField.name = CharOperation.concat(
							synthField.name,
							"$".toCharArray()); //$NON-NLS-1$
						needRecheck = true;
					} else {
						this.scope.problemReporter().duplicateFieldInType(this, fieldDecl);
					}
					break;
				}
			}
		}
	} while (needRecheck);
	return synthField;
}
/* Add a new synthetic field for a class literal access.
*	Answer the new field or the existing field if one already existed.
*/
public FieldBinding addSyntheticFieldForClassLiteral(TypeBinding targetType, BlockScope blockScope) {
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] == null)
		this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] = new HashMap(5);

	// use a different table than FIELDS, given there might be a collision between emulation of X.this$0 and X.class.
	FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].get(targetType);
	if (synthField == null) {
		synthField = new SyntheticFieldBinding(
			CharOperation.concat(
				TypeConstants.SYNTHETIC_CLASS,
				String.valueOf(this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].size()).toCharArray()),
			blockScope.getJavaLangClass(),
			ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic,
			this,
			Constant.NotAConstant,
			this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].size());
		this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].put(targetType, synthField);
	}
	// ensure there is not already such a field defined by the user
	FieldBinding existingField;
	if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
		TypeDeclaration typeDecl = blockScope.referenceType();
		for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
			FieldDeclaration fieldDecl = typeDecl.fields[i];
			if (fieldDecl.binding == existingField) {
				blockScope.problemReporter().duplicateFieldInType(this, fieldDecl);
				break;
			}
		}
	}
	return synthField;
}
/* Add a new synthetic field for the emulation of the assert statement.
*	Answer the new field or the existing field if one already existed.
*/
public FieldBinding addSyntheticFieldForAssert(BlockScope blockScope) {
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
		this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(5);

	FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get("assertionEmulation"); //$NON-NLS-1$
	if (synthField == null) {
		synthField = new SyntheticFieldBinding(
			TypeConstants.SYNTHETIC_ASSERT_DISABLED,
			TypeBinding.BOOLEAN,
			ClassFileConstants.AccDefault | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic | ClassFileConstants.AccFinal,
			this,
			Constant.NotAConstant,
			this.synthetics[SourceTypeBinding.FIELD_EMUL].size());
		this.synthetics[SourceTypeBinding.FIELD_EMUL].put("assertionEmulation", synthField); //$NON-NLS-1$
	}
	// ensure there is not already such a field defined by the user
	// ensure there is not already such a field defined by the user
	boolean needRecheck;
	int index = 0;
	do {
		needRecheck = false;
		FieldBinding existingField;
		if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
			TypeDeclaration typeDecl = this.classScope.referenceContext;
			for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
				FieldDeclaration fieldDecl = typeDecl.fields[i];
				if (fieldDecl.binding == existingField) {
					synthField.name = CharOperation.concat(
						TypeConstants.SYNTHETIC_ASSERT_DISABLED,
						("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
					needRecheck = true;
					break;
				}
			}
		}
	} while (needRecheck);
	return synthField;
}
/* Add a new synthetic field for recording all enum constant values
*	Answer the new field or the existing field if one already existed.
*/
public FieldBinding addSyntheticFieldForEnumValues() {
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
		this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(5);

	FieldBinding synthField = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get("enumConstantValues"); //$NON-NLS-1$
	if (synthField == null) {
		synthField = new SyntheticFieldBinding(
			TypeConstants.SYNTHETIC_ENUM_VALUES,
			this.scope.createArrayType(this,1),
			ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic | ClassFileConstants.AccFinal,
			this,
			Constant.NotAConstant,
			this.synthetics[SourceTypeBinding.FIELD_EMUL].size());
		this.synthetics[SourceTypeBinding.FIELD_EMUL].put("enumConstantValues", synthField); //$NON-NLS-1$
	}
	// ensure there is not already such a field defined by the user
	// ensure there is not already such a field defined by the user
	boolean needRecheck;
	int index = 0;
	do {
		needRecheck = false;
		FieldBinding existingField;
		if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
			TypeDeclaration typeDecl = this.classScope.referenceContext;
			for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
				FieldDeclaration fieldDecl = typeDecl.fields[i];
				if (fieldDecl.binding == existingField) {
					synthField.name = CharOperation.concat(
						TypeConstants.SYNTHETIC_ENUM_VALUES,
						("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
					needRecheck = true;
					break;
				}
			}
		}
	} while (needRecheck);
	return synthField;
}
/* Add a new synthetic access method for read/write access to <targetField>.
	Answer the new method or the existing method if one already existed.
*/
public SyntheticMethodBinding addSyntheticMethod(FieldBinding targetField, boolean isReadAccess) {
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
		this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5);

	SyntheticMethodBinding accessMethod = null;
	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(targetField);
	if (accessors == null) {
		accessMethod = new SyntheticMethodBinding(targetField, isReadAccess, this);
		this.synthetics[SourceTypeBinding.METHOD_EMUL].put(targetField, accessors = new SyntheticMethodBinding[2]);
		accessors[isReadAccess ? 0 : 1] = accessMethod;
	} else {
		if ((accessMethod = accessors[isReadAccess ? 0 : 1]) == null) {
			accessMethod = new SyntheticMethodBinding(targetField, isReadAccess, this);
			accessors[isReadAccess ? 0 : 1] = accessMethod;
		}
	}
	return accessMethod;
}
/* Add a new synthetic method the enum type. Selector can either be 'values' or 'valueOf'.
 * char[] constants from TypeConstants must be used: TypeConstants.VALUES/VALUEOF
*/
public SyntheticMethodBinding addSyntheticEnumMethod(char[] selector) {
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
		this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5);

	SyntheticMethodBinding accessMethod = null;
	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(selector);
	if (accessors == null) {
		accessMethod = new SyntheticMethodBinding(this, selector);
		this.synthetics[SourceTypeBinding.METHOD_EMUL].put(selector, accessors = new SyntheticMethodBinding[2]);
		accessors[0] = accessMethod;
	} else {
		if ((accessMethod = accessors[0]) == null) {
			accessMethod = new SyntheticMethodBinding(this, selector);
			accessors[0] = accessMethod;
		}
	}
	return accessMethod;
}
/*
 * Add a synthetic field to handle the cache of the switch translation table for the corresponding enum type
 */
public SyntheticFieldBinding addSyntheticFieldForSwitchEnum(char[] fieldName, String key) {
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
		this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap(5);

	SyntheticFieldBinding synthField = (SyntheticFieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(key);
	if (synthField == null) {
		synthField = new SyntheticFieldBinding(
			fieldName,
			this.scope.createArrayType(TypeBinding.INT,1),
			ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic | ClassFileConstants.AccSynthetic,
			this,
			Constant.NotAConstant,
			this.synthetics[SourceTypeBinding.FIELD_EMUL].size());
		this.synthetics[SourceTypeBinding.FIELD_EMUL].put(key, synthField);
	}
	// ensure there is not already such a field defined by the user
	boolean needRecheck;
	int index = 0;
	do {
		needRecheck = false;
		FieldBinding existingField;
		if ((existingField = this.getField(synthField.name, true /*resolve*/)) != null) {
			TypeDeclaration typeDecl = this.classScope.referenceContext;
			for (int i = 0, max = typeDecl.fields.length; i < max; i++) {
				FieldDeclaration fieldDecl = typeDecl.fields[i];
				if (fieldDecl.binding == existingField) {
					synthField.name = CharOperation.concat(
						fieldName,
						("_" + String.valueOf(index++)).toCharArray()); //$NON-NLS-1$
					needRecheck = true;
					break;
				}
			}
		}
	} while (needRecheck);
	return synthField;
}
/* Add a new synthetic method the enum type. Selector can either be 'values' or 'valueOf'.
 * char[] constants from TypeConstants must be used: TypeConstants.VALUES/VALUEOF
*/
public SyntheticMethodBinding addSyntheticMethodForSwitchEnum(TypeBinding enumBinding) {
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
		this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5);

	SyntheticMethodBinding accessMethod = null;
	char[] selector = CharOperation.concat(TypeConstants.SYNTHETIC_SWITCH_ENUM_TABLE, enumBinding.constantPoolName());
	CharOperation.replace(selector, '/', '$');
	final String key = new String(selector);
	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(key);
	// first add the corresponding synthetic field
	if (accessors == null) {
		// then create the synthetic method
		final SyntheticFieldBinding fieldBinding = this.addSyntheticFieldForSwitchEnum(selector, key);
		accessMethod = new SyntheticMethodBinding(fieldBinding, this, enumBinding, selector);
		this.synthetics[SourceTypeBinding.METHOD_EMUL].put(key, accessors = new SyntheticMethodBinding[2]);
		accessors[0] = accessMethod;
	} else {
		if ((accessMethod = accessors[0]) == null) {
			final SyntheticFieldBinding fieldBinding = this.addSyntheticFieldForSwitchEnum(selector, key);
			accessMethod = new SyntheticMethodBinding(fieldBinding, this, enumBinding, selector);
			accessors[0] = accessMethod;
		}
	}
	return accessMethod;
}
/* Add a new synthetic access method for access to <targetMethod>.
 * Must distinguish access method used for super access from others (need to use invokespecial bytecode)
	Answer the new method or the existing method if one already existed.
*/
public SyntheticMethodBinding addSyntheticMethod(MethodBinding targetMethod, boolean isSuperAccess) {
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
		this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5);

	SyntheticMethodBinding accessMethod = null;
	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(targetMethod);
	if (accessors == null) {
		accessMethod = new SyntheticMethodBinding(targetMethod, isSuperAccess, this);
		this.synthetics[SourceTypeBinding.METHOD_EMUL].put(targetMethod, accessors = new SyntheticMethodBinding[2]);
		accessors[isSuperAccess ? 0 : 1] = accessMethod;
	} else {
		if ((accessMethod = accessors[isSuperAccess ? 0 : 1]) == null) {
			accessMethod = new SyntheticMethodBinding(targetMethod, isSuperAccess, this);
			accessors[isSuperAccess ? 0 : 1] = accessMethod;
		}
	}
	return accessMethod;
}
/*
 * Record the fact that bridge methods need to be generated to override certain inherited methods
 */
public SyntheticMethodBinding addSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge, MethodBinding targetMethod) {
	if (isInterface()) return null; // only classes & enums get bridge methods
	// targetMethod may be inherited
	if (inheritedMethodToBridge.returnType.erasure() == targetMethod.returnType.erasure()
		&& inheritedMethodToBridge.areParameterErasuresEqual(targetMethod)) {
			return null; // do not need bridge method
	}
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) {
		this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5);
	} else {
		// check to see if there is another equivalent inheritedMethod already added
		Iterator synthMethods = this.synthetics[SourceTypeBinding.METHOD_EMUL].keySet().iterator();
		while (synthMethods.hasNext()) {
			Object synthetic = synthMethods.next();
			if (synthetic instanceof MethodBinding) {
				MethodBinding method = (MethodBinding) synthetic;
				if (CharOperation.equals(inheritedMethodToBridge.selector, method.selector)
					&& inheritedMethodToBridge.returnType.erasure() == method.returnType.erasure()
					&& inheritedMethodToBridge.areParameterErasuresEqual(method)) {
						return null;
				}
			}
		}
	}

	SyntheticMethodBinding accessMethod = null;
	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(inheritedMethodToBridge);
	if (accessors == null) {
		accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, targetMethod, this);
		this.synthetics[SourceTypeBinding.METHOD_EMUL].put(inheritedMethodToBridge, accessors = new SyntheticMethodBinding[2]);
		accessors[1] = accessMethod;
	} else {
		if ((accessMethod = accessors[1]) == null) {
			accessMethod = new SyntheticMethodBinding(inheritedMethodToBridge, targetMethod, this);
			accessors[1] = accessMethod;
		}
	}
	return accessMethod;
}
public int kind() {
	if (this.typeVariables != Binding.NO_TYPE_VARIABLES) return Binding.GENERIC_TYPE;
	return Binding.TYPE;
}
public char[] computeUniqueKey(boolean isLeaf) {
	char[] uniqueKey = super.computeUniqueKey(isLeaf);
	if (uniqueKey.length == 2) return uniqueKey; // problem type's unique key is "L;"
	if (Util.isClassFileName(this.fileName)) return uniqueKey; // no need to insert compilation unit name for a .class file

	// insert compilation unit name if the type name is not the main type name
	int end = CharOperation.lastIndexOf('.', this.fileName);
	if (end != -1) {
		int start = CharOperation.lastIndexOf('/', this.fileName) + 1;
		char[] mainTypeName = CharOperation.subarray(this.fileName, start, end);
		start = CharOperation.lastIndexOf('/', uniqueKey) + 1;
		if (start == 0)
			start = 1; // start after L
		end = CharOperation.indexOf('$', uniqueKey, start);
		if (end == -1)
			end = CharOperation.indexOf('<', uniqueKey, start);
		if (end == -1)
			end = CharOperation.indexOf(';', uniqueKey, start);
		char[] topLevelType = CharOperation.subarray(uniqueKey, start, end);
		if (!CharOperation.equals(topLevelType, mainTypeName)) {
			StringBuffer buffer = new StringBuffer();
			buffer.append(uniqueKey, 0, start);
			buffer.append(mainTypeName);
			buffer.append('~');
			buffer.append(topLevelType);
			buffer.append(uniqueKey, end, uniqueKey.length - end);
			int length = buffer.length();
			uniqueKey = new char[length];
			buffer.getChars(0, length, uniqueKey, 0);
			return uniqueKey;
		}
	}
	return uniqueKey;
}
void faultInTypesForFieldsAndMethods() {
	// check @Deprecated annotation
//	getAnnotationTagBits(); // marks as deprecated by side effect
	ReferenceBinding enclosingType = this.enclosingType();
	if (enclosingType != null && enclosingType.isViewedAsDeprecated() && !this.isDeprecated())
		this.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
	fields();
	methods();

//	for (int i = 0, length = this.memberTypes.length; i < length; i++)
//		((SourceTypeBinding) this.memberTypes[i]).faultInTypesForFieldsAndMethods();
}
// NOTE: the type of each field of a source type is resolved when needed
public FieldBinding[] fields() {
	if ((this.tagBits & TagBits.AreFieldsComplete) == 0)
	{

		int failed = 0;
		FieldBinding[] resolvedFields = this.fields;
		try {
			// lazily sort fields
			if ((this.tagBits & TagBits.AreFieldsSorted) == 0) {
				int length = this.fields.length;
				if (length > 1)
					ReferenceBinding.sortFields(this.fields, 0, length);
				this.tagBits |= TagBits.AreFieldsSorted;
			}
			for (int i = 0, length = this.fields.length; i < length; i++) {
				if (resolveTypeFor(this.fields[i]) == null) {
					// do not alter original field array until resolution is over, due to reentrance (143259)
					if (resolvedFields == this.fields) {
						System.arraycopy(this.fields, 0, resolvedFields = new FieldBinding[length], 0, length);
					}
					resolvedFields[i] = null;
					failed++;
				}
			}
		} finally {
			if (failed > 0) {
				// ensure fields are consistent reqardless of the error
				int newSize = resolvedFields.length - failed;
				if (newSize == 0)
					return this.fields = Binding.NO_FIELDS;

				FieldBinding[] newFields = new FieldBinding[newSize];
				for (int i = 0, j = 0, length = resolvedFields.length; i < length; i++) {
					if (resolvedFields[i] != null)
						newFields[j++] = resolvedFields[i];
				}
				this.fields = newFields;
			}
		}
		this.tagBits |= TagBits.AreFieldsComplete;
	}
	if (this.nextType!=null)
	{
		FieldBinding[] moreFields=this.nextType.fields();
		FieldBinding[] combinedFields=new FieldBinding[this.fields.length+moreFields.length];
		System.arraycopy(this.fields, 0, combinedFields, 0, this.fields.length);
		System.arraycopy(moreFields, 0, combinedFields, this.fields.length, moreFields.length);

		return combinedFields;

	}
	else
		return this.fields;
}
/**
 * @see org.eclipse.wst.jsdt.internal.compiler.lookup.TypeBinding#genericTypeSignature()
 */
public char[] genericTypeSignature() {
    if (this.genericReferenceTypeSignature == null)
    	this.genericReferenceTypeSignature = computeGenericTypeSignature(this.typeVariables);
    return this.genericReferenceTypeSignature;
}
/**
 * <param1 ... paramN>superclass superinterface1 ... superinterfaceN
 * <T:LY<TT;>;U:Ljava/lang/Object;V::Ljava/lang/Runnable;:Ljava/lang/Cloneable;:Ljava/util/Map;>Ljava/lang/Exception;Ljava/lang/Runnable;
 */
public char[] genericSignature() {
    StringBuffer sig = null;
	if (this.typeVariables != Binding.NO_TYPE_VARIABLES) {
	    sig = new StringBuffer(10);
	    sig.append('<');
	    for (int i = 0, length = this.typeVariables.length; i < length; i++)
	        sig.append(this.typeVariables[i].genericSignature());
	    sig.append('>');
	} else {
	    // could still need a signature if any of supertypes is parameterized
	    noSignature: if (this.superclass == null || !this.superclass.isParameterizedType()) {
		    for (int i = 0, length = this.superInterfaces.length; i < length; i++)
		        if (this.superInterfaces[i].isParameterizedType())
					break noSignature;
	        return null;
	    }
	    sig = new StringBuffer(10);
	}
	if (this.superclass != null)
		sig.append(this.superclass.genericTypeSignature());
	else // interface scenario only (as Object cannot be generic) - 65953
		sig.append(this.scope.getJavaLangObject().genericTypeSignature());
    for (int i = 0, length = this.superInterfaces.length; i < length; i++)
        sig.append(this.superInterfaces[i].genericTypeSignature());
	return sig.toString().toCharArray();
}

/**
 * Compute the tagbits for standard annotations. For source types, these could require
 * lazily resolving corresponding annotation nodes, in case of forward references.
 * @see org.eclipse.wst.jsdt.internal.compiler.lookup.Binding#getAnnotationTagBits()
 */
public long getAnnotationTagBits() {
//	if ((this.tagBits & TagBits.AnnotationResolved) == 0 && this.scope != null) {
//		TypeDeclaration typeDecl = this.classScope.referenceContext;
//		boolean old = typeDecl.staticInitializerScope.insideTypeAnnotation;
//		try {
//			typeDecl.staticInitializerScope.insideTypeAnnotation = true;
//			ASTNode.resolveAnnotations(typeDecl.staticInitializerScope, typeDecl.annotations, this);
//		} finally {
//			typeDecl.staticInitializerScope.insideTypeAnnotation = old;
//		}
//		if ((this.tagBits & TagBits.AnnotationDeprecated) != 0)
//			this.modifiers |= ClassFileConstants.AccDeprecated;
//	}
	return this.tagBits;
}
public MethodBinding[] getDefaultAbstractMethods() {
	int count = 0;
	for (int i = this.methods.length; --i >= 0;)
		if (this.methods[i].isDefaultAbstract())
			count++;
	if (count == 0) return Binding.NO_METHODS;

	MethodBinding[] result = new MethodBinding[count];
	count = 0;
	for (int i = this.methods.length; --i >= 0;)
		if (this.methods[i].isDefaultAbstract())
			result[count++] = this.methods[i];
	return result;
}

public MethodBinding getExactConstructor(TypeBinding[] argumentTypes) {
	MethodBinding exactConstructor = getExactConstructor0(argumentTypes);
	if (exactConstructor==null && this.nextType!=null)
		exactConstructor=this.nextType.getExactConstructor(argumentTypes);
	return exactConstructor;
}

// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
private MethodBinding getExactConstructor0(TypeBinding[] argumentTypes) {
	int argCount = argumentTypes.length;
	if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods
		long range;
		if ((range = ReferenceBinding.binarySearch(TypeConstants.INIT, this.methods)) >= 0) {
//			nextMethod: 
				for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) {
				MethodBinding method = this.methods[imethod];
//				if (method.parameters.length == argCount) {
//					TypeBinding[] toMatch = method.parameters;
//					for (int iarg = 0; iarg < argCount; iarg++)
//						if (toMatch[iarg] != argumentTypes[iarg])
//							continue nextMethod;
					return method;
//				}
			}
		}
	} else {
		// lazily sort methods
		if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
			int length = this.methods.length;
			if (length > 1)
				ReferenceBinding.sortMethods(this.methods, 0, length);
			this.tagBits |= TagBits.AreMethodsSorted;
		}
		long range;
		if ((range = ReferenceBinding.binarySearch(TypeConstants.INIT, this.methods)) >= 0) {
//			nextMethod: 
				for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) {
				MethodBinding method = this.methods[imethod];
				if (resolveTypesFor(method) == null || method.returnType == null) {
					methods();
					return getExactConstructor(argumentTypes);  // try again since the problem methods have been removed
				}
//				if (method.parameters.length == argCount) {
//					TypeBinding[] toMatch = method.parameters;
//					for (int iarg = 0; iarg < argCount; iarg++)
//						if (toMatch[iarg] != argumentTypes[iarg])
//							continue nextMethod;
//					return method;
//				}
				return method;
			}
		}
	}
	return null;
}


public MethodBinding getExactMethod(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
	MethodBinding exactMethod = getExactMethod0(selector, argumentTypes, refScope);
	if (exactMethod==null && this.nextType!=null)
		exactMethod=this.nextType.getExactMethod(selector, argumentTypes, refScope);
	return exactMethod;
}
//NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
//searches up the hierarchy as long as no potential (but not exact) match was found.
private MethodBinding getExactMethod0(char[] selector, TypeBinding[] argumentTypes, CompilationUnitScope refScope) {
	// sender from refScope calls recordTypeReference(this)
//	int argCount = argumentTypes.length;
	boolean foundNothing = true;

	if ((this.tagBits & TagBits.AreMethodsComplete) != 0) { // have resolved all arg types & return type of the methods
		long range;
		if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
//			nextMethod:
				for (int imethod = (int)range, end = (int)(range >> 32); imethod <= end; imethod++) {
				MethodBinding method = this.methods[imethod];
				foundNothing = false; // inner type lookups must know that a method with this name exists
//				if (method.parameters.length == argCount) {
//					TypeBinding[] toMatch = method.parameters;
//					for (int iarg = 0; iarg < argCount; iarg++)
//						if (toMatch[iarg] != argumentTypes[iarg])
//						{
//						if (toMatch[iarg].id!=TypeIds.T_any && argumentTypes[iarg].id!=TypeIds.T_any)
//						continue nextMethod;
//					}
//					return method;
//				}
				return method;
			}
		}
	} else {
		// lazily sort methods
		if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
			int length = this.methods.length;
			if (length > 1)
				ReferenceBinding.sortMethods(this.methods, 0, length);
			this.tagBits |= TagBits.AreMethodsSorted;
		}

		long range;
		if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
			// check unresolved method
			int start = (int) range, end = (int) (range >> 32);
			for (int imethod = start; imethod <= end; imethod++) {
				MethodBinding method = this.methods[imethod];
				if (resolveTypesFor(method) == null || method.returnType == null) {
					methods();
					return getExactMethod(selector, argumentTypes, refScope); // try again since the problem methods have been removed
				}
			}
			// check dup collisions
			boolean isSource15 = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
			for (int i = start; i <= end; i++) {
				MethodBinding method1 = this.methods[i];
				for (int j = end; j > i; j--) {
					MethodBinding method2 = this.methods[j];
					boolean paramsMatch = isSource15
						? method1.areParameterErasuresEqual(method2)
						: method1.areParametersEqual(method2);
					if (paramsMatch) {
						methods();
						return getExactMethod(selector, argumentTypes, refScope); // try again since the problem methods have been removed
					}
				}
			}
			return this.methods[start];
//			nextMethod: for (int imethod = start; imethod <= end; imethod++) {
//				FunctionBinding method = this.methods[imethod];
//				TypeBinding[] toMatch = method.parameters;
//				if (toMatch.length == argCount) {
//					for (int iarg = 0; iarg < argCount; iarg++)
//						if (toMatch[iarg] != argumentTypes[iarg])
//							continue nextMethod;
//					return method;
//				}
//			}
		}
	}

	if (foundNothing) {
		if (JavaScriptCore.IS_ECMASCRIPT4 && isInterface()) {
			 if (this.superInterfaces.length == 1) {
				if (refScope != null)
					refScope.recordTypeReference(this.superInterfaces[0]);
				return this.superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
			 }
		/* BC- Added cycle check BUG 200501 */
		} else if (this.superclass != null && this.superclass!=this) {
			if (refScope != null)
				refScope.recordTypeReference(this.superclass);
			return this.superclass.getExactMethod(selector, argumentTypes, refScope);
		}
	}
	return null;
}


public FieldBinding getField(char[] fieldName, boolean needResolve) {
	FieldBinding field = getField0(fieldName, needResolve);
	if (field==null && this.nextType!=null)
		field=this.nextType.getField(fieldName, needResolve);
	return field;
}
//NOTE: the type of a field of a source type is resolved when needed
private FieldBinding getField0(char[] fieldName, boolean needResolve) {

	if ((this.tagBits & TagBits.AreFieldsComplete) != 0)
		return ReferenceBinding.binarySearch(fieldName, this.fields);

	// lazily sort fields
	if ((this.tagBits & TagBits.AreFieldsSorted) == 0) {
		int length = this.fields.length;
		if (length > 1)
			ReferenceBinding.sortFields(this.fields, 0, length);
		this.tagBits |= TagBits.AreFieldsSorted;
	}
	// always resolve anyway on source types
	FieldBinding field = ReferenceBinding.binarySearch(fieldName, this.fields);
	if (field != null) {
		FieldBinding result = null;
		try {
			result = resolveTypeFor(field);
			return result;
		} finally {
			if (result == null) {
				// ensure fields are consistent reqardless of the error
				int newSize = this.fields.length - 1;
				if (newSize == 0) {
					this.fields = Binding.NO_FIELDS;
				} else {
					FieldBinding[] newFields = new FieldBinding[newSize];
					int index = 0;
					for (int i = 0, length = this.fields.length; i < length; i++) {
						FieldBinding f = this.fields[i];
						if (f == field) continue;
						newFields[index++] = f;
					}
					this.fields = newFields;
				}
			}
		}
	}
	return null;
}

public MethodBinding[] getMethods(char[] selector) {
	MethodBinding[] meths = getMethods0(selector);
	if (this.nextType==null)
		return meths;
	MethodBinding[] moreMethods=this.nextType.getMethods(selector);
	MethodBinding[] combinedMethods=new MethodBinding[meths.length+moreMethods.length];
	System.arraycopy( meths, 0, combinedMethods, 0,  meths.length);
	System.arraycopy(moreMethods, 0, combinedMethods,  meths.length, moreMethods.length);

	return combinedMethods;	
}
 
// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
private MethodBinding[] getMethods0(char[] selector) {
	if ((this.tagBits & TagBits.AreMethodsComplete) != 0) {
		long range;
		if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
			int start = (int) range, end = (int) (range >> 32);
			int length = end - start + 1;
			MethodBinding[] result;
			System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length);
			return result;
		} else {
			return Binding.NO_METHODS;
		}
	}
	// lazily sort methods
	if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
		int length = this.methods.length;
		if (length > 1)
			ReferenceBinding.sortMethods(this.methods, 0, length);
		this.tagBits |= TagBits.AreMethodsSorted;
	}
	MethodBinding[] result;
	long range;
	if ((range = ReferenceBinding.binarySearch(selector, this.methods)) >= 0) {
		int start = (int) range, end = (int) (range >> 32);
		for (int i = start; i <= end; i++) {
			MethodBinding method = this.methods[i];
			if (resolveTypesFor(method) == null || method.returnType == null) {
				methods();
				return getMethods(selector); // try again since the problem methods have been removed
			}
		}
		int length = end - start + 1;
		System.arraycopy(this.methods, start, result = new MethodBinding[length], 0, length);
	} else {
		return Binding.NO_METHODS;
	}
	boolean isSource15 = this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5;
	for (int i = 0, length = result.length - 1; i < length; i++) {
		MethodBinding method = result[i];
		for (int j = length; j > i; j--) {
			boolean paramsMatch = isSource15
				? method.areParameterErasuresEqual(result[j])
				: method.areParametersEqual(result[j]);
			if (paramsMatch) {
				methods();
				return getMethods(selector); // try again since the duplicate methods have been removed
			}
		}
	}
	return result;
}
/* Answer the synthetic field for <actualOuterLocalVariable>
*	or null if one does not exist.
*/
public FieldBinding getSyntheticField(LocalVariableBinding actualOuterLocalVariable) {
	if (this.synthetics == null || this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) return null;
	return (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(actualOuterLocalVariable);
}
/* Answer the synthetic field for <targetEnclosingType>
*	or null if one does not exist.
*/
public FieldBinding getSyntheticField(ReferenceBinding targetEnclosingType, boolean onlyExactMatch) {

	if (this.synthetics == null || this.synthetics[SourceTypeBinding.FIELD_EMUL] == null) return null;
	FieldBinding field = (FieldBinding) this.synthetics[SourceTypeBinding.FIELD_EMUL].get(targetEnclosingType);
	if (field != null) return field;

	// type compatibility : to handle cases such as
	// class T { class M{}}
	// class S extends T { class N extends M {}} --> need to use S as a default enclosing instance for the super constructor call in N().
	if (!onlyExactMatch){
		Iterator accessFields = this.synthetics[SourceTypeBinding.FIELD_EMUL].values().iterator();
		while (accessFields.hasNext()) {
			field = (FieldBinding) accessFields.next();
			if (CharOperation.prefixEquals(TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX, field.name)
				&& field.type.findSuperTypeWithSameErasure(targetEnclosingType) != null)
					return field;
		}
	}
	return null;
}
/*
 * Answer the bridge method associated for an  inherited methods or null if one does not exist
 */
public SyntheticMethodBinding getSyntheticBridgeMethod(MethodBinding inheritedMethodToBridge) {
	if (this.synthetics == null) return null;
	if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) return null;
	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(inheritedMethodToBridge);
	if (accessors == null) return null;
	return accessors[1];
}

/**
 * @see org.eclipse.wst.jsdt.internal.compiler.lookup.Binding#initializeDeprecatedAnnotationTagBits()
 */
public void initializeDeprecatedAnnotationTagBits() {
//	if ((this.tagBits & TagBits.DeprecatedAnnotationResolved) == 0) {
//		TypeDeclaration typeDecl = this.classScope.referenceContext;
//		boolean old = typeDecl.staticInitializerScope.insideTypeAnnotation;
//		try {
//			typeDecl.staticInitializerScope.insideTypeAnnotation = true;
//			ASTNode.resolveDeprecatedAnnotations(typeDecl.staticInitializerScope, typeDecl.annotations, this);
//			this.tagBits |= TagBits.DeprecatedAnnotationResolved;
//		} finally {
//			typeDecl.staticInitializerScope.insideTypeAnnotation = old;
//		}
//		if ((this.tagBits & TagBits.AnnotationDeprecated) != 0) {
//			this.modifiers |= ClassFileConstants.AccDeprecated;
//		}
//	}
}

/**
 * Returns true if a type is identical to another one,
 * or for generic types, true if compared to its raw type.
 */
public boolean isEquivalentTo(TypeBinding otherType) {

	if (this == otherType) return true;
	if (otherType == null) return false;
	switch(otherType.kind()) {

		case Binding.WILDCARD_TYPE :
			return ((WildcardBinding) otherType).boundCheck(this);

		case Binding.PARAMETERIZED_TYPE :
			if ((otherType.tagBits & TagBits.HasDirectWildcard) == 0 && (!this.isMemberType() || !otherType.isMemberType()))
				return false; // should have been identical
			ParameterizedTypeBinding otherParamType = (ParameterizedTypeBinding) otherType;
			if (this != otherParamType.genericType())
				return false;
			if (!isStatic()) { // static member types do not compare their enclosing
            	ReferenceBinding enclosing = enclosingType();
            	if (enclosing != null) {
            		ReferenceBinding otherEnclosing = otherParamType.enclosingType();
            		if (otherEnclosing == null) return false;
            		if ((otherEnclosing.tagBits & TagBits.HasDirectWildcard) == 0) {
						if (enclosing != otherEnclosing) return false;
            		} else {
            			if (!enclosing.isEquivalentTo(otherParamType.enclosingType())) return false;
            		}
            	}
			}
			int length = this.typeVariables == null ? 0 : this.typeVariables.length;
			TypeBinding[] otherArguments = otherParamType.arguments;
			int otherLength = otherArguments == null ? 0 : otherArguments.length;
			if (otherLength != length)
				return false;
			for (int i = 0; i < length; i++)
				if (!this.typeVariables[i].isTypeArgumentContainedBy(otherArguments[i]))
					return false;
			return true;

		case Binding.RAW_TYPE :
	        return otherType.erasure() == this;
	}
	return false;
}
public boolean isGenericType() {
    return this.typeVariables != Binding.NO_TYPE_VARIABLES;
}
public ReferenceBinding[] memberTypes() {
	if (this.nextType==null)
		return this.memberTypes;
	
	ReferenceBinding[] moreTypes=this.nextType.memberTypes();
	ReferenceBinding[] combinedTypes=new ReferenceBinding[this.memberTypes.length+moreTypes.length];
	System.arraycopy(this.memberTypes, 0, combinedTypes, 0, this.memberTypes.length);
	System.arraycopy(moreTypes, 0, combinedTypes, this.memberTypes.length, moreTypes.length);

	return combinedTypes;

}
public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] == null)
		this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] = new HashMap(5);

	Hashtable fieldMap = (Hashtable) this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].get(targetField);
	if (fieldMap == null) {
		fieldMap = new Hashtable(5);
		this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].put(targetField, fieldMap);
	}
	FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
	if (updatedField == null){
		updatedField = new FieldBinding(targetField, newDeclaringClass);
		fieldMap.put(newDeclaringClass, updatedField);
	}
	return updatedField;
}
public MethodBinding getUpdatedMethodBinding(MethodBinding targetMethod, ReferenceBinding newDeclaringClass) {
	if (this.synthetics == null)
		this.synthetics = new HashMap[4];
	if (this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] == null)
		this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] = new HashMap(5);

	Hashtable methodMap = (Hashtable) this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].get(targetMethod);
	if (methodMap == null) {
		methodMap = new Hashtable(5);
		this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL].put(targetMethod, methodMap);
	}
	MethodBinding updatedMethod = (MethodBinding) methodMap.get(newDeclaringClass);
	if (updatedMethod == null){
		updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);
		updatedMethod.createFunctionTypeBinding(scope);
		methodMap.put(newDeclaringClass, updatedMethod);
	}
	return updatedMethod;
}
public boolean hasMemberTypes() {
    boolean hasMembers= this.memberTypes!=null &&  this.memberTypes.length > 0;
    if (!hasMembers && this.nextType!=null)
    	hasMembers=this.nextType.hasMemberTypes();
    return hasMembers;
}
// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
public MethodBinding[] methods() {

	if ((this.tagBits & TagBits.AreMethodsComplete) == 0) {
		// lazily sort methods
		if ((this.tagBits & TagBits.AreMethodsSorted) == 0) {
			int length = this.methods.length;
			if (length > 1)
				ReferenceBinding.sortMethods(this.methods, 0, length);
			this.tagBits |= TagBits.AreMethodsSorted;
		}
		int failed = 0;
		MethodBinding[] resolvedMethods = this.methods;
		try {
			for (int i = 0, length = this.methods.length; i < length; i++) {
				if (resolveTypesFor(this.methods[i]) == null) {
					// do not alter original method array until resolution is over, due to reentrance (143259)
					if (resolvedMethods == this.methods) {
						System.arraycopy(this.methods, 0,
								resolvedMethods = new MethodBinding[length], 0,
								length);
					}
					resolvedMethods[i] = null; // unable to resolve parameters
					failed++;
				}
			}

			// find & report collision cases
			
			boolean complyTo15 = 
				(this.scope!=null && this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5);
			for (int i = 0, length = this.methods.length; i < length; i++) {
				MethodBinding method = resolvedMethods[i];
				if (method == null)
					continue;
				char[] selector = method.selector;
				AbstractMethodDeclaration methodDecl = null;
				nextSibling: for (int j = i + 1; j < length; j++) {
					MethodBinding method2 = resolvedMethods[j];
					if (method2 == null)
						continue nextSibling;
					if (!CharOperation.equals(selector, method2.selector))
						break nextSibling; // methods with same selector are contiguous

					if (complyTo15 && method.returnType != null
							&& method2.returnType != null) {
						// 8.4.2, for collision to be detected between m1 and m2:
						// signature(m1) == signature(m2) i.e. same arity, same type parameter count, can be substituted
						// signature(m1) == erasure(signature(m2)) or erasure(signature(m1)) == signature(m2)
						TypeBinding[] params1 = method.parameters;
						TypeBinding[] params2 = method2.parameters;
						int pLength = params1.length;
						if (pLength != params2.length)
							continue nextSibling;

						TypeVariableBinding[] vars = method.typeVariables;
						TypeVariableBinding[] vars2 = method2.typeVariables;
						boolean equalTypeVars = vars == vars2;
						MethodBinding subMethod = method2;
						if (!equalTypeVars) {
							MethodBinding temp = method
									.computeSubstitutedMethod(method2,
											this.scope.environment());
							if (temp != null) {
								equalTypeVars = true;
								subMethod = temp;
							}
						}
						boolean equalParams = method
								.areParametersEqual(subMethod);
						if (equalParams && equalTypeVars) {
							// duplicates regardless of return types
						} else if (method.returnType.erasure() == subMethod.returnType
								.erasure()
								&& (equalParams || method
										.areParameterErasuresEqual(method2))) {
							// name clash for sure if not duplicates, report as duplicates
						} else if (!equalTypeVars
								&& vars != Binding.NO_TYPE_VARIABLES
								&& vars2 != Binding.NO_TYPE_VARIABLES) {
							// type variables are different so we can distinguish between methods
							continue nextSibling;
						} else if (pLength > 0) {
							// check to see if the erasure of either method is equal to the other
							int index = pLength;
							for (; --index >= 0;) {
								if (params1[index] != params2[index].erasure())
									break;
								if (params1[index] == params2[index]) {
									TypeBinding type = params1[index]
											.leafComponentType();
									if (type instanceof SourceTypeBinding
											&& type.typeVariables() != Binding.NO_TYPE_VARIABLES) {
										index = pLength; // handle comparing identical source types like X<T>... its erasure is itself BUT we need to answer false
										break;
									}
								}
							}
							if (index >= 0 && index < pLength) {
								for (index = pLength; --index >= 0;)
									if (params1[index].erasure() != params2[index])
										break;
							}
							if (index >= 0)
								continue nextSibling;
						}
					} else if (!method.areParametersEqual(method2)) { // prior to 1.5, parameter identity meant a collision case
						continue nextSibling;
					}
					boolean isEnumSpecialMethod = isEnum()
							&& (CharOperation.equals(selector,
									TypeConstants.VALUEOF) || CharOperation
									.equals(selector, TypeConstants.VALUES));
					// report duplicate
					if (methodDecl == null) {
						methodDecl = method.sourceMethod(); // cannot be retrieved after binding is lost & may still be null if method is special
						if (methodDecl != null && methodDecl.binding != null) { // ensure its a valid user defined method
							if (isEnumSpecialMethod) {
								this.scope.problemReporter()
										.duplicateEnumSpecialMethod(this,
												methodDecl);
							} else {
								this.scope
										.problemReporter()
										.duplicateMethodInType(this, methodDecl);
							}
							methodDecl.binding = null;
							// do not alter original method array until resolution is over, due to reentrance (143259)
							if (resolvedMethods == this.methods) {
								System
										.arraycopy(
												this.methods,
												0,
												resolvedMethods = new MethodBinding[length],
												0, length);
							}
							resolvedMethods[i] = null;
							failed++;
						}
					}
					AbstractMethodDeclaration method2Decl = method2
							.sourceMethod();
					if (method2Decl != null && method2Decl.binding != null) { // ensure its a valid user defined method
						if (isEnumSpecialMethod) {
							this.scope.problemReporter()
									.duplicateEnumSpecialMethod(this,
											method2Decl);
						} else {
							this.scope.problemReporter().duplicateMethodInType(
									this, method2Decl);
						}
						method2Decl.binding = null;
						// do not alter original method array until resolution is over, due to reentrance (143259)
						if (resolvedMethods == this.methods) {
							System
									.arraycopy(
											this.methods,
											0,
											resolvedMethods = new MethodBinding[length],
											0, length);
						}
						resolvedMethods[j] = null;
						failed++;
					}
				}
				if (method.returnType == null && methodDecl == null) { // forget method with invalid return type... was kept to detect possible collisions
					methodDecl = method.sourceMethod();
					if (methodDecl != null) {
						methodDecl.binding = null;
					}
					// do not alter original method array until resolution is over, due to reentrance (143259)
					if (resolvedMethods == this.methods) {
						System.arraycopy(this.methods, 0,
								resolvedMethods = new MethodBinding[length], 0,
								length);
					}
					resolvedMethods[i] = null;
					failed++;
				}
			}
		} finally {
			if (failed > 0) {
				int newSize = resolvedMethods.length - failed;
				if (newSize == 0) {
					this.methods = Binding.NO_METHODS;
				} else {
					MethodBinding[] newMethods = new MethodBinding[newSize];
					for (int i = 0, j = 0, length = resolvedMethods.length; i < length; i++)
						if (resolvedMethods[i] != null)
							newMethods[j++] = resolvedMethods[i];
					this.methods = newMethods;
				}
			}

			// handle forward references to potential default abstract methods
			//		addDefaultAbstractMethods();
			this.tagBits |= TagBits.AreMethodsComplete;
		}
	}
	if (this.nextType!=null)
	{
		MethodBinding[] moreMethods=this.nextType.methods();
		MethodBinding[] combinedMethods=new MethodBinding[this.methods.length+moreMethods.length];
		System.arraycopy(this.methods, 0, combinedMethods, 0, this.methods.length);
		System.arraycopy(moreMethods, 0, combinedMethods, this.methods.length, moreMethods.length);

		return combinedMethods;

	}
	else
		return this.methods;

}
private FieldBinding resolveTypeFor(FieldBinding field) {
	if ((field.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
		return field;

	if (this.scope!=null && this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
		if ((field.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0)
			field.modifiers |= ClassFileConstants.AccDeprecated;
	}
	if (isViewedAsDeprecated() && !field.isDeprecated())
		field.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
	if (hasRestrictedAccess())
		field.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;
	return field;
//	FieldDeclaration[] fieldDecls = this.classScope.referenceContext.fields;
//	for (int f = 0, length = fieldDecls.length; f < length; f++) {
//		if (fieldDecls[f].binding != field)
//			continue;
//
//			MethodScope initializationScope = field.isStatic()
//				? this.classScope.referenceContext.staticInitializerScope
//				: this.classScope.referenceContext.initializerScope;
//			FieldBinding previousField = initializationScope.initializedField;
//			try {
//				initializationScope.initializedField = field;
//				FieldDeclaration fieldDecl = fieldDecls[f];
//				TypeBinding fieldType =
//					fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT
//						? initializationScope.environment().convertToRawType(this) // enum constant is implicitly of declaring enum type
//						: fieldDecl.type.resolveType(initializationScope, true /* check bounds*/);
//				field.type = fieldType;
//				field.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
//				if (fieldType == null) {
//					fieldDecl.binding = null;
//					return null;
//				}
//				if (fieldType == TypeBinding.VOID) {
//					this.scope.problemReporter().variableTypeCannotBeVoid(fieldDecl);
//					fieldDecl.binding = null;
//					return null;
//				}
//				if (fieldType.isArrayType() && ((ArrayBinding) fieldType).leafComponentType == TypeBinding.VOID) {
//					this.scope.problemReporter().variableTypeCannotBeVoidArray(fieldDecl);
//					fieldDecl.binding = null;
//					return null;
//				}
//				TypeBinding leafType = fieldType.leafComponentType();
//				if (leafType instanceof ReferenceBinding && (((ReferenceBinding)leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0) {
//					field.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
//				}
//			} finally {
//			    initializationScope.initializedField = previousField;
//			}
//		return field;
//	}
//	return null; // should never reach this point
}
public MethodBinding resolveTypesFor(MethodBinding method) {
	if ((method.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
		return method;

	if (this.scope!=null && this.scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
		if ((method.getAnnotationTagBits() & TagBits.AnnotationDeprecated) != 0)
			method.modifiers |= ClassFileConstants.AccDeprecated;
	}
	if (isViewedAsDeprecated() && !method.isDeprecated())
		method.modifiers |= ExtraCompilerModifiers.AccDeprecatedImplicitly;
	if (hasRestrictedAccess())
		method.modifiers |= ExtraCompilerModifiers.AccRestrictedAccess;

	AbstractMethodDeclaration methodDecl = method.sourceMethod();
	if (methodDecl == null) return null; // method could not be resolved in previous iteration

	TypeParameter[] typeParameters = methodDecl.typeParameters();
	if (JavaScriptCore.IS_ECMASCRIPT4)
	{
		if (typeParameters != null) {
			methodDecl.scope.connectTypeVariables(typeParameters, true);
		// 	Perform deferred bound checks for type variables (only done after type variable hierarchy is connected)
			for (int i = 0, paramLength = typeParameters.length; i < paramLength; i++)
				typeParameters[i].checkBounds(methodDecl.scope);
		}
		TypeReference[] exceptionTypes = methodDecl.thrownExceptions;
		if (exceptionTypes != null) {
			int size = exceptionTypes.length;
			method.thrownExceptions = new ReferenceBinding[size];
			int count = 0;
			ReferenceBinding resolvedExceptionType;
			for (int i = 0; i < size; i++) {
				resolvedExceptionType = (ReferenceBinding) exceptionTypes[i].resolveType(methodDecl.scope, true /* check bounds*/);
				if (resolvedExceptionType == null)
					continue;
				if (resolvedExceptionType.isBoundParameterizedType()) {
					methodDecl.scope.problemReporter().invalidParameterizedExceptionType(resolvedExceptionType, exceptionTypes[i]);
					continue;
				}
				if (resolvedExceptionType.findSuperTypeErasingTo(TypeIds.T_JavaLangThrowable, true) == null) {
					methodDecl.scope.problemReporter().cannotThrowType(exceptionTypes[i], resolvedExceptionType);
					continue;
				}
				if ((resolvedExceptionType.modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
					method.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
				method.thrownExceptions[count++] = resolvedExceptionType;
			}
			if (count < size)
				System.arraycopy(method.thrownExceptions, 0, method.thrownExceptions = new ReferenceBinding[count], 0, count);
		}
	}

	boolean foundArgProblem = false;
	Argument[] arguments = methodDecl.arguments;
	if (arguments != null) {
		int size = arguments.length;
		method.parameters = Binding.NO_PARAMETERS;
		TypeBinding[] newParameters = new TypeBinding[size];
		for (int i = 0; i < size; i++) {
			Argument arg = arguments[i];
			TypeBinding parameterType = TypeBinding.UNKNOWN;
			if (arg.type!=null) parameterType = arg.type.resolveType(methodDecl.scope, true /* check bounds*/) ;
			else if (arg.inferredType!=null) parameterType = arg.inferredType.resolveType(methodDecl.scope, arg);
			
			
			if (parameterType == null) {
//				foundArgProblem = true;
				parameterType=TypeBinding.ANY;
			} 
//			else 
			if (parameterType == TypeBinding.VOID) {
				methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg);
				foundArgProblem = true;
			} else {
				TypeBinding leafType = parameterType.leafComponentType();
			    if (leafType instanceof ReferenceBinding && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
					method.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
				newParameters[i] = parameterType;
				arg.binding = new LocalVariableBinding(arg, parameterType, arg.modifiers, true);
			}
		}
		// only assign parameters if no problems are found
		if (!foundArgProblem)
			method.parameters = newParameters;
	}

	boolean foundReturnTypeProblem = false;
	if (!method.isConstructor()) {
		TypeReference returnType = methodDecl instanceof MethodDeclaration
			? ((MethodDeclaration) methodDecl).returnType
			: null;
		if (returnType == null && !(methodDecl instanceof MethodDeclaration)) {
			methodDecl.scope.problemReporter().missingReturnType(methodDecl);
			method.returnType = null;
			foundReturnTypeProblem = true;
		} else {
		    TypeBinding methodType = (returnType!=null )? returnType.resolveType(methodDecl.scope, true /* check bounds*/) : null;
		    if (methodType==null)
		    	methodType=(methodDecl.inferredType!=null)?methodDecl.inferredType.resolveType(methodDecl.scope, methodDecl):TypeBinding.UNKNOWN;
			if (methodType == null) {
				foundReturnTypeProblem = true;
			} else if (methodType.isArrayType() && ((ArrayBinding) methodType).leafComponentType == TypeBinding.VOID) {
				methodDecl.scope.problemReporter().returnTypeCannotBeVoidArray((MethodDeclaration) methodDecl);
				foundReturnTypeProblem = true;
			} else {
				method.returnType = methodType;
				TypeBinding leafType = methodType.leafComponentType();
				if (leafType instanceof ReferenceBinding && (((ReferenceBinding) leafType).modifiers & ExtraCompilerModifiers.AccGenericSignature) != 0)
					method.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
			}
		}
	}
	if (foundArgProblem) {
		methodDecl.binding = null;
		method.parameters = Binding.NO_PARAMETERS; // see 107004
		// nullify type parameter bindings as well as they have a backpointer to the method binding
		// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=81134)
		if (JavaScriptCore.IS_ECMASCRIPT4)
		{
			if (typeParameters != null)
				for (int i = 0, length = typeParameters.length; i < length; i++)
					typeParameters[i].binding = null;
		}
		return null;
	}
	if (foundReturnTypeProblem)
		return method; // but its still unresolved with a null return type & is still connected to its method declaration

	method.modifiers &= ~ExtraCompilerModifiers.AccUnresolved;
	return method;
}
public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) {
	if (forceInitialization)
		binding.getAnnotationTagBits(); // ensure annotations are up to date
	return super.retrieveAnnotationHolder(binding, false);
}
public void setFields(FieldBinding[] fields) {
//	if (this.nextType!=null)
//		throw new UnimplementedException("should not get here"); //$NON-NLS-1$

	this.fields = fields;
}
public void setMethods(MethodBinding[] methods) {
//	if (this.nextType!=null)
//		throw new UnimplementedException("should not get here"); //$NON-NLS-1$
	this.methods = methods;
}
public  int sourceEnd() {
	if (this.classScope.referenceContext!=null)
		return this.classScope.referenceContext.sourceEnd;
	else
		return this.classScope.inferredType.sourceEnd;
}
public  int sourceStart() {
	if (this.classScope.referenceContext!=null)
		return this.classScope.referenceContext.sourceStart;
	else
		return this.classScope.inferredType.sourceStart;
}
SimpleLookupTable storedAnnotations(boolean forceInitialize) {
	if (forceInitialize && this.storedAnnotations == null && this.scope != null) { // scope null when no annotation cached, and type got processed fully (159631)
		this.scope.referenceCompilationUnit().compilationResult.hasAnnotations = true;
		if (!this.scope.environment().globalOptions.storeAnnotations)
			return null; // not supported during this compile
		this.storedAnnotations = new SimpleLookupTable(3);
	}
	return this.storedAnnotations;
}
public ReferenceBinding superclass() {
	if (this.nextType==null)
		return this.superclass;
	if (this.superclass!=null && this.superclass.id!=TypeIds.T_JavaLangObject)
		return this.superclass;
	return this.nextType.superclass();

}
public ReferenceBinding[] superInterfaces() {
	return this.superInterfaces;
}
// TODO (philippe) could be a performance issue since some senders are building the list just to count them
public SyntheticMethodBinding[] syntheticMethods() {

	if (this.synthetics == null || this.synthetics[SourceTypeBinding.METHOD_EMUL] == null || this.synthetics[SourceTypeBinding.METHOD_EMUL].size() == 0) return null;

	// difficult to compute size up front because of the embedded arrays so assume there is only 1
	int index = 0;
	SyntheticMethodBinding[] bindings = new SyntheticMethodBinding[1];
	Iterator fieldsOrMethods = this.synthetics[SourceTypeBinding.METHOD_EMUL].keySet().iterator();
	while (fieldsOrMethods.hasNext()) {

		Object fieldOrMethod = fieldsOrMethods.next();

		if (fieldOrMethod instanceof MethodBinding) {

			SyntheticMethodBinding[] methodAccessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(fieldOrMethod);
			int numberOfAccessors = 0;
			if (methodAccessors[0] != null) numberOfAccessors++;
			if (methodAccessors[1] != null) numberOfAccessors++;
			if (index + numberOfAccessors > bindings.length)
				System.arraycopy(bindings, 0, (bindings = new SyntheticMethodBinding[index + numberOfAccessors]), 0, index);
			if (methodAccessors[0] != null)
				bindings[index++] = methodAccessors[0]; // super access
			if (methodAccessors[1] != null)
				bindings[index++] = methodAccessors[1]; // normal access or bridge

		} else {

			SyntheticMethodBinding[] fieldAccessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(fieldOrMethod);
			int numberOfAccessors = 0;
			if (fieldAccessors[0] != null) numberOfAccessors++;
			if (fieldAccessors[1] != null) numberOfAccessors++;
			if (index + numberOfAccessors > bindings.length)
				System.arraycopy(bindings, 0, (bindings = new SyntheticMethodBinding[index + numberOfAccessors]), 0, index);
			if (fieldAccessors[0] != null)
				bindings[index++] = fieldAccessors[0]; // read access
			if (fieldAccessors[1] != null)
				bindings[index++] = fieldAccessors[1]; // write access
		}
	}

	// sort them in according to their own indexes
	int length;
	SyntheticMethodBinding[] sortedBindings = new SyntheticMethodBinding[length = bindings.length];
	for (int i = 0; i < length; i++){
		SyntheticMethodBinding binding = bindings[i];
		sortedBindings[binding.index] = binding;
	}
	return sortedBindings;
}
/**
 * Answer the collection of synthetic fields to append into the classfile
 */
public FieldBinding[] syntheticFields() {

	if (this.synthetics == null) return null;

	int fieldSize = this.synthetics[SourceTypeBinding.FIELD_EMUL] == null ? 0 : this.synthetics[SourceTypeBinding.FIELD_EMUL].size();
	int literalSize = this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] == null ? 0 :this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].size();
	int totalSize = fieldSize + literalSize;
	if (totalSize == 0) return null;
	FieldBinding[] bindings = new FieldBinding[totalSize];

	// add innerclass synthetics
	if (this.synthetics[SourceTypeBinding.FIELD_EMUL] != null){
		Iterator elements = this.synthetics[SourceTypeBinding.FIELD_EMUL].values().iterator();
		for (int i = 0; i < fieldSize; i++) {
			SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.next();
			bindings[synthBinding.index] = synthBinding;
		}
	}
	// add class literal synthetics
	if (this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] != null){
		Iterator elements = this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL].values().iterator();
		for (int i = 0; i < literalSize; i++) {
			SyntheticFieldBinding synthBinding = (SyntheticFieldBinding) elements.next();
			bindings[fieldSize+synthBinding.index] = synthBinding;
		}
	}
	return bindings;
}
public String toString() {
    StringBuffer buffer = new StringBuffer(30);
    buffer.append("(id="); //$NON-NLS-1$
    if (this.id == TypeIds.NoId)
        buffer.append("NoId"); //$NON-NLS-1$
    else
        buffer.append(this.id);
    buffer.append(")\n"); //$NON-NLS-1$
	if (isDeprecated()) buffer.append("deprecated "); //$NON-NLS-1$
	if (isPublic()) buffer.append("public "); //$NON-NLS-1$
	if (isProtected()) buffer.append("protected "); //$NON-NLS-1$
	if (isPrivate()) buffer.append("private "); //$NON-NLS-1$
	if (isAbstract() && isClass()) buffer.append("abstract "); //$NON-NLS-1$
	if (isStatic() && isNestedType()) buffer.append("static "); //$NON-NLS-1$
	if (isFinal()) buffer.append("final "); //$NON-NLS-1$

	if (isEnum()) buffer.append("enum "); //$NON-NLS-1$
	else if (isAnnotationType()) buffer.append("@interface "); //$NON-NLS-1$
	else if (isClass()) buffer.append("class "); //$NON-NLS-1$
	else buffer.append("interface "); //$NON-NLS-1$
	buffer.append((this.compoundName != null) ? CharOperation.toString(this.compoundName) : "UNNAMED TYPE"); //$NON-NLS-1$

	if (this.typeVariables == null) {
		buffer.append("<NULL TYPE VARIABLES>"); //$NON-NLS-1$
	} else if (this.typeVariables != Binding.NO_TYPE_VARIABLES) {
		buffer.append("\n\t<"); //$NON-NLS-1$
		for (int i = 0, length = this.typeVariables.length; i < length; i++) {
			if (i  > 0)
				buffer.append(", "); //$NON-NLS-1$
			buffer.append((this.typeVariables[i] != null) ? this.typeVariables[i].toString() : "NULL TYPE VARIABLE"); //$NON-NLS-1$
		}
		buffer.append(">"); //$NON-NLS-1$
	}
	buffer.append("\n\textends "); //$NON-NLS-1$
	buffer.append((this.superclass != null) ? this.superclass.debugName() : "NULL TYPE"); //$NON-NLS-1$

	if (this.superInterfaces != null) {
		if (this.superInterfaces != Binding.NO_SUPERINTERFACES) {
			buffer.append("\n\timplements : "); //$NON-NLS-1$
			for (int i = 0, length = this.superInterfaces.length; i < length; i++) {
				if (i  > 0)
					buffer.append(", "); //$NON-NLS-1$
				buffer.append((this.superInterfaces[i] != null) ? this.superInterfaces[i].debugName() : "NULL TYPE"); //$NON-NLS-1$
			}
		}
	} else {
		buffer.append("NULL SUPERINTERFACES"); //$NON-NLS-1$
	}

	if (enclosingType() != null) {
		buffer.append("\n\tenclosing type : "); //$NON-NLS-1$
		buffer.append(enclosingType().debugName());
	}

	if (this.fields != null) {
		if (this.fields != Binding.NO_FIELDS) {
			buffer.append("\n/*   fields   */"); //$NON-NLS-1$
			for (int i = 0, length = this.fields.length; i < length; i++)
			    buffer.append('\n').append((this.fields[i] != null) ? this.fields[i].toString() : "NULL FIELD"); //$NON-NLS-1$
		}
	} else {
		buffer.append("NULL FIELDS"); //$NON-NLS-1$
	}

	if (this.methods != null) {
		if (this.methods != Binding.NO_METHODS) {
			buffer.append("\n/*   methods   */"); //$NON-NLS-1$
			for (int i = 0, length = this.methods.length; i < length; i++)
				buffer.append('\n').append((this.methods[i] != null) ? this.methods[i].toString() : "NULL METHOD"); //$NON-NLS-1$
		}
	} else {
		buffer.append("NULL METHODS"); //$NON-NLS-1$
	}

	if (this.memberTypes != null) {
		if (this.memberTypes != Binding.NO_MEMBER_TYPES) {
			buffer.append("\n/*   members   */"); //$NON-NLS-1$
			for (int i = 0, length = this.memberTypes.length; i < length; i++)
				buffer.append('\n').append((this.memberTypes[i] != null) ? this.memberTypes[i].toString() : "NULL TYPE"); //$NON-NLS-1$
		}
	} else {
		buffer.append("NULL MEMBER TYPES"); //$NON-NLS-1$
	}

	buffer.append("\n\n"); //$NON-NLS-1$
	return buffer.toString();
}
public TypeVariableBinding[] typeVariables() {
	return this.typeVariables;
}
void verifyMethods(MethodVerifier verifier) {
	verifier.verify(this);

//	for (int i = this.memberTypes.length; --i >= 0;)
//		 ((SourceTypeBinding) this.memberTypes[i]).verifyMethods(verifier);
}

public AbstractMethodDeclaration sourceMethod(MethodBinding binding) {
	if (this.classScope==null)
		return null;
	InferredType inferredType=this.classScope.inferredType;
	InferredMethod inferredMethod = inferredType.findMethod(binding.selector, null);
	if (inferredMethod!=null)
		return (AbstractMethodDeclaration) inferredMethod.getFunctionDeclaration();
//	AbstractMethodDeclaration[] methods = classScope.referenceContext.methods;
//	for (int i = methods.length; --i >= 0;)
//		if (binding == methods[i].binding)
//			return methods[i];
	return null;
}

public void addMethod(MethodBinding binding)
{
	int length=this.methods.length;
	System.arraycopy(this.methods, 0, this.methods=new MethodBinding[length+1], 0, length);
	this.methods[length]=binding;

}

public void cleanup()
{
this.scope=null;
this.classScope=null;
// clean up should be called for each compilation unit, so it shouldnt be necessary to chain the cleanups
//if (this.nextType!=null)
//	this.nextType.cleanup();
}


public boolean contains(ReferenceBinding binding)
{
	if (binding==this)
		return true;
	if (this.nextType!=null)
		return this.nextType.contains(binding);
	return false;
}


public void addNextType(SourceTypeBinding type) {
	SourceTypeBinding binding=this;
	while (binding.nextType!=null)
		binding=binding.nextType;
	binding.nextType=type;
	
}

}
