private Binding findImport(char[][] compoundName, int length) {
    recordQualifiedReference(compoundName);

    Binding binding = this.environment.getTopLevelPackage(compoundName[0]);
    int i = 1;
    foundNothingOrType:
    if (binding != null) {
      PackageBinding packageBinding = (PackageBinding) binding;
      while (i < length) {
        binding = packageBinding.getTypeOrPackage(compoundName[i++]);
        if (binding == null || !binding.isValidBinding()) {
          binding = null;
          break foundNothingOrType;
        }
        if (!(binding instanceof PackageBinding)) break foundNothingOrType;

        packageBinding = (PackageBinding) binding;
      }
      return packageBinding;
    }

    ReferenceBinding type;
    if (binding == null) {
      if (compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
        return new ProblemReferenceBinding(
            CharOperation.subarray(compoundName, 0, i), null, ProblemReasons.NotFound);
      type =
          findType(
              compoundName[0], this.environment.defaultPackage, this.environment.defaultPackage);
      if (type == null || !type.isValidBinding())
        return new ProblemReferenceBinding(
            CharOperation.subarray(compoundName, 0, i), null, ProblemReasons.NotFound);
      i = 1; // reset to look for member types inside the default package type
    } else {
      type = (ReferenceBinding) binding;
    }

    while (i < length) {
      type =
          (ReferenceBinding)
              this.environment.convertToRawType(
                  type, false /*do not force conversion of enclosing types*/); // type imports are
      // necessarily raw for all
      // except last
      if (!type.canBeSeenBy(this.fPackage))
        return new ProblemReferenceBinding(
            CharOperation.subarray(compoundName, 0, i), type, ProblemReasons.NotVisible);

      char[] name = compoundName[i++];
      // does not look for inherited member types on purpose, only immediate members
      type = type.getMemberType(name);
      if (type == null)
        return new ProblemReferenceBinding(
            CharOperation.subarray(compoundName, 0, i), null, ProblemReasons.NotFound);
    }
    if (!type.canBeSeenBy(this.fPackage))
      return new ProblemReferenceBinding(compoundName, type, ProblemReasons.NotVisible);
    return type;
  }
  // helper method for findSingleStaticImport()
  private MethodBinding findStaticMethod(ReferenceBinding currentType, char[] selector) {
    if (!currentType.canBeSeenBy(this)) return null;

    do {
      currentType.initializeForStaticImports();
      MethodBinding[] methods = currentType.getMethods(selector);
      if (methods != Binding.NO_METHODS) {
        for (int i = methods.length; --i >= 0; ) {
          MethodBinding method = methods[i];
          if (method.isStatic() && method.canBeSeenBy(this.fPackage)) return method;
        }
      }
    } while ((currentType = currentType.superclass()) != null);
    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;
  }