/*******************************************************************************
 * 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.jdt.internal.compiler.lookup;

import com.google.gwt.dev.util.collect.HashMap;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.Util;

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

public class SourceTypeBinding extends ReferenceBinding {
  public ReferenceBinding superclass;
  public ReferenceBinding[] superInterfaces;
  private FieldBinding[] fields;
  private MethodBinding[] methods;
  public ReferenceBinding[] memberTypes;
  public TypeVariableBinding[] typeVariables;

  public ClassScope scope;

  // Synthetics are separated into 5 categories: methods, super methods, fields, class literals, changed declaring type bindings and bridge methods
  // if a new category is added, also increment MAX_SYNTHETICS
  private final static int METHOD_EMUL = 0;
  private final static int FIELD_EMUL = 1;
  private final static int CLASS_LITERAL_EMUL = 2;
  private final static int RECEIVER_TYPE_EMUL = 3;
  
  private final static int MAX_SYNTHETICS = 4;

  HashMap[] synthetics;
  char[] genericReferenceTypeSignature;

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

public SourceTypeBinding(char[][] compoundName, PackageBinding fPackage, ClassScope scope) {
  this.compoundName = compoundName;
  this.fPackage = fPackage;
  this.fileName = scope.referenceCompilationUnit().getFileName();
  this.modifiers = scope.referenceContext.modifiers;
  this.sourceName = scope.referenceContext.name;
  this.scope = scope;

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

  computeId();
}

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) {
      MethodBinding[] 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()) {
          MethodBinding[] superMethods = superType.methods();
          nextAbstractMethod: for (int m = superMethods.length; --m >= 0;) {
            MethodBinding method = superMethods[m];
            // explicitly implemented ?
            if (implementsMethod(method))
              continue nextAbstractMethod;
            if (defaultAbstractsCount == 0) {
              defaultAbstracts = new MethodBinding[5];
            } else {
              // already added as default abstract ?
              for (int k = 0; k < defaultAbstractsCount; k++) {
                MethodBinding alreadyAdded = defaultAbstracts[k];
                if (CharOperation.equals(alreadyAdded.selector, method.selector) && alreadyAdded.areParametersEqual(method))
                  continue nextAbstractMethod;
              }
            }
            MethodBinding defaultAbstract = new MethodBinding(
                method.modifiers | ExtraCompilerModifiers.AccDefaultAbstract | ClassFileConstants.AccSynthetic,
                method.selector,
                method.returnType,
                method.parameters,
                method.thrownExceptions,
                this);
            if (defaultAbstractsCount == defaultAbstracts.length)
              System.arraycopy(defaultAbstracts, 0, defaultAbstracts = new MethodBinding[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 MethodBinding[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[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
    this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap();
  
  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.scope.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[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
    this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap();

  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.scope.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[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] == null)
    this.synthetics[SourceTypeBinding.CLASS_LITERAL_EMUL] = new HashMap();

  // 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[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
    this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap();

  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.scope.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[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
    this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap();

  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.scope.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[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
    this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap();

  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[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
    this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap();

  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[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.FIELD_EMUL] == null)
    this.synthetics[SourceTypeBinding.FIELD_EMUL] = new HashMap();

  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.scope.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[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
    this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap();

  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[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null)
    this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap();

  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[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) {
    this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap();
  } 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;
}
boolean areFieldsInitialized() {
  return this.fields != Binding.UNINITIALIZED_FIELDS;
}
boolean areMethodsInitialized() {
  return this.methods != Binding.UNINITIALIZED_METHODS;
}
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)
    return this.fields; 

  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;
  return this.fields;
}
/**
 * @see org.eclipse.jdt.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.jdt.internal.compiler.lookup.Binding#getAnnotationTagBits()
 */
public long getAnnotationTagBits() {
  if ((this.tagBits & TagBits.AnnotationResolved) == 0 && this.scope != null) {
    TypeDeclaration typeDecl = this.scope.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;
}
// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
public MethodBinding getExactConstructor(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 null;
}

//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.
public MethodBinding getExactMethod(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])
              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(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
          }
        }
      }
      nextMethod: for (int imethod = start; imethod <= end; imethod++) {
        MethodBinding 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 (isInterface()) {
       if (this.superInterfaces.length == 1) {
        if (refScope != null)
          refScope.recordTypeReference(this.superInterfaces[0]);
        return this.superInterfaces[0].getExactMethod(selector, argumentTypes, refScope);
       }
    } else if (this.superclass != null) {
      if (refScope != null)
        refScope.recordTypeReference(this.superclass);
      return this.superclass.getExactMethod(selector, argumentTypes, refScope);
    }
  }
  return null;
}

//NOTE: the type of a field of a source type is resolved when needed
public FieldBinding getField(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;
}

// NOTE: the return type, arg & exception types of each method of a source type are resolved when needed
public MethodBinding[] getMethods(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.findSuperTypeOriginatingFrom(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.jdt.internal.compiler.lookup.Binding#initializeDeprecatedAnnotationTagBits()
 */
public void initializeDeprecatedAnnotationTagBits() {
  if ((this.tagBits & TagBits.DeprecatedAnnotationResolved) == 0) {
    TypeDeclaration typeDecl = this.scope.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;
    }
  }
}

// ensure the receiver knows its hierarchy & fields/methods so static imports can be resolved correctly
// see bug 230026
void initializeForStaticImports() {
  if (this.scope == null) return; // already initialized

  if (this.superInterfaces == null)
    this.scope.connectTypeHierarchy();
  this.scope.buildFields();
  this.scope.buildMethods();
}

/**
 * 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 :
    case Binding.INTERSECTION_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() {
  return this.memberTypes;
}
public FieldBinding getUpdatedFieldBinding(FieldBinding targetField, ReferenceBinding newDeclaringClass) {
  if (this.synthetics == null)
    this.synthetics = new HashMap[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] == null)
    this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] = new HashMap();

  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[MAX_SYNTHETICS];
  if (this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] == null)
    this.synthetics[SourceTypeBinding.RECEIVER_TYPE_EMUL] = new HashMap();

  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);
    methodMap.put(newDeclaringClass, updatedMethod);
  }
  return updatedMethod;
}
public boolean hasMemberTypes() {
    return this.memberTypes.length > 0;
}
// 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)
    return this.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;
  }

  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.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, method.areParametersEqual(method2));
            }
            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, method.areParametersEqual(method2));
          }
          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;
  }   
  return this.methods;
}
private FieldBinding resolveTypeFor(FieldBinding field) {
  if ((field.modifiers & ExtraCompilerModifiers.AccUnresolved) == 0)
    return field;

  if (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;
  FieldDeclaration[] fieldDecls = this.scope.referenceContext.fields;
  for (int f = 0, length = fieldDecls.length; f < length; f++) {
    if (fieldDecls[f].binding != field)
      continue;

      MethodScope initializationScope = field.isStatic() 
        ? this.scope.referenceContext.staticInitializerScope 
        : this.scope.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, false /*do not force conversion of enclosing types*/) // 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;
        }
        if ((fieldType.tagBits & TagBits.HasMissingType) != 0) {
          field.tagBits |= TagBits.HasMissingType;
        }           
        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.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 (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.findSuperTypeOriginatingFrom(TypeIds.T_JavaLangThrowable, true) == null) {
        if (resolvedExceptionType.isValidBinding()) {
          methodDecl.scope.problemReporter().cannotThrowType(exceptionTypes[i], resolvedExceptionType);
          continue;
        }
      }
      if ((resolvedExceptionType.tagBits & TagBits.HasMissingType) != 0) {
        method.tagBits |= TagBits.HasMissingType;
      }           
      method.modifiers |= (resolvedExceptionType.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];
      if (arg.annotations != null) {
        method.tagBits |= TagBits.HasParameterAnnotations;
      }
      TypeBinding parameterType = arg.type.resolveType(methodDecl.scope, true /* check bounds*/);
      if (parameterType == null) {
        foundArgProblem = true;
      } else if (parameterType == TypeBinding.VOID) {
        methodDecl.scope.problemReporter().argumentTypeCannotBeVoid(this, methodDecl, arg);
        foundArgProblem = true;
      } else {
        if ((parameterType.tagBits & TagBits.HasMissingType) != 0) {
          method.tagBits |= TagBits.HasMissingType;
        }           
        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.scope.problemReporter().missingReturnType(methodDecl);
      method.returnType = null;
      foundReturnTypeProblem = true;
    } else {
      TypeBinding methodType = returnType.resolveType(methodDecl.scope, true /* check bounds*/);
      if (methodType == null) {
        foundReturnTypeProblem = true;
      } else if (methodType.isArrayType() && ((ArrayBinding) methodType).leafComponentType == TypeBinding.VOID) {
        methodDecl.scope.problemReporter().returnTypeCannotBeVoidArray((MethodDeclaration) methodDecl);
        foundReturnTypeProblem = true;
      } else {
        if ((methodType.tagBits & TagBits.HasMissingType) != 0) {
          method.tagBits |= TagBits.HasMissingType;
        }         
        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 (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) {
  this.fields = fields;
}
public void setMethods(MethodBinding[] methods) {
  this.methods = methods;
}
public final int sourceEnd() {
  return this.scope.referenceContext.sourceEnd;
}
public final int sourceStart() {
  return this.scope.referenceContext.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() {
  return this.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("<"); //$NON-NLS-1$
    for (int i = 0, length = this.typeVariables.length; i < length; i++) {
      if (i  > 0) buffer.append(", "); //$NON-NLS-1$
      if (this.typeVariables[i] == null) {
        buffer.append("NULL TYPE VARIABLE"); //$NON-NLS-1$
        continue;
      }
      char[] varChars = this.typeVariables[i].toString().toCharArray();
      buffer.append(varChars, 1, varChars.length - 2);
    }
    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);
}
}
