Beispiel #1
0
  /*
   * Record a statement - regular method should have been created a block body
   */
  public RecoveredElement add(Statement statement, int bracketBalanceValue) {
    this.resetPendingModifiers();

    /* do not consider a type starting passed the type end (if set)
    it must be belonging to an enclosing type */
    if (methodDeclaration.declarationSourceEnd != 0
        && statement.sourceStart > methodDeclaration.declarationSourceEnd) {

      if (this.parent == null) {
        return this; // ignore
      } else {
        return this.parent.add(statement, bracketBalanceValue);
      }
    }
    if (methodBody == null) {
      Block block = new Block(0);
      block.sourceStart = methodDeclaration.bodyStart;
      RecoveredElement currentBlock = this.add(block, 1);
      if (this.bracketBalance > 0) {
        for (int i = 0; i < this.bracketBalance - 1; i++) {
          currentBlock = currentBlock.add(new Block(0), 1);
        }
        this.bracketBalance = 1;
      }
      return currentBlock.add(statement, bracketBalanceValue);
    }
    return methodBody.add(statement, bracketBalanceValue, true);
  }
Beispiel #2
0
  /*
   * Record a local declaration - regular method should have been created a block body
   */
  public RecoveredElement add(LocalDeclaration localDeclaration, int bracketBalanceValue) {
    this.resetPendingModifiers();

    /* local variables inside method can only be final and non void */
    /*
    	char[][] localTypeName;
    	if ((localDeclaration.modifiers & ~AccFinal) != 0 // local var can only be final
    		|| (localDeclaration.type == null) // initializer
    		|| ((localTypeName = localDeclaration.type.getTypeName()).length == 1 // non void
    			&& CharOperation.equals(localTypeName[0], VoidBinding.sourceName()))){

    		if (this.parent == null){
    			return this; // ignore
    		} else {
    			this.updateSourceEndIfNecessary(this.previousAvailableLineEnd(localDeclaration.declarationSourceStart - 1));
    			return this.parent.add(localDeclaration, bracketBalance);
    		}
    	}
    */
    /* do not consider a type starting passed the type end (if set)
    it must be belonging to an enclosing type */
    if (methodDeclaration.declarationSourceEnd != 0
        && localDeclaration.declarationSourceStart > methodDeclaration.declarationSourceEnd) {

      if (this.parent == null) {
        return this; // ignore
      } else {
        return this.parent.add(localDeclaration, bracketBalanceValue);
      }
    }
    if (methodBody == null) {
      Block block = new Block(0);
      block.sourceStart = methodDeclaration.bodyStart;
      RecoveredElement currentBlock = this.add(block, 1);
      if (this.bracketBalance > 0) {
        for (int i = 0; i < this.bracketBalance - 1; i++) {
          currentBlock = currentBlock.add(new Block(0), 1);
        }
        this.bracketBalance = 1;
      }
      return currentBlock.add(localDeclaration, bracketBalanceValue);
    }
    return methodBody.add(localDeclaration, bracketBalanceValue, true);
  }
Beispiel #3
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;
    }
  }
Beispiel #4
0
  public RecoveredElement add(TypeDeclaration typeDeclaration, int bracketBalanceValue) {

    /* do not consider a type starting passed the type end (if set)
    it must be belonging to an enclosing type */
    if (methodDeclaration.declarationSourceEnd != 0
        && typeDeclaration.declarationSourceStart > methodDeclaration.declarationSourceEnd) {

      if (this.parent == null) {
        return this; // ignore
      }
      return this.parent.add(typeDeclaration, bracketBalanceValue);
    }
    if ((typeDeclaration.bits & ASTNode.IsLocalType) != 0
        || this.parser().methodRecoveryActivated
        || this.parser().statementRecoveryActivated) {
      if (methodBody == null) {
        Block block = new Block(0);
        block.sourceStart = methodDeclaration.bodyStart;
        this.add(block, 1);
      }
      methodBody.attachPendingModifiers(
          this.pendingAnnotations,
          this.pendingAnnotationCount,
          this.pendingModifiers,
          this.pendingModifersSourceStart);
      this.resetPendingModifiers();
      return methodBody.add(typeDeclaration, bracketBalanceValue, true);
    }
    switch (TypeDeclaration.kind(typeDeclaration.modifiers)) {
      case TypeDeclaration.INTERFACE_DECL:
      case TypeDeclaration.ANNOTATION_TYPE_DECL:
        resetPendingModifiers();
        this.updateSourceEndIfNecessary(
            this.previousAvailableLineEnd(typeDeclaration.declarationSourceStart - 1));
        if (this.parent == null) {
          return this; // ignore
        }
        // close the constructor
        return this.parent.add(typeDeclaration, bracketBalanceValue);
    }
    if (localTypes == null) {
      localTypes = new RecoveredType[5];
      localTypeCount = 0;
    } else {
      if (localTypeCount == localTypes.length) {
        System.arraycopy(
            localTypes, 0, (localTypes = new RecoveredType[2 * localTypeCount]), 0, localTypeCount);
      }
    }
    RecoveredType element = new RecoveredType(typeDeclaration, this, bracketBalanceValue);
    localTypes[localTypeCount++] = element;

    if (this.pendingAnnotationCount > 0) {
      element.attach(
          pendingAnnotations, pendingAnnotationCount, pendingModifiers, pendingModifersSourceStart);
    }
    this.resetPendingModifiers();

    /* consider that if the opening brace was not found, it is there */
    if (!foundOpeningBrace) {
      foundOpeningBrace = true;
      this.bracketBalance++;
    }
    return element;
  }
Beispiel #5
0
  @Override
  public boolean handle(
      AnnotationValues<Synchronized> annotation, Annotation source, EclipseNode annotationNode) {
    int p1 = source.sourceStart - 1;
    int p2 = source.sourceStart - 2;
    long pos = (((long) p1) << 32) | p2;
    EclipseNode methodNode = annotationNode.up();
    if (methodNode == null
        || methodNode.getKind() != Kind.METHOD
        || !(methodNode.get() instanceof MethodDeclaration)) {
      annotationNode.addError("@Synchronized is legal only on methods.");
      return true;
    }

    MethodDeclaration method = (MethodDeclaration) methodNode.get();
    if (method.isAbstract()) {
      annotationNode.addError("@Synchronized is legal only on concrete methods.");
      return true;
    }

    char[] lockName = annotation.getInstance().value().toCharArray();
    boolean autoMake = false;
    if (lockName.length == 0) {
      autoMake = true;
      lockName = method.isStatic() ? STATIC_LOCK_NAME : INSTANCE_LOCK_NAME;
    }

    if (fieldExists(new String(lockName), methodNode) == MemberExistsResult.NOT_EXISTS) {
      if (!autoMake) {
        annotationNode.addError("The field " + new String(lockName) + " does not exist.");
        return true;
      }
      FieldDeclaration fieldDecl = new FieldDeclaration(lockName, 0, -1);
      Eclipse.setGeneratedBy(fieldDecl, source);
      fieldDecl.declarationSourceEnd = -1;

      fieldDecl.modifiers =
          (method.isStatic() ? Modifier.STATIC : 0) | Modifier.FINAL | Modifier.PRIVATE;

      // We use 'new Object[0];' because quite unlike 'new Object();', empty arrays *ARE*
      // serializable!
      ArrayAllocationExpression arrayAlloc = new ArrayAllocationExpression();
      Eclipse.setGeneratedBy(arrayAlloc, source);
      arrayAlloc.dimensions = new Expression[] {new IntLiteral(new char[] {'0'}, 0, 0)};
      Eclipse.setGeneratedBy(arrayAlloc.dimensions[0], source);
      arrayAlloc.type =
          new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] {0, 0, 0});
      Eclipse.setGeneratedBy(arrayAlloc.type, source);
      fieldDecl.type =
          new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] {0, 0, 0});
      Eclipse.setGeneratedBy(fieldDecl.type, source);
      fieldDecl.initialization = arrayAlloc;
      injectFieldSuppressWarnings(annotationNode.up().up(), fieldDecl);
    }

    if (method.statements == null) return false;

    Block block = new Block(0);
    Eclipse.setGeneratedBy(block, source);
    block.statements = method.statements;
    Expression lockVariable;
    if (method.isStatic())
      lockVariable =
          new QualifiedNameReference(
              new char[][] {methodNode.up().getName().toCharArray(), lockName},
              new long[] {pos, pos},
              p1,
              p2);
    else {
      lockVariable = new FieldReference(lockName, pos);
      ThisReference thisReference = new ThisReference(p1, p2);
      Eclipse.setGeneratedBy(thisReference, source);
      ((FieldReference) lockVariable).receiver = thisReference;
    }
    Eclipse.setGeneratedBy(lockVariable, source);

    method.statements = new Statement[] {new SynchronizedStatement(lockVariable, block, 0, 0)};
    Eclipse.setGeneratedBy(method.statements[0], source);

    methodNode.rebuild();

    return true;
  }