/*
   * Creates the super class handle of the given type.
   * Returns null if the type has no super class.
   * Adds the simple name to the hierarchy missing types if the class is not found and returns null.
   */
  private IType findSuperClass(IGenericType type, ReferenceBinding typeBinding) {
    ReferenceBinding superBinding = typeBinding.superclass();

    if (superBinding != null) {
      superBinding = (ReferenceBinding) superBinding.erasure();
      if (typeBinding.isHierarchyInconsistent()) {
        if (superBinding.problemId() == ProblemReasons.NotFound) {
          this.hasMissingSuperClass = true;
          this.builder.hierarchy.missingTypes.add(
              new String(superBinding.sourceName)); // note: this could be Map$Entry
          return null;
        } else if ((superBinding.id == TypeIds.T_JavaLangObject)) {
          char[] superclassName;
          char separator;
          if (type instanceof IBinaryType) {
            superclassName = ((IBinaryType) type).getSuperclassName();
            separator = '/';
          } else if (type instanceof ISourceType) {
            superclassName = ((ISourceType) type).getSuperclassName();
            separator = '.';
          } else if (type instanceof HierarchyType) {
            superclassName = ((HierarchyType) type).superclassName;
            separator = '.';
          } else {
            return null;
          }

          if (superclassName
              != null) { // check whether subclass of Object due to broken hierarchy (as opposed to
                         // explicitly extending it)
            int lastSeparator = CharOperation.lastIndexOf(separator, superclassName);
            char[] simpleName =
                lastSeparator == -1
                    ? superclassName
                    : CharOperation.subarray(
                        superclassName, lastSeparator + 1, superclassName.length);
            if (!CharOperation.equals(simpleName, TypeConstants.OBJECT)) {
              this.hasMissingSuperClass = true;
              this.builder.hierarchy.missingTypes.add(new String(simpleName));
              return null;
            }
          }
        }
      }
      for (int t = this.typeIndex; t >= 0; t--) {
        if (TypeBinding.equalsEquals(this.typeBindings[t], superBinding)) {
          return this.builder.getHandle(this.typeModels[t], superBinding);
        }
      }
    }
    return null;
  }
  private Binding findSingleStaticImport(char[][] compoundName, int mask) {
    Binding binding = findImport(compoundName, compoundName.length - 1);
    if (!binding.isValidBinding()) return binding;

    char[] name = compoundName[compoundName.length - 1];
    if (binding instanceof PackageBinding) {
      Binding temp = ((PackageBinding) binding).getTypeOrPackage(name);
      if (temp != null
          && temp
              instanceof
              ReferenceBinding) // must resolve to a member type or field, not a top level type
      return new ProblemReferenceBinding(
            compoundName, (ReferenceBinding) temp, ProblemReasons.InvalidTypeForStaticImport);
      return binding; // cannot be a package, error is caught in sender
    }

    // look to see if its a static field first
    ReferenceBinding type = (ReferenceBinding) binding;
    FieldBinding field = (mask & Binding.FIELD) != 0 ? findField(type, name, null, true) : null;
    if (field != null) {
      if (field.problemId() == ProblemReasons.Ambiguous
          && ((ProblemFieldBinding) field).closestMatch.isStatic())
        return field; // keep the ambiguous field instead of a possible method match
      if (field.isValidBinding() && field.isStatic() && field.canBeSeenBy(type, null, this))
        return field;
    }

    // look to see if there is a static method with the same selector
    MethodBinding method = (mask & Binding.METHOD) != 0 ? findStaticMethod(type, name) : null;
    if (method != null) return method;

    type = findMemberType(name, type);
    if (type == null || !type.isStatic()) {
      if (field != null && !field.isValidBinding() && field.problemId() != ProblemReasons.NotFound)
        return field;
      return new ProblemReferenceBinding(compoundName, type, ProblemReasons.NotFound);
    }
    if (type.isValidBinding() && !type.canBeSeenBy(this.fPackage))
      return new ProblemReferenceBinding(compoundName, type, ProblemReasons.NotVisible);
    if (type.problemId() == ProblemReasons.NotVisible) // ensure compoundName is correct
    return new ProblemReferenceBinding(
          compoundName, ((ProblemReferenceBinding) type).closestMatch, ProblemReasons.NotVisible);
    return type;
  }
  /**
   * Checks for duplicates. If all ok, records the importBinding returns -1 when this import is
   * flagged as duplicate.
   *
   * @param importBinding
   * @param typesBySimpleNames
   * @param importReference
   * @param compoundName
   * @return -1 when this import is flagged as duplicate, importPtr otherwise.
   */
  private int checkAndRecordImportBinding(
      Binding importBinding,
      HashtableOfType typesBySimpleNames,
      ImportReference importReference,
      char[][] compoundName) {
    ReferenceBinding conflictingType = null;
    if (importBinding instanceof MethodBinding) {
      conflictingType = (ReferenceBinding) getType(compoundName, compoundName.length);
      if (!conflictingType.isValidBinding()
          || (importReference.isStatic() && !conflictingType.isStatic())) conflictingType = null;
    }
    // collisions between an imported static field & a type should be checked according to spec...
    // but currently not by javac
    final char[] name = compoundName[compoundName.length - 1];
    if (importBinding instanceof ReferenceBinding || conflictingType != null) {
      ReferenceBinding referenceBinding =
          conflictingType == null ? (ReferenceBinding) importBinding : conflictingType;
      ReferenceBinding typeToCheck =
          referenceBinding.problemId() == ProblemReasons.Ambiguous
              ? ((ProblemReferenceBinding) referenceBinding).closestMatch
              : referenceBinding;
      if (importReference.isTypeUseDeprecated(typeToCheck, this))
        problemReporter().deprecatedType(typeToCheck, importReference);

      ReferenceBinding existingType = typesBySimpleNames.get(name);
      if (existingType != null) {
        // duplicate test above should have caught this case, but make sure
        if (TypeBinding.equalsEquals(existingType, referenceBinding)) {
          // https://bugs.eclipse.org/bugs/show_bug.cgi?id=302865
          // Check all resolved imports to see if this import qualifies as a duplicate
          for (int j = 0; j < this.importPtr; j++) {
            ImportBinding resolved = this.tempImports[j];
            if (resolved instanceof ImportConflictBinding) {
              ImportConflictBinding importConflictBinding = (ImportConflictBinding) resolved;
              if (TypeBinding.equalsEquals(
                  importConflictBinding.conflictingTypeBinding, referenceBinding)) {
                if (!importReference.isStatic()) {
                  // resolved is implicitly static
                  problemReporter().duplicateImport(importReference);
                  recordImportBinding(
                      new ImportBinding(compoundName, false, importBinding, importReference));
                }
              }
            } else if (resolved.resolvedImport == referenceBinding) {
              if (importReference.isStatic() != resolved.isStatic()) {
                problemReporter().duplicateImport(importReference);
                recordImportBinding(
                    new ImportBinding(compoundName, false, importBinding, importReference));
              }
            }
          }
          return -1;
        }
        // either the type collides with a top level type or another imported type
        for (int j = 0, length = this.topLevelTypes.length; j < length; j++) {
          if (CharOperation.equals(this.topLevelTypes[j].sourceName, existingType.sourceName)) {
            problemReporter().conflictingImport(importReference);
            return -1;
          }
        }
        if (importReference.isStatic()
            && importBinding instanceof ReferenceBinding
            && compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8) {
          // 7.5.3 says nothing about collision of single static imports and JDK8 tolerates them,
          // though use is flagged.
          for (int j = 0; j < this.importPtr; j++) {
            ImportBinding resolved = this.tempImports[j];
            if (resolved.isStatic()
                && resolved.resolvedImport instanceof ReferenceBinding
                && importBinding != resolved.resolvedImport) {
              if (CharOperation.equals(
                  name, resolved.compoundName[resolved.compoundName.length - 1])) {
                ReferenceBinding type = (ReferenceBinding) resolved.resolvedImport;
                resolved.resolvedImport =
                    new ProblemReferenceBinding(
                        new char[][] {name}, type, ProblemReasons.Ambiguous);
                return -1;
              }
            }
          }
        }
        problemReporter().duplicateImport(importReference);
        return -1;
      }
      typesBySimpleNames.put(name, referenceBinding);
    } else if (importBinding instanceof FieldBinding) {
      for (int j = 0; j < this.importPtr; j++) {
        ImportBinding resolved = this.tempImports[j];
        // find other static fields with the same name
        if (resolved.isStatic()
            && resolved.resolvedImport instanceof FieldBinding
            && importBinding != resolved.resolvedImport) {
          if (CharOperation.equals(name, resolved.compoundName[resolved.compoundName.length - 1])) {
            if (compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8) {
              // 7.5.3 says nothing about collision of single static imports and JDK8 tolerates
              // them, though use is flagged.
              FieldBinding field = (FieldBinding) resolved.resolvedImport;
              resolved.resolvedImport =
                  new ProblemFieldBinding(
                      field, field.declaringClass, name, ProblemReasons.Ambiguous);
              return -1;
            } else {
              problemReporter().duplicateImport(importReference);
              return -1;
            }
          }
        }
      }
    }
    if (conflictingType == null) {
      recordImportBinding(new ImportBinding(compoundName, false, importBinding, importReference));
    } else {
      recordImportBinding(
          new ImportConflictBinding(compoundName, importBinding, conflictingType, importReference));
    }
    return this.importPtr;
  }