/** Method entries are encoded as selector '/' Arity: e.g. 'foo/0' */
 public static char[] createIndexKey(char[] selector, int argCount) {
   char[] countChars =
       argCount < 10
           ? COUNTS[argCount]
           : ("/" + String.valueOf(argCount)).toCharArray(); // $NON-NLS-1$
   return CharOperation.concat(selector, countChars);
 }
  private void acceptName(char[] name) {
    // the null check is added to fix bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=166570
    if (name == null) return;

    if (!CharOperation.prefixEquals(
            this.completionEngine.completionToken, name, false /* ignore case */)
        && !(this.completionEngine.options.camelCaseMatch
            && CharOperation.camelCaseMatch(this.completionEngine.completionToken, name))) return;

    if (acceptedNames.includes(name)) return;

    this.acceptedNames.add(name);

    // accept result
    this.requestor.acceptName(name);
  }
  EntryResult[] queryIn(Index index) throws IOException {
    char[] key = this.selector; // can be null
    int matchRule = getMatchRule();

    switch (getMatchMode()) {
      case R_EXACT_MATCH:
        if (this.isCamelCase) break;
        if (this.selector != null && this.parameterCount >= 0 && !this.varargs)
          key = createIndexKey(this.selector, this.parameterCount);
        else { // do a prefix query with the selector
          matchRule &= ~R_EXACT_MATCH;
          matchRule |= R_PREFIX_MATCH;
        }
        break;
      case R_PREFIX_MATCH:
        // do a prefix query with the selector
        break;
      case R_PATTERN_MATCH:
        if (this.parameterCount >= 0 && !this.varargs)
          key =
              createIndexKey(this.selector == null ? ONE_STAR : this.selector, this.parameterCount);
        else if (this.selector != null && this.selector[this.selector.length - 1] != '*')
          key = CharOperation.concat(this.selector, ONE_STAR, SEPARATOR);
        // else do a pattern query with just the selector
        break;
      case R_REGEXP_MATCH:
        // TODO (frederic) implement regular expression match
        break;
    }

    return index.query(
        getIndexCategories(), key, matchRule); // match rule is irrelevant when the key is null
  }
  public char[] getMainTypeName() {

    if (compilationResult.compilationUnit == null) {
      char[] fileName = compilationResult.getFileName();

      int start = CharOperation.lastIndexOf('/', fileName) + 1;
      if (start == 0 || start < CharOperation.lastIndexOf('\\', fileName))
        start = CharOperation.lastIndexOf('\\', fileName) + 1;

      int end = CharOperation.lastIndexOf('.', fileName);
      if (end == -1) end = fileName.length;

      return CharOperation.subarray(fileName, start, end);
    } else {
      return compilationResult.compilationUnit.getMainTypeName();
    }
  }
  public MethodPattern(
      boolean findDeclarations,
      boolean findReferences,
      boolean isFunction,
      char[] selector,
      char[] declaringQualification,
      char[] declaringSimpleName,
      char[] returnQualification,
      char[] returnSimpleName,
      char[][] parameterQualifications,
      char[][] parameterSimpleNames,
      IType declaringType,
      int matchRule) {

    this(matchRule, isFunction);

    this.findDeclarations = findDeclarations;
    this.findReferences = findReferences;

    this.selector =
        (isCaseSensitive() || isCamelCase()) ? selector : CharOperation.toLowerCase(selector);
    this.declaringQualification =
        isCaseSensitive()
            ? declaringQualification
            : CharOperation.toLowerCase(declaringQualification);
    this.declaringSimpleName =
        isCaseSensitive() ? declaringSimpleName : CharOperation.toLowerCase(declaringSimpleName);
    this.returnQualification =
        isCaseSensitive() ? returnQualification : CharOperation.toLowerCase(returnQualification);
    this.returnSimpleName =
        isCaseSensitive() ? returnSimpleName : CharOperation.toLowerCase(returnSimpleName);
    if (parameterSimpleNames != null) {
      this.parameterCount = parameterSimpleNames.length;
      this.parameterQualifications = new char[this.parameterCount][];
      this.parameterSimpleNames = new char[this.parameterCount][];
      for (int i = 0; i < this.parameterCount; i++) {
        this.parameterQualifications[i] =
            isCaseSensitive()
                ? parameterQualifications[i]
                : CharOperation.toLowerCase(parameterQualifications[i]);
        this.parameterSimpleNames[i] =
            isCaseSensitive()
                ? parameterSimpleNames[i]
                : CharOperation.toLowerCase(parameterSimpleNames[i]);
      }
    } else {
      this.parameterCount = -1;
    }
    this.declaringType = declaringType;
    ((InternalSearchPattern) this).mustResolve = mustResolve();
  }
 /*
  * Type checking for constructor, just another method, except for special check
  * for recursive constructor invocations.
  */
 public void resolveStatements() {
   SourceTypeBinding sourceType = this.scope.enclosingSourceType();
   if (!CharOperation.equals(sourceType.sourceName, this.selector)) {
     this.scope.problemReporter().missingReturnType(this);
   }
   if (this.binding != null && !this.binding.isPrivate()) {
     sourceType.tagBits |= TagBits.HasNonPrivateConstructor;
   }
   // if null ==> an error has occurs at parsing time ....
   if (this.constructorCall != null) {
     if (sourceType.id == TypeIds.T_JavaLangObject
         && this.constructorCall.accessMode != ExplicitConstructorCall.This) {
       this.constructorCall = null;
     } else {
       this.constructorCall.resolve(this.scope);
     }
   }
   if ((this.modifiers & ExtraCompilerModifiers.AccSemicolonBody) != 0) {
     this.scope.problemReporter().methodNeedBody(this);
   }
   super.resolveStatements();
 }
  private void removeLocals(Statement[] statements, int start, int end) {
    if (statements != null) {
      for (int i = 0; i < statements.length; i++) {
        if (statements[i] instanceof LocalDeclaration) {
          LocalDeclaration localDeclaration = (LocalDeclaration) statements[i];
          int j = indexOfFisrtNameAfter(start);
          done:
          while (j != -1) {
            int nameStart = this.potentialVariableNameStarts[j];
            if (start <= nameStart && nameStart <= end) {
              if (CharOperation.equals(
                  this.potentialVariableNames[j], localDeclaration.name, false)) {
                this.removeNameAt(j);
              }
            }

            if (end < nameStart) break done;
            j = indexOfNextName(j);
          }
        }
      }
    }
  }
  private void removeFields(TypeDeclaration typeDeclaration) {
    int start = typeDeclaration.declarationSourceStart;
    int end = typeDeclaration.declarationSourceEnd;

    FieldDeclaration[] fieldDeclarations = typeDeclaration.fields;
    if (fieldDeclarations != null) {
      for (int i = 0; i < fieldDeclarations.length; i++) {
        int j = indexOfFisrtNameAfter(start);
        done:
        while (j != -1) {
          int nameStart = this.potentialVariableNameStarts[j];
          if (start <= nameStart && nameStart <= end) {
            if (CharOperation.equals(
                this.potentialVariableNames[j], fieldDeclarations[i].name, false)) {
              this.removeNameAt(j);
            }
          }

          if (end < nameStart) break done;
          j = indexOfNextName(j);
        }
      }
    }
  }
  private boolean initPotentialNamesTables(char[][] discouragedNames) {
    char[][] pvns = this.parser.potentialVariableNames;
    int[] pvnss = this.parser.potentialVariableNameStarts;
    int pvnsPtr = this.parser.potentialVariableNamesPtr;

    if (pvnsPtr < 0) return false; // there is no potential names

    // remove null and discouragedNames
    int discouragedNamesCount = discouragedNames == null ? 0 : discouragedNames.length;
    int j = -1;
    next:
    for (int i = 0; i <= pvnsPtr; i++) {
      char[] temp = pvns[i];

      if (temp == null) continue next;

      for (int k = 0; k < discouragedNamesCount; k++) {
        if (CharOperation.equals(temp, discouragedNames[k], false)) {
          continue next;
        }
      }

      pvns[i] = null;
      pvns[++j] = temp;
      pvnss[j] = pvnss[i];
    }
    pvnsPtr = j;

    if (pvnsPtr < 0) return false; // there is no potential names

    this.potentialVariableNames = pvns;
    this.potentialVariableNameStarts = pvnss;
    this.potentialVariableNamesPtr = pvnsPtr;

    return true;
  }
  /**
   * Validate the given package name for the given source and compliance levels.
   *
   * <p>The syntax of a package name corresponds to PackageName as defined by PackageDeclaration.
   *
   * <p>Note that the given name must be a non-empty package name (that is, attempting to validate
   * the default package will return an error status.) Also it must not contain any characters or
   * substrings that are not valid on the file system on which workspace root is located.
   *
   * <p><b>Note: This Method only applies to ECMAScript 4 which is not yet supported</b>
   *
   * @param name the name of a package
   * @param sourceLevel the source level
   * @param complianceLevel the compliance level
   * @return a status object with code <code>IStatus.OK</code> if the given name is valid as a
   *     package name, otherwise a status object indicating what is wrong with the name
   */
  public static IStatus validatePackageName(
      String name, String sourceLevel, String complianceLevel) {

    if (name == null) {
      return new Status(
          IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_package_nullName, null);
    }
    int length;
    if ((length = name.length()) == 0) {
      return new Status(
          IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_package_emptyName, null);
    }
    if (name.charAt(0) == DOT || name.charAt(length - 1) == DOT) {
      return new Status(
          IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_package_dotName, null);
    }
    if (CharOperation.isWhitespace(name.charAt(0))
        || CharOperation.isWhitespace(name.charAt(name.length() - 1))) {
      return new Status(
          IStatus.ERROR,
          JavaScriptCore.PLUGIN_ID,
          -1,
          Messages.convention_package_nameWithBlanks,
          null);
    }
    int dot = 0;
    while (dot != -1 && dot < length - 1) {
      if ((dot = name.indexOf(DOT, dot + 1)) != -1
          && dot < length - 1
          && name.charAt(dot + 1) == DOT) {
        return new Status(
            IStatus.ERROR,
            JavaScriptCore.PLUGIN_ID,
            -1,
            Messages.convention_package_consecutiveDotsName,
            null);
      }
    }
    IWorkspace workspace = ResourcesPlugin.getWorkspace();
    IStatus status = workspace.validateName(new String(name), IResource.FOLDER);
    if (!status.isOK()) {
      return status;
    }
    StringTokenizer st = new StringTokenizer(name, "."); // $NON-NLS-1$
    boolean firstToken = true;
    IStatus warningStatus = null;
    while (st.hasMoreTokens()) {
      String typeName = st.nextToken();
      typeName = typeName.trim(); // grammar allows spaces
      char[] scannedID = scannedIdentifier(typeName, sourceLevel, complianceLevel);
      if (scannedID == null) {
        return new Status(
            IStatus.WARNING,
            JavaScriptCore.PLUGIN_ID,
            -1,
            Messages.bind(Messages.convention_illegalIdentifier, typeName),
            null);
      }
      status = workspace.validateName(new String(name), IResource.FOLDER);
      if (!status.isOK()) {
        return status;
      }
      if (firstToken && scannedID.length > 0 && ScannerHelper.isUpperCase(scannedID[0])) {
        if (warningStatus == null) {
          warningStatus =
              new Status(
                  IStatus.WARNING,
                  JavaScriptCore.PLUGIN_ID,
                  -1,
                  Messages.convention_package_uppercaseName,
                  null);
        }
      }
      firstToken = false;
    }
    if (warningStatus != null) {
      return warningStatus;
    }
    return JavaModelStatus.VERIFIED_OK;
  }
  /**
   * Validate the given JavaScript type name, either simple or qualified, for the given source and
   * compliance levels.
   *
   * <p>
   *
   * @param name the name of a type
   * @param sourceLevel the source level
   * @param complianceLevel the compliance level
   * @return a status object with code <code>IStatus.OK</code> if the given name is valid as a
   *     JavaScript type name, a status with code <code>IStatus.WARNING</code> indicating why the
   *     given name is discouraged, otherwise a status object indicating what is wrong with the name
   */
  public static IStatus validateJavaScriptTypeName(
      String name, String sourceLevel, String complianceLevel) {
    if (name == null) {
      return new Status(
          IStatus.ERROR, JavaScriptCore.PLUGIN_ID, -1, Messages.convention_type_nullName, null);
    }
    String trimmed = name.trim();
    if (!name.equals(trimmed)) {
      return new Status(
          IStatus.ERROR,
          JavaScriptCore.PLUGIN_ID,
          -1,
          Messages.convention_type_nameWithBlanks,
          null);
    }
    int index = name.lastIndexOf('.');
    char[] scannedID;
    if (index == -1) {
      // simple name
      scannedID = scannedIdentifier(name, sourceLevel, complianceLevel);
    } else {
      // qualified name
      String pkg = name.substring(0, index).trim();
      IStatus status = validatePackageName(pkg, sourceLevel, complianceLevel);
      if (!status.isOK()) {
        return status;
      }
      String type = name.substring(index + 1).trim();
      scannedID = scannedIdentifier(type, sourceLevel, complianceLevel);
    }

    if (scannedID != null) {
      IStatus status =
          ResourcesPlugin.getWorkspace().validateName(new String(scannedID), IResource.FILE);
      if (!status.isOK()) {
        return status;
      }
      if (CharOperation.contains('$', scannedID)) {
        return new Status(
            IStatus.WARNING,
            JavaScriptCore.PLUGIN_ID,
            -1,
            Messages.convention_type_dollarName,
            null);
      }
      if ((scannedID.length > 0 && ScannerHelper.isLowerCase(scannedID[0]))) {
        return new Status(
            IStatus.WARNING,
            JavaScriptCore.PLUGIN_ID,
            -1,
            Messages.convention_type_lowercaseName,
            null);
      }
      return JavaModelStatus.VERIFIED_OK;
    } else {
      return new Status(
          IStatus.ERROR,
          JavaScriptCore.PLUGIN_ID,
          -1,
          Messages.bind(Messages.convention_type_invalidName, name),
          null);
    }
  }
 public boolean isPackageInfo() {
   return CharOperation.equals(this.getMainTypeName(), TypeConstants.PACKAGE_INFO_NAME);
 }