/*
  * (non-Javadoc)
  *
  * @see org.walkmod.javalang.visitors.VoidVisitorAdapter#visit(org.walkmod.javalang.ast.body.MethodDeclaration,
  * java.lang.Object)
  */
 @SuppressWarnings("unchecked")
 @Override
 public void visit(MethodDeclaration n, VisitorContext arg) {
   Map<String, Object> m = variablesMap.get(classStack.peek());
   if (!methodStack.isEmpty()) {
     Object[] strings = methodStack.toArray();
     for (int i = 0; i < methodStack.size(); i++) {
       if (m.containsKey(strings[i])) {
         m = (Map<String, Object>) m.get(strings[i]);
       }
     }
   }
   String name = getUniqueMethodName(n);
   Map<String, String> temp = new HashMap<String, String>();
   temp.put("this", getActualType(n.getType()));
   m.put(name, temp);
   methodStack.push(name);
   super.visit(n, arg);
   m.remove(methodStack.pop());
 }
  @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);
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }