@Override
 public boolean visit(TryStatement node) {
   final List<Statement> tryStmts = asList(node.getBody());
   if (tryStmts.isEmpty()) {
     final List<Statement> finallyStmts = asList(node.getFinally());
     if (!finallyStmts.isEmpty()) {
       final ASTBuilder b = this.ctx.getASTBuilder();
       this.ctx.getRefactorings().replace(node, b.copy(node.getFinally()));
       return DO_NOT_VISIT_SUBTREE;
     } else if (node.resources().isEmpty()) {
       this.ctx.getRefactorings().remove(node);
       return DO_NOT_VISIT_SUBTREE;
     }
   }
   // }else {
   // for (CatchClause catchClause : (List<CatchClause>) node.catchClauses()) {
   // final List<Statement> finallyStmts = asList(catchClause.getBody());
   // if (finallyStmts.isEmpty()) {
   // // TODO cannot remove without checking what subsequent catch clauses are
   // catching
   // this.ctx.getRefactorings().remove(catchClause);
   // }
   // }
   //
   // final List<Statement> finallyStmts = asList(node.getFinally());
   // if (finallyStmts.isEmpty()) {
   // this.ctx.getRefactorings().remove(node.getFinally());
   // }
   // // TODO If all finally and catch clauses have been removed,
   // // then we can remove the whole try statement and replace it with a simple block
   // return DO_NOT_VISIT_SUBTREE; // TODO JNR is this correct?
   // }
   return VISIT_SUBTREE;
 }
 @Override
 public boolean visit(IfStatement node) {
   final Statement elseStmt = node.getElseStatement();
   if (elseStmt instanceof Block) {
     List<Statement> elseStmts = statements((Block) elseStmt);
     if (elseStmts.size() == 1 && elseStmts.get(0) instanceof IfStatement) {
       final ASTBuilder b = this.ctx.getASTBuilder();
       this.ctx.getRefactorings().set(node, ELSE_STATEMENT_PROPERTY, b.copy(elseStmts.get(0)));
       return DO_NOT_VISIT_SUBTREE;
     }
   }
   return VISIT_SUBTREE;
 }
  @Override
  public boolean visit(IfStatement node) {
    final ASTBuilder b = this.ctx.getASTBuilder();
    final Refactorings r = this.ctx.getRefactorings();

    final Statement thenStmt = node.getThenStatement();
    final Statement elseStmt = node.getElseStatement();
    final Expression condition = node.getExpression();
    if (elseStmt != null && asList(elseStmt).isEmpty()) {
      r.remove(elseStmt);
      return DO_NOT_VISIT_SUBTREE;
    } else if (thenStmt != null && asList(thenStmt).isEmpty()) {
      if (elseStmt != null) {
        r.replace(node, b.if0(b.negate(condition), b.move(elseStmt)));
      } else {
        final List<Expression> sideEffectExprs = new ArrayList<Expression>();
        collectSideEffects(condition, sideEffectExprs);
        if (!sideEffectExprs.isEmpty()) {
          for (Expression sideEffectExpr : sideEffectExprs) {
            r.insertBefore(b.toStmt(b.move(sideEffectExpr)), node);
          }
        }
        r.remove(node);
      }
      return DO_NOT_VISIT_SUBTREE;
    }

    final Object constantCondition = condition.resolveConstantExpressionValue();
    if (Boolean.TRUE.equals(constantCondition)) {
      r.replace(node, b.copy(thenStmt));
      if (lastStmtIsThrowOrReturn(thenStmt)) {
        r.remove(getNextSiblings(node));
      }
      return DO_NOT_VISIT_SUBTREE;
    } else if (Boolean.FALSE.equals(constantCondition)) {
      if (elseStmt != null) {
        r.replace(node, b.copy(elseStmt));
        if (lastStmtIsThrowOrReturn(elseStmt)) {
          r.remove(getNextSiblings(node));
        }
      } else {
        r.remove(node);
      }
      return DO_NOT_VISIT_SUBTREE;
    }
    return VISIT_SUBTREE;
  }
 @Override
 protected <T extends ASTNode> T perform(ASTBuilder b, T node) {
   return b.move(node);
 }