/**
  * Remove an statement
  *
  * @param statement
  */
 private void remove(CtStatement statement) {
   if (statement.getParent() instanceof CtBlock) {
     ((CtBlock) statement.getParent()).removeStatement(statement);
   } else {
     CtCodeSnippetStatementImpl comment = new CtCodeSnippetStatementImpl();
     comment.setValue("/*REMOVED*/");
     statement.replace(comment);
   }
 }
 @Override
 public <R> void visitCtBlock(CtBlock<R> block) {
   int i = 0;
   while (i < block.getStatements().size()) {
     int size = block.getStatements().size();
     CtStatement s = block.getStatement(i);
     s.accept(this);
     if (block.getStatements().size() >= size) i++;
   }
 }
  protected CtMethod apply(CtMethod method, List<Statement> statements, int index) {
    CtMethod cloned_method = AmplificationHelper.cloneMethodTest(method, "_cf", 1000);
    CtStatement stmt = getAssertStatement(cloned_method).get(index);
    statements
        .stream()
        .forEach(
            c -> {
              stmt.insertBefore((CtStatement) c.getCtCodeFragment());
              c.getCtCodeFragment().setParent(stmt.getParent());
            });

    return cloned_method;
  }
  @Override
  public void visitCtIf(CtIf ifElement) {
    // super.visitCtIf(ifElement);

    CtStatement ctThen = ifElement.getThenStatement();
    CtStatement ctElse = ifElement.getElseStatement();

    Mutability condMut = mutability(ifElement.getCondition());
    if (ctThen != null) ifElement.getThenStatement().accept(this);
    if (ctElse != null) ifElement.getElseStatement().accept(this);

    if (condMut == Mutability.ERASABLE && isEmpty(ctThen)) {
      // if ( - ) {  } else {  } <- Remove the whole if
      if (ctElse == null || isEmpty(ctElse)) remove(ifElement);
      // else if case: if ( - ) {  } else if { doSomething() } <-- pull the else if element up
      else if (ctElse instanceof CtIf) ctElse.setParent(ifElement.getParent());
    }
  }
 /**
  * Pretty print for the resulting degraded block
  *
  * @param clonedBody
  * @return
  */
 public String prettyPrintBody(CtStatement clonedBody) {
   String result = "";
   if (clonedBody instanceof CtBlock) {
     CtBlock block = (CtBlock) clonedBody;
     try {
       for (int i = 0; i < block.getStatements().size(); i++) {
         if (block.getStatement(i) instanceof CtBlock)
           result += prettyPrintBody(block.getStatement(i));
         else if (block.getStatement(i) != null)
           result += block.getStatement(i).toString() + ";\n";
       }
     } catch (NullPointerException ex) {
       log.error("Unable to print the degraded loop!");
     }
   } else result = clonedBody.toString();
   return result;
 }
  protected List<CtLocalVariable> getLocalVarInScope(CtStatement stmt) {
    List<CtLocalVariable> vars = new ArrayList<>();
    try {
      CtBlock parentBlock = stmt.getParent(CtBlock.class);
      if (parentBlock != null) {
        boolean beforeCurrentStmt = true;
        int i = 0;
        List<CtStatement> stmts = parentBlock.getStatements();

        while (beforeCurrentStmt && i < stmts.size()) {
          CtStatement currentStatement = stmts.get(i);
          i++;
          beforeCurrentStmt = beforeCurrentStmt && currentStatement != stmt;
          if (currentStatement instanceof CtLocalVariable) {
            vars.add((CtLocalVariable) currentStatement);
          }
        }
        vars.addAll(getLocalVarInScope(parentBlock));
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    return vars;
  }