/*
  * (non-Javadoc)
  *
  * @see org.walkmod.javalang.visitors.VoidVisitorAdapter#visit(org.walkmod.javalang .ast.stmt.BlockStmt,
  * java.lang.Object)
  */
 @Override
 public void visit(BlockStmt n, VisitorContext arg) {
   List<Statement> stmts = n.getStmts();
   if (stmts == null) {
     super.visit(n, arg);
     return;
   }
   int returnStmtIndex = -1;
   String variableName = null;
   for (int i = 0; i < stmts.size(); i++) {
     Statement statement = stmts.get(i);
     if (statement instanceof ReturnStmt) {
       Expression expr = ((ReturnStmt) statement).getExpr();
       if (expr instanceof NameExpr) {
         returnStmtIndex = i;
         variableName = ((NameExpr) expr).getName();
         break;
       }
     }
   }
   if (returnStmtIndex > 0) {
     Statement statement = stmts.get(returnStmtIndex - 1);
     boolean isEmpty = false;
     boolean isRemove = false;
     Expression init = null;
     if (statement instanceof ExpressionStmt) {
       Expression expression = ((ExpressionStmt) statement).getExpression();
       if (expression instanceof VariableDeclarationExpr) {
         List<VariableDeclarator> vars = ((VariableDeclarationExpr) expression).getVars();
         for (VariableDeclarator variableDeclarator : vars) {
           if (variableDeclarator.getId().getName().equals(variableName)) {
             init = variableDeclarator.getInit();
             vars.remove(variableDeclarator);
             isRemove = true;
             break;
           }
         }
         isEmpty = vars.isEmpty();
       } else if (expression instanceof AssignExpr) {
         AssignExpr assignExpr = (AssignExpr) expression;
         if (assignExpr.getOperator() == ASSIGN_OPERATOR) {
           Expression target = assignExpr.getTarget();
           if (target instanceof NameExpr) {
             NameExpr expr = (NameExpr) target;
             if (expr.getName().equals(variableName)) {
               init = assignExpr.getValue();
               isRemove = true;
               isEmpty = true;
             }
           }
         }
       }
       if (isRemove) {
         ReturnStmt returnStmt = (ReturnStmt) stmts.get(returnStmtIndex);
         returnStmt.setExpr(init);
         if (isEmpty) {
           stmts.remove(returnStmtIndex - 1);
         }
       }
     }
   }
   super.visit(n, arg);
 }
  @Override
  public void visit(MethodDeclaration md, T ctx) {

    BlockStmt block = md.getBody();
    if (block != null) {
      List<Statement> stmts = block.getStmts();
      if (stmts != null) {
        if (stmts.size() == 2) {
          Statement firstStmt = stmts.get(0);
          if (firstStmt instanceof IfStmt) {
            Statement lastStmt = stmts.get(1);
            if (lastStmt instanceof ReturnStmt) {
              IfStmt ifStmt = (IfStmt) firstStmt;
              Expression condition = ifStmt.getCondition();
              if (condition instanceof BinaryExpr) {
                BinaryExpr be = (BinaryExpr) condition;
                if (be.getOperator().equals(BinaryExpr.Operator.equals)) {
                  if (be.getRight() instanceof NullLiteralExpr) {
                    Expression leftExpr = be.getLeft();
                    ReturnStmt returnStmt = (ReturnStmt) lastStmt;
                    Expression returnedExpr = returnStmt.getExpr();

                    CheckSameObjectField<T> visitor1 = new CheckSameObjectField<T>();
                    leftExpr.accept(visitor1, ctx);
                    String variableNameOfCheckingNull = visitor1.getName();

                    visitor1 = new CheckSameObjectField<T>();
                    returnedExpr.accept(visitor1, ctx);
                    String variableNameOfReturnExpression = visitor1.getName();

                    if (variableNameOfCheckingNull != null
                        && variableNameOfReturnExpression != null
                        && variableNameOfCheckingNull.equals(variableNameOfReturnExpression)) {

                      Statement thenStmt = ifStmt.getThenStmt();
                      if (thenStmt instanceof BlockStmt) {
                        BlockStmt thenBlock = (BlockStmt) thenStmt;
                        List<Statement> blockStmts = thenBlock.getStmts();
                        if (blockStmts != null && blockStmts.size() == 1) {

                          SynchronizedStmt synchStmt = new SynchronizedStmt();
                          BlockStmt innerBlock = new BlockStmt();
                          List<Statement> innerStmts = new LinkedList<Statement>();
                          BlockStmt newBlock = new BlockStmt();
                          List<Statement> newStmts = new LinkedList<Statement>();
                          newStmts.add(blockStmts.get(0));
                          newBlock.setStmts(newStmts);

                          IfStmt newIf =
                              new IfStmt(
                                  new BinaryExpr(
                                      new NameExpr(variableNameOfReturnExpression),
                                      new NullLiteralExpr(),
                                      BinaryExpr.Operator.equals),
                                  newBlock,
                                  null);
                          innerStmts.add(newIf);
                          innerBlock.setStmts(innerStmts);
                          synchStmt.setBlock(innerBlock);
                          synchStmt.setExpr(new ThisExpr());
                          blockStmts.clear();
                          blockStmts.add(synchStmt);
                        }

                      } else {
                        BlockStmt blockStmt = new BlockStmt();
                        List<Statement> stmtList = new LinkedList<Statement>();
                        SynchronizedStmt synchStmt = new SynchronizedStmt();
                        BlockStmt innerBlock = new BlockStmt();
                        List<Statement> innerStmts = new LinkedList<Statement>();
                        IfStmt newIf =
                            new IfStmt(
                                new BinaryExpr(
                                    new NameExpr(variableNameOfReturnExpression),
                                    new NullLiteralExpr(),
                                    BinaryExpr.Operator.equals),
                                thenStmt,
                                null);
                        innerStmts.add(newIf);
                        innerBlock.setStmts(innerStmts);
                        synchStmt.setBlock(innerBlock);
                        synchStmt.setExpr(new ThisExpr());
                        stmtList.add(synchStmt);
                        blockStmt.setStmts(stmtList);
                        ifStmt.setThenStmt(blockStmt);
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }