예제 #1
0
  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);
  }
예제 #2
0
  /**
   * 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;
    }
  }
  /* Take a type and apply annotations to various components of it. By construction when we see the type reference @Outer Outer.@Middle Middle.@Inner Inner,
     we first construct the binding for Outer.Middle.Inner and then annotate various parts of it. Likewise for PQTR's binding.
  */
  public TypeBinding getAnnotatedType(TypeBinding type, AnnotationBinding[][] annotations) {

    if (type == null || !type.isValidBinding() || annotations == null || annotations.length == 0)
      return type;

    TypeBinding annotatedType = null;
    switch (type.kind()) {
      case Binding.ARRAY_TYPE:
        ArrayBinding arrayBinding = (ArrayBinding) type;
        annotatedType =
            getArrayType(
                arrayBinding.leafComponentType,
                arrayBinding.dimensions,
                flattenedAnnotations(annotations));
        break;
      case Binding.BASE_TYPE:
      case Binding.TYPE:
      case Binding.GENERIC_TYPE:
      case Binding.PARAMETERIZED_TYPE:
      case Binding.RAW_TYPE:
      case Binding.TYPE_PARAMETER:
      case Binding.WILDCARD_TYPE:
      case Binding.INTERSECTION_TYPE:
      case Binding.INTERSECTION_CAST_TYPE:
        /* Taking the binding of QTR as an example, there could be different annotatable components, but we come in a with a single binding, e.g:
          @T Z;                                      type => Z  annotations => [[@T]]
          @T Y.@T Z                                  type => Z  annotations => [[@T][@T]]
          @T X.@T Y.@T Z                             type => Z  annotations => [[@T][@T][@T]]
          java.lang.@T X.@T Y.@T Z                   type => Z  annotations => [[][][@T][@T][@T]]
          in all these cases the incoming type binding is for Z, but annotations are for different levels. We need to align their layout for proper attribution.
        */

        if (type.isUnresolvedType() && CharOperation.indexOf('$', type.sourceName()) > 0)
          type =
              BinaryTypeBinding.resolveType(
                  type,
                  this.environment,
                  true); // must resolve member types before asking for enclosingType

        int levels = type.depth() + 1;
        TypeBinding[] types = new TypeBinding[levels];
        types[--levels] = type;
        TypeBinding enclosingType = type.enclosingType();
        while (enclosingType != null) {
          types[--levels] = enclosingType;
          enclosingType = enclosingType.enclosingType();
        }
        // Locate the outermost type being annotated. Beware annotations.length could be >
        // types.length (for package qualified names in QTR/PQTR)
        levels = annotations.length;
        int i, j = types.length - levels;
        for (i = 0; i < levels; i++, j++) {
          if (annotations[i] != null && annotations[i].length > 0) break;
        }
        if (i == levels) // empty annotations array ?
        return type;
        if (j
            < 0) // Not kosher, broken type that is not flagged as invalid while reporting
                 // compilation error ? don't touch.
        return type;
        // types[j] is the first component being annotated. Its annotations are annotations[i]
        for (enclosingType = j == 0 ? null : types[j - 1]; i < levels; i++, j++) {
          final TypeBinding currentType = types[j];
          // while handling annotations from SE7 locations, take care not to drop existing
          // annotations.
          AnnotationBinding[] currentAnnotations =
              annotations[i] != null && annotations[i].length > 0
                  ? annotations[i]
                  : currentType.getTypeAnnotations();
          annotatedType = getAnnotatedType(currentType, enclosingType, currentAnnotations);
          enclosingType = annotatedType;
        }
        break;
      default:
        throw new IllegalStateException();
    }
    return annotatedType;
  }
 @Override
 public BinaryGenericTypeSignature getTypeErasure() {
   int end = CharOperation.indexOf(Signature.C_GENERIC_START, chars, offset, offset + length);
   if (end == -1) return this;
   return new BinaryErasureTypeSignature(this, getArrayDimensions());
 }
예제 #5
0
 private static boolean dependencyExists(IFile buildConfigFile, String dependencyText)
     throws CoreException {
   char[] contents = ((CompilationUnit) JavaCore.create(buildConfigFile)).getContents();
   return CharOperation.indexOf(dependencyText.toCharArray(), contents, true) >= 0;
 }