public void replaceWithElementType() {
   if (this.constantPoolName[1] == 'L') {
     this.constantPoolName =
         CharOperation.subarray(this.constantPoolName, 2, this.constantPoolName.length - 1);
   } else {
     this.constantPoolName =
         CharOperation.subarray(this.constantPoolName, 1, this.constantPoolName.length);
     if (this.constantPoolName.length == 1) {
       switch (this.constantPoolName[0]) {
         case 'I':
           this.id = TypeIds.T_int;
           break;
         case 'B':
           this.id = TypeIds.T_byte;
           break;
         case 'S':
           this.id = TypeIds.T_short;
           break;
         case 'C':
           this.id = TypeIds.T_char;
           break;
         case 'J':
           this.id = TypeIds.T_long;
           break;
         case 'F':
           this.id = TypeIds.T_float;
           break;
         case 'D':
           this.id = TypeIds.T_double;
           break;
         case 'Z':
           this.id = TypeIds.T_boolean;
           break;
         case 'N':
           this.id = TypeIds.T_null;
           break;
         case 'V':
           this.id = TypeIds.T_void;
           break;
       }
     }
   }
 }
  protected boolean matches(char[][] compoundName) {
    int length = compoundName.length;
    if (length == 0) return false;
    char[] simpleName = compoundName[length - 1];
    int last = length - 1;
    if (this.typeSimpleName == null || this.pattern.matchesName(simpleName, this.typeSimpleName)) {
      // most frequent case: simple name equals last segment of compoundName
      char[][] qualification = new char[last][];
      System.arraycopy(compoundName, 0, qualification, 0, last);
      return this.pattern.matchesName(
          this.typeQualification, CharOperation.concatWith(qualification, '.'));
    }

    if (!CharOperation.endsWith(simpleName, this.typeSimpleName)) return false;

    // member type -> transform A.B.C$D into A.B.C.D
    System.arraycopy(compoundName, 0, compoundName = new char[length + 1][], 0, last);
    int dollar = CharOperation.indexOf('$', simpleName);
    if (dollar == -1) return false;
    compoundName[last] = CharOperation.subarray(simpleName, 0, dollar);
    compoundName[length] = CharOperation.subarray(simpleName, dollar + 1, simpleName.length);
    return this.matches(compoundName);
  }
  public char[] getMainTypeName() {
    if (this.compilationResult.compilationUnit == null) {
      char[] fileName = this.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 this.compilationResult.compilationUnit.getMainTypeName();
    }
  }
  /**
   * In case emulating local variables, wrap the (recovered) statements inside a try statement so as
   * to achieve local state commiting (copy local vars back to fields). The CSToCuMapper could not
   * be used, since it could have interfered with the syntax recovery specific to code snippets.
   */
  protected void consumeMethodDeclaration(boolean isNotAbstract) {
    // MethodDeclaration ::= MethodHeader MethodBody
    // AbstractMethodDeclaration ::= MethodHeader ';'

    super.consumeMethodDeclaration(isNotAbstract);

    // now we know that we have a method declaration at the top of the ast stack
    MethodDeclaration methodDecl = (MethodDeclaration) this.astStack[this.astPtr];

    // automatically wrap the last statement inside a return statement, if it is an expression
    // support have to be defined at toplevel only
    if (this.isTopLevelType()) {
      int last = methodDecl.statements == null ? -1 : methodDecl.statements.length - 1;
      if (last >= 0 && methodDecl.statements[last] instanceof Expression) {
        Expression lastExpression = (Expression) methodDecl.statements[last];
        methodDecl.statements[last] =
            new CodeSnippetReturnStatement(
                lastExpression, lastExpression.sourceStart, lastExpression.sourceEnd);
      }
    }

    int start = methodDecl.bodyStart - 1, end = start;
    long position = ((long) start << 32) + end;
    long[] positions = new long[] {position};
    if (this.evaluationContext.localVariableNames != null) {

      int varCount =
          this.evaluationContext.localVariableNames.length; // n local decls+ try statement

      // generate n local variable declarations: [type] [name] = val$[name];
      Statement[] newStatements = new Statement[varCount + 1];
      for (int i = 0; i < varCount; i++) {
        char[] trimmedTypeName = this.evaluationContext.localVariableTypeNames[i];
        int nameEnd = CharOperation.indexOf('[', trimmedTypeName);
        if (nameEnd >= 0) {
          trimmedTypeName = CharOperation.subarray(trimmedTypeName, 0, nameEnd);
        }
        nameEnd = CharOperation.indexOf(' ', trimmedTypeName);
        if (nameEnd >= 0) {
          trimmedTypeName = CharOperation.subarray(trimmedTypeName, 0, nameEnd);
        }
        TypeReference typeReference =
            new QualifiedTypeReference(CharOperation.splitOn('.', trimmedTypeName), positions);
        int dimCount =
            CharOperation.occurencesOf('[', this.evaluationContext.localVariableTypeNames[i]);
        if (dimCount > 0) {
          typeReference = this.copyDims(typeReference, dimCount);
        }
        NameReference init =
            new SingleNameReference(
                CharOperation.concat(
                    LOCAL_VAR_PREFIX, this.evaluationContext.localVariableNames[i]),
                position);
        LocalDeclaration declaration =
            new LocalDeclaration(this.evaluationContext.localVariableNames[i], start, end);
        declaration.initialization = init;
        declaration.type = typeReference;
        declaration.modifiers = this.evaluationContext.localVariableModifiers[i];
        newStatements[i] = declaration;
      }

      // generate try { [snippet] } finally { [save locals to fields] }
      // try block
      TryStatement tryStatement = new TryStatement();
      Block tryBlock = new Block(methodDecl.explicitDeclarations);
      tryBlock.sourceStart = start;
      tryBlock.sourceEnd = end;
      tryBlock.statements = methodDecl.statements; // snippet statements
      tryStatement.tryBlock = tryBlock;
      // finally block
      Block finallyBlock = new Block(0);
      finallyBlock.sourceStart = start;
      finallyBlock.sourceEnd = end;
      finallyBlock.statements = new Statement[varCount];
      for (int i = 0; i < varCount; i++) {
        finallyBlock.statements[i] =
            new Assignment(
                new SingleNameReference(
                    CharOperation.concat(
                        LOCAL_VAR_PREFIX, this.evaluationContext.localVariableNames[i]),
                    position),
                new SingleNameReference(this.evaluationContext.localVariableNames[i], position),
                (int) position);
      }
      tryStatement.finallyBlock = finallyBlock;

      newStatements[varCount] = tryStatement;
      methodDecl.statements = newStatements;
    }
  }
  /** Locate declaration in the current class file. This class file is always in a jar. */
  public void locateMatches(MatchLocator locator, ClassFile classFile, IBinaryType info)
      throws CoreException {
    SearchPattern pattern = locator.pattern;

    // check annotations references
    matchAnnotations(pattern, locator, classFile, info);

    // check class definition
    BinaryType binaryType = (BinaryType) classFile.getType();
    if (matchBinary(pattern, info, null)) {
      binaryType =
          new ResolvedBinaryType(
              (JavaElement) binaryType.getParent(),
              binaryType.getElementName(),
              binaryType.getKey());
      locator.reportBinaryMemberDeclaration(null, binaryType, null, info, SearchMatch.A_ACCURATE);
      return;
    }

    // Define arrays to store methods/fields from binary type if necessary
    IBinaryMethod[] binaryMethods = info.getMethods();
    int bMethodsLength = binaryMethods == null ? 0 : binaryMethods.length;
    IBinaryMethod[] unresolvedMethods = null;
    char[][] binaryMethodSignatures = null;
    boolean hasUnresolvedMethods = false;

    // Get fields from binary type info
    IBinaryField[] binaryFields = info.getFields();
    int bFieldsLength = binaryFields == null ? 0 : binaryFields.length;
    IBinaryField[] unresolvedFields = null;
    boolean hasUnresolvedFields = false;

    // Report as many accurate matches as possible
    int accuracy = SearchMatch.A_ACCURATE;
    boolean mustResolve = pattern.mustResolve;
    if (mustResolve) {
      BinaryTypeBinding binding = locator.cacheBinaryType(binaryType, info);
      if (binding != null) {
        // filter out element not in hierarchy scope
        if (!locator.typeInHierarchy(binding)) return;

        // Search matches on resolved methods
        MethodBinding[] availableMethods = binding.availableMethods();
        int aMethodsLength = availableMethods == null ? 0 : availableMethods.length;
        hasUnresolvedMethods = bMethodsLength != aMethodsLength;
        for (int i = 0; i < aMethodsLength; i++) {
          MethodBinding method = availableMethods[i];
          char[] methodSignature = method.genericSignature();
          if (methodSignature == null) methodSignature = method.signature();

          // Report the match if possible
          int level = locator.patternLocator.resolveLevel(method);
          if (level != PatternLocator.IMPOSSIBLE_MATCH) {
            IMethod methodHandle =
                binaryType.getMethod(
                    new String(
                        method.isConstructor()
                            ? binding.compoundName[binding.compoundName.length - 1]
                            : method.selector),
                    CharOperation.toStrings(
                        Signature.getParameterTypes(convertClassFileFormat(methodSignature))));
            accuracy =
                level == PatternLocator.ACCURATE_MATCH
                    ? SearchMatch.A_ACCURATE
                    : SearchMatch.A_INACCURATE;
            locator.reportBinaryMemberDeclaration(null, methodHandle, method, info, accuracy);
          }

          // Remove method from unresolved list
          if (hasUnresolvedMethods) {
            if (binaryMethodSignatures
                == null) { // Store binary method signatures to avoid multiple computation
              binaryMethodSignatures = new char[bMethodsLength][];
              for (int j = 0; j < bMethodsLength; j++) {
                IBinaryMethod binaryMethod = binaryMethods[j];
                char[] signature = binaryMethod.getGenericSignature();
                if (signature == null) signature = binaryMethod.getMethodDescriptor();
                binaryMethodSignatures[j] = signature;
              }
            }
            for (int j = 0; j < bMethodsLength; j++) {
              if (CharOperation.equals(binaryMethods[j].getSelector(), method.selector)
                  && CharOperation.equals(binaryMethodSignatures[j], methodSignature)) {
                if (unresolvedMethods == null) {
                  System.arraycopy(
                      binaryMethods,
                      0,
                      unresolvedMethods = new IBinaryMethod[bMethodsLength],
                      0,
                      bMethodsLength);
                }
                unresolvedMethods[j] = null;
                break;
              }
            }
          }
        }

        // Search matches on resolved fields
        FieldBinding[] availableFields = binding.availableFields();
        int aFieldsLength = availableFields == null ? 0 : availableFields.length;
        hasUnresolvedFields = bFieldsLength != aFieldsLength;
        for (int i = 0; i < aFieldsLength; i++) {
          FieldBinding field = availableFields[i];

          // Report the match if possible
          int level = locator.patternLocator.resolveLevel(field);
          if (level != PatternLocator.IMPOSSIBLE_MATCH) {
            IField fieldHandle = binaryType.getField(new String(field.name));
            accuracy =
                level == PatternLocator.ACCURATE_MATCH
                    ? SearchMatch.A_ACCURATE
                    : SearchMatch.A_INACCURATE;
            locator.reportBinaryMemberDeclaration(null, fieldHandle, field, info, accuracy);
          }

          // Remove the field from unresolved list
          if (hasUnresolvedFields) {
            for (int j = 0; j < bFieldsLength; j++) {
              if (CharOperation.equals(binaryFields[j].getName(), field.name)) {
                if (unresolvedFields == null) {
                  System.arraycopy(
                      binaryFields,
                      0,
                      unresolvedFields = new IBinaryField[bFieldsLength],
                      0,
                      bFieldsLength);
                }
                unresolvedFields[j] = null;
                break;
              }
            }
          }
        }

        // If all methods/fields were accurate then returns now
        if (!hasUnresolvedMethods && !hasUnresolvedFields) {
          return;
        }
      }
      accuracy = SearchMatch.A_INACCURATE;
    }

    // Report inaccurate methods
    if (mustResolve) binaryMethods = unresolvedMethods;
    bMethodsLength = binaryMethods == null ? 0 : binaryMethods.length;
    for (int i = 0; i < bMethodsLength; i++) {
      IBinaryMethod method = binaryMethods[i];
      if (method == null) continue; // impossible match or already reported as accurate
      if (matchBinary(pattern, method, info)) {
        char[] name;
        if (method.isConstructor()) {
          name = info.getName();
          int lastSlash = CharOperation.lastIndexOf('/', name);
          if (lastSlash != -1) {
            name = CharOperation.subarray(name, lastSlash + 1, name.length);
          }
        } else {
          name = method.getSelector();
        }
        String selector = new String(name);
        char[] methodSignature = binaryMethodSignatures == null ? null : binaryMethodSignatures[i];
        if (methodSignature == null) {
          methodSignature = method.getGenericSignature();
          if (methodSignature == null) methodSignature = method.getMethodDescriptor();
        }
        String[] parameterTypes =
            CharOperation.toStrings(
                Signature.getParameterTypes(convertClassFileFormat(methodSignature)));
        IMethod methodHandle = binaryType.getMethod(selector, parameterTypes);
        methodHandle =
            new ResolvedBinaryMethod(binaryType, selector, parameterTypes, methodHandle.getKey());
        locator.reportBinaryMemberDeclaration(null, methodHandle, null, info, accuracy);
      }
    }

    // Report inaccurate fields
    if (mustResolve) binaryFields = unresolvedFields;
    bFieldsLength = binaryFields == null ? 0 : binaryFields.length;
    for (int i = 0; i < bFieldsLength; i++) {
      IBinaryField field = binaryFields[i];
      if (field == null) continue; // impossible match or already reported as accurate
      if (matchBinary(pattern, field, info)) {
        String fieldName = new String(field.getName());
        IField fieldHandle = binaryType.getField(fieldName);
        fieldHandle = new ResolvedBinaryField(binaryType, fieldName, fieldHandle.getKey());
        locator.reportBinaryMemberDeclaration(null, fieldHandle, null, info, accuracy);
      }
    }
  }
 public static char[] getSimpleNameAsCharArray(char[] name) {
   int index = CharOperation.lastIndexOf('.', name);
   char[] subarray = CharOperation.subarray(name, index + 1, name.length);
   subarray = CharOperation.replaceOnCopy(subarray, '$', '.');
   return subarray;
 }