@Override
 public boolean visit(ForStatement node) {
   List<Expression> initializers = node.getInitializers();
   // The for-loop initializers can either be a single variable declaration
   // expression or a list of initializer expressions.
   if (initializers.size() == 1 && initializers.get(0) instanceof VariableDeclarationExpression) {
     VariableDeclarationExpression decl = (VariableDeclarationExpression) initializers.get(0);
     extractVariableDeclarationFragments(
         decl.getFragments(), TreeUtil.asStatementList(node).subList(0, 0));
   } else {
     extractExpressionList(initializers, TreeUtil.asStatementList(node).subList(0, 0), false);
   }
   Expression expr = node.getExpression();
   if (expr != null) {
     newExpression(expr);
     expr.accept(this);
     List<VariableAccess> toExtract = getUnsequencedAccesses();
     if (!toExtract.isEmpty()) {
       // Convert "if (;cond;)" into "if (;;) { if (!(cond)) break; ...}".
       List<Statement> stmtList = TreeUtil.asStatementList(node.getBody()).subList(0, 0);
       extractOrderedAccesses(stmtList, currentTopNode, toExtract);
       stmtList.add(createLoopTermination(node.getExpression()));
       node.setExpression(null);
     }
   }
   extractExpressionList(node.getUpdaters(), TreeUtil.asStatementList(node.getBody()), true);
   node.getBody().accept(this);
   return false;
 }
 private void extractVariableDeclarationFragments(
     List<VariableDeclarationFragment> fragments, List<Statement> stmtList) {
   for (int i = 0; i < fragments.size(); i++) {
     VariableDeclarationFragment frag = fragments.get(i);
     Expression init = frag.getInitializer();
     if (init == null) {
       continue;
     }
     newExpression(init);
     init.accept(this);
     List<VariableAccess> toExtract = getUnsequencedAccesses();
     if (!toExtract.isEmpty()) {
       if (i > 0) {
         // Extract all fragments before the current one to preserve ordering.
         VariableDeclarationStatement newDecl =
             new VariableDeclarationStatement(fragments.get(0).copy());
         for (int j = 1; j < i; j++) {
           newDecl.getFragments().add(fragments.get(j).copy());
         }
         stmtList.add(newDecl);
         fragments.subList(0, i).clear();
       }
       extractOrderedAccesses(stmtList, currentTopNode, toExtract);
       i = 0;
     }
   }
 }
 private void visitAndExtract(Expression expr, Statement stmt) {
   if (expr != null) {
     newExpression(expr);
     expr.accept(this);
     extractUnsequenced(stmt);
   }
 }
 @Override
 public boolean visit(SuperConstructorInvocation node) {
   newExpression(node);
   for (Expression arg : node.getArguments()) {
     arg.accept(this);
   }
   extractUnsequenced(node);
   return false;
 }
 @Override
 public boolean visit(Assignment node) {
   Expression lhs = node.getLeftHandSide();
   IVariableBinding lhsVar = TreeUtil.getVariableBinding(lhs);
   // Access order is important. If the lhs is a variable, then we must record
   // its access after visiting the rhs. Otherwise, visit both sides.
   if (lhsVar == null) {
     lhs.accept(this);
   }
   node.getRightHandSide().accept(this);
   addVariableAccess(lhsVar, node, true);
   return false;
 }
 private void extractExpressionList(
     List<Expression> expressions, List<Statement> stmtList, boolean extractModifiedExpression) {
   for (int i = 0; i < expressions.size(); i++) {
     Expression expr = expressions.get(i);
     newExpression(expr);
     expr.accept(this);
     List<VariableAccess> unsequencedAccesses = getUnsequencedAccesses();
     if (!unsequencedAccesses.isEmpty()) {
       for (int j = 0; j < i; j++) {
         stmtList.add(new ExpressionStatement(expressions.get(j).copy()));
       }
       expressions.subList(0, i).clear();
       extractOrderedAccesses(stmtList, currentTopNode, unsequencedAccesses);
       i = 0;
       if (extractModifiedExpression) {
         stmtList.add(new ExpressionStatement(expressions.get(0).copy()));
         expressions.remove(0);
         i = -1;
       }
     }
   }
 }
 @Override
 public boolean visit(AssertStatement node) {
   Expression expr = node.getExpression();
   visitAndExtract(expr, node);
   Expression msg = node.getMessage();
   if (msg != null) {
     newExpression(msg);
     msg.accept(this);
     List<VariableAccess> toExtract = getUnsequencedAccesses();
     if (!toExtract.isEmpty()) {
       // If the message expression needs any extraction, then we first extract
       // the entire boolean expression to preserve ordering between the two.
       IVariableBinding exprVar =
           new GeneratedVariableBinding(
               "unseq$" + count++, 0, expr.getTypeBinding(), false, false, null, currentMethod);
       TreeUtil.insertBefore(
           node, new VariableDeclarationStatement(exprVar, node.getExpression().copy()));
       node.setExpression(new SimpleName(exprVar));
       extractOrderedAccesses(
           TreeUtil.asStatementList(node).subList(0, 0), currentTopNode, toExtract);
     }
   }
   return false;
 }