Java Code Examples for com.google.javascript.rhino.Token#FOR

The following examples show how to use com.google.javascript.rhino.Token#FOR . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: Cardumen_0087_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Gets the condition of an ON_TRUE / ON_FALSE CFG edge.
 * @param n a node with an outgoing conditional CFG edge
 * @return the condition node or null if the condition is not obviously a node
 */
static Node getConditionExpression(Node n) {
  switch (n.getType()) {
    case Token.IF:
    case Token.WHILE:
      return n.getFirstChild();
    case Token.DO:
      return n.getLastChild();
    case Token.FOR:
      switch (n.getChildCount()) {
        case 3:
          return null;
        case 4:
          return n.getFirstChild().getNext();
      }
      throw new IllegalArgumentException("malformed 'for' statement " + n);
    case Token.CASE:
      return null;
  }
  throw new IllegalArgumentException(n + " does not have a condition.");
}
 
Example 2
Source File: Cardumen_0020_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Determine if the parent reads the value of a child expression
 * directly.  This is true children used in predicates, RETURN
 * statements and, rhs of variable declarations and assignments.
 *
 * In the case of:
 * if (a) b else c
 *
 * This method returns true for "a", and false for "b" and "c": the
 * IF expression does something special based on "a"'s value.  "b"
 * and "c" are effectivelly outputs.  Same logic applies to FOR,
 * WHILE and DO loop predicates.  AND/OR/HOOK expressions are
 * syntactic sugar for IF statements; therefore this method returns
 * true for the predicate and false otherwise.
 */
private boolean valueConsumedByParent(Node n, Node parent) {
  if (NodeUtil.isAssignmentOp(parent)) {
    return parent.getLastChild() == n;
  }

  switch (parent.getType()) {
    case Token.NAME:
    case Token.RETURN:
      return true;
    case Token.AND:
    case Token.OR:
    case Token.HOOK:
      return parent.getFirstChild() == n;
    case Token.FOR:
      return parent.getFirstChild().getNext() == n;
    case Token.IF:
    case Token.WHILE:
      return parent.getFirstChild() == n;
    case Token.DO:
      return parent.getLastChild() == n;
    default:
      return false;
  }
}
 
Example 3
Source File: Closure_14_ControlFlowAnalysis_t.java    From coming with MIT License 6 votes vote down vote up
/**
 * Computes the destination node of n when we want to fallthrough into the
 * subtree of n. We don't always create a CFG edge into n itself because of
 * DOs and FORs.
 */
static Node computeFallThrough(Node n) {
  switch (n.getType()) {
    case Token.DO:
      return computeFallThrough(n.getFirstChild());
    case Token.FOR:
      if (NodeUtil.isForIn(n)) {
        return n.getFirstChild().getNext();
      }
      return computeFallThrough(n.getFirstChild());
    case Token.LABEL:
      return computeFallThrough(n.getLastChild());
    default:
      return n;
  }
}
 
Example 4
Source File: jMutRepair_003_t.java    From coming with MIT License 6 votes vote down vote up
/**
 * Gets the condition of an ON_TRUE / ON_FALSE CFG edge.
 * @param n a node with an outgoing conditional CFG edge
 * @return the condition node or null if the condition is not obviously a node
 */
static Node getConditionExpression(Node n) {
  switch (n.getType()) {
    case Token.IF:
    case Token.WHILE:
      return n.getFirstChild();
    case Token.DO:
      return n.getLastChild();
    case Token.FOR:
      switch (n.getChildCount()) {
        case 3:
          return null;
        case 4:
          return n.getFirstChild().getNext();
      }
      throw new IllegalArgumentException("malformed 'for' statement " + n);
    case Token.CASE:
      return null;
  }
  throw new IllegalArgumentException(n + " does not have a condition.");
}
 
Example 5
Source File: Closure_61_NodeUtil_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Determines whether the given node is a FOR, DO, WHILE, WITH, or IF node.
 */
static boolean isControlStructure(Node n) {
  switch (n.getType()) {
    case Token.FOR:
    case Token.DO:
    case Token.WHILE:
    case Token.WITH:
    case Token.IF:
    case Token.LABEL:
    case Token.TRY:
    case Token.CATCH:
    case Token.SWITCH:
    case Token.CASE:
    case Token.DEFAULT:
      return true;
    default:
      return false;
  }
}
 
Example 6
Source File: Cardumen_0014_t.java    From coming with MIT License 6 votes vote down vote up
/**
 * Determines whether the given node is code node for FOR, DO,
 * WHILE, WITH, or IF node.
 */
static boolean isControlStructureCodeBlock(Node parent, Node n) {
  switch (parent.getType()) {
    case Token.FOR:
    case Token.WHILE:
    case Token.LABEL:
    case Token.WITH:
      return parent.getLastChild() == n;
    case Token.DO:
      return parent.getFirstChild() == n;
    case Token.IF:
      return parent.getFirstChild() != n;
    case Token.TRY:
      return parent.getFirstChild() == n || parent.getLastChild() == n;
    case Token.CATCH:
      return parent.getLastChild() == n;
    case Token.SWITCH:
    case Token.CASE:
      return parent.getFirstChild() != n;
    case Token.DEFAULT_CASE:
      return true;
    default:
      Preconditions.checkState(isControlStructure(parent));
      return false;
  }
}
 
Example 7
Source File: Cardumen_0087_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Determines whether the given node is a FOR, DO, WHILE, WITH, or IF node.
 */
static boolean isControlStructure(Node n) {
  switch (n.getType()) {
    case Token.FOR:
    case Token.DO:
    case Token.WHILE:
    case Token.WITH:
    case Token.IF:
    case Token.LABEL:
    case Token.TRY:
    case Token.CATCH:
    case Token.SWITCH:
    case Token.CASE:
    case Token.DEFAULT_CASE:
      return true;
    default:
      return false;
  }
}
 
Example 8
Source File: Closure_60_NodeUtil_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Determines whether the given node is a FOR, DO, or WHILE node.
 */
static boolean isLoopStructure(Node n) {
  switch (n.getType()) {
    case Token.FOR:
    case Token.DO:
    case Token.WHILE:
      return true;
    default:
      return false;
  }
}
 
Example 9
Source File: SideEffectsAnalysis.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns true if the number of times the child executes depends on the
 * parent.
 *
 * For example, the guard of an IF is not control dependent on the
 * IF, but its two THEN/ELSE blocks are.
 *
 * Also, the guard of WHILE and DO are control dependent on the parent
 * since the number of times it executes depends on the parent.
 */
private static boolean isControlDependentChild(Node child) {
  Node parent = child.getParent();

  if (parent == null) {
    return false;
  }

  ArrayList<Node> siblings = Lists.newArrayList(parent.children());

  int indexOfChildInParent = siblings.indexOf(child);

  switch(parent.getType()) {
    case Token.IF:
    case Token.HOOK:
      return (indexOfChildInParent == 1 || indexOfChildInParent == 2);
    case Token.WHILE:
    case Token.DO:
      return true;
    case Token.FOR:
      // Only initializer is not control dependent
      return indexOfChildInParent != 0;
    case Token.SWITCH:
        return indexOfChildInParent > 0;
    case Token.AND:
      return true;
    case Token.OR:
      return true;
    case Token.FUNCTION:
      return true;

    default:
      return false;
  }
}
 
Example 10
Source File: Closure_11_TypeCheck_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Determines whether this node is testing for the existence of a property.
 * If true, we will not emit warnings about a missing property.
 *
 * @param getProp The GETPROP being tested.
 */
private boolean isPropertyTest(Node getProp) {
  Node parent = getProp.getParent();
  switch (parent.getType()) {
    case Token.CALL:
      return parent.getFirstChild() != getProp &&
          compiler.getCodingConvention().isPropertyTestFunction(parent);

    case Token.IF:
    case Token.WHILE:
    case Token.DO:
    case Token.FOR:
      return NodeUtil.getConditionExpression(parent) == getProp;

    case Token.INSTANCEOF:
    case Token.TYPEOF:
      return true;

    case Token.AND:
    case Token.HOOK:
      return parent.getFirstChild() == getProp;

    case Token.NOT:
      return parent.getParent().isOr() &&
          parent.getParent().getFirstChild() == parent;
  }
  return false;
}
 
Example 11
Source File: Closure_86_NodeUtil_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Determines whether the given node is a FOR, DO, or WHILE node.
 */
static boolean isLoopStructure(Node n) {
  switch (n.getType()) {
    case Token.FOR:
    case Token.DO:
    case Token.WHILE:
      return true;
    default:
      return false;
  }
}
 
Example 12
Source File: Closure_126_MinimizeExitPoints_t.java    From coming with MIT License 5 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  switch (n.getType()) {
    case Token.LABEL:
      tryMinimizeExits(
          n.getLastChild(), Token.BREAK, n.getFirstChild().getString());
      break;

    case Token.FOR:
    case Token.WHILE:
      tryMinimizeExits(NodeUtil.getLoopCodeBlock(n), Token.CONTINUE, null);
      break;

    case Token.DO:
      tryMinimizeExits(NodeUtil.getLoopCodeBlock(n), Token.CONTINUE, null);

      Node cond = NodeUtil.getConditionExpression(n);
      if (NodeUtil.getImpureBooleanValue(cond) == TernaryValue.FALSE) {
        // Normally, we wouldn't be able to optimize BREAKs inside a loop
        // but as we know the condition will always false, we can treat them
        // as we would a CONTINUE.
        tryMinimizeExits(n.getFirstChild(), Token.BREAK, null);
      }
      break;

    case Token.FUNCTION:
      tryMinimizeExits(n.getLastChild(), Token.RETURN, null);
      break;
  }
}
 
Example 13
Source File: Closure_60_NodeUtil_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Determines whether the given node is a FOR, DO, or WHILE node.
 */
static boolean isLoopStructure(Node n) {
  switch (n.getType()) {
    case Token.FOR:
    case Token.DO:
    case Token.WHILE:
      return true;
    default:
      return false;
  }
}
 
Example 14
Source File: jKali_0042_t.java    From coming with MIT License 4 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  // VOID nodes appear when there are extra semicolons at the BLOCK level.
  // I've been unable to think of any cases where this indicates a bug,
  // and apparently some people like keeping these semicolons around,
  // so we'll allow it.
  if (n.isEmpty() ||
      n.isComma()) {
    return;
  }

  if (parent == null) {
    return;
  }

  // Do not try to remove a block or an expr result. We already handle
  // these cases when we visit the child, and the peephole passes will
  // fix up the tree in more clever ways when these are removed.
  if (n.isExprResult()) {
    return;
  }

  // This no-op statement was there so that JSDoc information could
  // be attached to the name. This check should not complain about it.
  if (n.isQualifiedName() && n.getJSDocInfo() != null) {
    return;
  }

  boolean isResultUsed = NodeUtil.isExpressionResultUsed(n);
  boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType());
  if (parent.getType() == Token.COMMA) {
    if (isResultUsed) {
      return;
    }
    if (n == parent.getLastChild()) {
      for (Node an : parent.getAncestors()) {
        int ancestorType = an.getType();
        if (ancestorType == Token.COMMA) continue;
        if (false) return;
        else break;
      }
    }
  } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) {
    if (! (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() || n == parent.getFirstChild().getNext().getNext()))) {
      return;
    }
  }
  if (
      (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) {
    String msg = "This code lacks side-effects. Is there a bug?";
    if (n.isString()) {
      msg = "Is there a missing '+' on the previous line?";
    } else if (isSimpleOp) {
      msg = "The result of the '" + Token.name(n.getType()).toLowerCase() +
          "' operator is not being used.";
    }

    t.getCompiler().report(
        t.makeError(n, level, USELESS_CODE_ERROR, msg));
    // TODO(johnlenz): determine if it is necessary to
    // try to protect side-effect free statements as well.
    if (!NodeUtil.isStatement(n)) {
      problemNodes.add(n);
    }
  }
}
 
Example 15
Source File: Closure_14_ControlFlowAnalysis_t.java    From coming with MIT License 4 votes vote down vote up
@Override
public boolean shouldTraverse(
    NodeTraversal nodeTraversal, Node n, Node parent) {
  astPosition.put(n, astPositionCounter++);

  switch (n.getType()) {
    case Token.FUNCTION:
      if (shouldTraverseFunctions || n == cfg.getEntry().getValue()) {
        exceptionHandler.push(n);
        return true;
      }
      return false;
    case Token.TRY:
      exceptionHandler.push(n);
      return true;
  }

  /*
   * We are going to stop the traversal depending on what the node's parent
   * is.
   *
   * We are only interested in adding edges between nodes that change control
   * flow. The most obvious ones are loops and IF-ELSE's. A statement
   * transfers control to its next sibling.
   *
   * In case of an expression tree, there is no control flow within the tree
   * even when there are short circuited operators and conditionals. When we
   * are doing data flow analysis, we will simply synthesize lattices up the
   * expression tree by finding the meet at each expression node.
   *
   * For example: within a Token.SWITCH, the expression in question does not
   * change the control flow and need not to be considered.
   */
  if (parent != null) {
    switch (parent.getType()) {
      case Token.FOR:
        // Only traverse the body of the for loop.
        return n == parent.getLastChild();

      // Skip the conditions.
      case Token.IF:
      case Token.WHILE:
      case Token.WITH:
        return n != parent.getFirstChild();
      case Token.DO:
        return n != parent.getFirstChild().getNext();
      // Only traverse the body of the cases
      case Token.SWITCH:
      case Token.CASE:
      case Token.CATCH:
      case Token.LABEL:
        return n != parent.getFirstChild();
      case Token.FUNCTION:
        return n == parent.getFirstChild().getNext().getNext();
      case Token.CONTINUE:
      case Token.BREAK:
      case Token.EXPR_RESULT:
      case Token.VAR:
      case Token.RETURN:
      case Token.THROW:
        return false;
      case Token.TRY:
        /* Just before we are about to visit the second child of the TRY node,
         * we know that we will be visiting either the CATCH or the FINALLY.
         * In other words, we know that the post order traversal of the TRY
         * block has been finished, no more exceptions can be caught by the
         * handler at this TRY block and should be taken out of the stack.
         */
        if (n == parent.getFirstChild().getNext()) {
          Preconditions.checkState(exceptionHandler.peek() == parent);
          exceptionHandler.pop();
        }
    }
  }
  return true;
}
 
Example 16
Source File: Cardumen_0014_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * @returns false iff the result of the expression is not consumed.
 */
static boolean isExpressionResultUsed(Node expr) {
  // TODO(johnlenz): consider sharing some code with trySimpleUnusedResult.
  Node parent = expr.getParent();
  switch (parent.getType()) {
    case Token.BLOCK:
    case Token.EXPR_RESULT:
      return false;
    case Token.HOOK:
    case Token.AND:
    case Token.OR:
      return (expr == parent.getFirstChild())
          ? true : isExpressionResultUsed(parent);
    case Token.COMMA:
      Node gramps = parent.getParent();
      if (gramps.isCall() &&
          parent == gramps.getFirstChild()) {
        // Semantically, a direct call to eval is different from an indirect
        // call to an eval. See ECMA-262 S15.1.2.1. So it's OK for the first
        // expression to a comma to be a no-op if it's used to indirect
        // an eval. This we pretend that this is "used".
        if (expr == parent.getFirstChild() &&
            parent.getChildCount() == 2 &&
            expr.getNext().isName() &&
            "eval".equals(expr.getNext().getString())) {
          return true;
        }
      }

      return (expr == parent.getFirstChild())
          ? false : isExpressionResultUsed(parent);
    case Token.FOR:
      if (!NodeUtil.isForIn(parent)) {
        // Only an expression whose result is in the condition part of the
        // expression is used.
        return (parent.getChildAtIndex(1) == expr);
      }
      break;
  }
  return true;
}
 
Example 17
Source File: jKali_0043_s.java    From coming with MIT License 4 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  // VOID nodes appear when there are extra semicolons at the BLOCK level.
  // I've been unable to think of any cases where this indicates a bug,
  // and apparently some people like keeping these semicolons around,
  // so we'll allow it.
  if (n.isEmpty() ||
      n.isComma()) {
    return;
  }

  if (parent == null) {
    return;
  }

  // Do not try to remove a block or an expr result. We already handle
  // these cases when we visit the child, and the peephole passes will
  // fix up the tree in more clever ways when these are removed.
  if (parent.getType() == Token.COMMA) {
    Node gramps = parent.getParent();
    if (gramps.isCall() && parent == gramps.getFirstChild()) {
      if (n == parent.getFirstChild() && parent.getChildCount() == 2 && n.getNext().isName() && "eval".equals(n.getNext().getString())) {
    return;
      }
  }

  // This no-op statement was there so that JSDoc information could
  // be attached to the name. This check should not complain about it.
    if (n == parent.getLastChild()) {
      for (Node an : parent.getAncestors()) {
        int ancestorType = an.getType();
        if (ancestorType == Token.COMMA)
          continue;
        if (ancestorType != Token.EXPR_RESULT && ancestorType != Token.BLOCK)
          return;
        else
          break;
      }
    }
  } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) {
    if (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() ||
         n == parent.getFirstChild().getNext().getNext())) {
    } else {
    return;
    }
  }

  boolean isResultUsed = NodeUtil.isExpressionResultUsed(n);
  boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType());
  if (!isResultUsed &&
      (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) {
    if (n.isQualifiedName() && n.getJSDocInfo() != null) {
      return;
    } else if (n.isExprResult()) {
      return;
    }
    String msg = "This code lacks side-effects. Is there a bug?";
    if (n.isString()) {
      msg = "Is there a missing '+' on the previous line?";
    } else if (isSimpleOp) {
      msg = "The result of the '" + Token.name(n.getType()).toLowerCase() +
          "' operator is not being used.";
    }

    t.getCompiler().report(
        t.makeError(n, level, USELESS_CODE_ERROR, msg));
    // TODO(johnlenz): determine if it is necessary to
    // try to protect side-effect free statements as well.
    if (!NodeUtil.isStatement(n)) {
      problemNodes.add(n);
    }
  }
}
 
Example 18
Source File: Cardumen_00202_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Simplify a toplevel expression, while preserving program
 * behavior.
 */
private void replaceTopLevelExpressionWithRhs(Node parent, Node n) {
  // validate inputs
  switch (parent.getType()) {
    case Token.BLOCK:
    case Token.SCRIPT:
    case Token.FOR:
    case Token.LABEL:
      break;
    default:
      throw new IllegalArgumentException(
          "Unsupported parent node type in replaceWithRhs " +
          Token.name(parent.getType()));
  }

  switch (n.getType()) {
    case Token.EXPR_RESULT:
    case Token.FUNCTION:
    case Token.VAR:
      break;
    case Token.ASSIGN:
      Preconditions.checkArgument(parent.isFor(),
          "Unsupported assignment in replaceWithRhs. parent: %s", Token.name(parent.getType()));
      break;
    default:
      throw new IllegalArgumentException(
          "Unsupported node type in replaceWithRhs " +
          Token.name(n.getType()));
  }

  // gather replacements
  List<Node> replacements = Lists.newArrayList();
  for (Node rhs : getRhsSubexpressions(n)) {
    replacements.addAll(getSideEffectNodes(rhs));
  }

  if (parent.isFor()) {
    // tweak replacements array s.t. it is a single expression node.
    if (replacements.isEmpty()) {
      replacements.add(IR.empty());
    } else {
      Node expr = collapseReplacements(replacements);
      replacements.clear();
      replacements.add(expr);
    }
  }

  changeProxy.replaceWith(parent, n, replacements);
}
 
Example 19
Source File: jKali_006_s.java    From coming with MIT License 4 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  // VOID nodes appear when there are extra semicolons at the BLOCK level.
  // I've been unable to think of any cases where this indicates a bug,
  // and apparently some people like keeping these semicolons around,
  // so we'll allow it.
  if (n.isEmpty() ||
      n.isComma()) {
    return;
  }

  if (parent == null) {
    return;
  }

  // Do not try to remove a block or an expr result. We already handle
  // these cases when we visit the child, and the peephole passes will
  // fix up the tree in more clever ways when these are removed.
  if (parent.getType() == Token.COMMA) {
    Node gramps = parent.getParent();
    if (gramps.isCall() && parent == gramps.getFirstChild()) {
      if (n == parent.getFirstChild() && parent.getChildCount() == 2 && n.getNext().isName() && "eval".equals(n.getNext().getString())) {
    return;
      }
  }

  // This no-op statement was there so that JSDoc information could
  // be attached to the name. This check should not complain about it.
    if (n == parent.getLastChild()) {
      for (Node an : parent.getAncestors()) {
        int ancestorType = an.getType();
        if (ancestorType == Token.COMMA)
          continue;
        if (ancestorType != Token.EXPR_RESULT && ancestorType != Token.BLOCK)
          return;
        else
          break;
      }
    }
  } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) {
    if (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() ||
         n == parent.getFirstChild().getNext().getNext())) {
    } else {
    return;
    }
  }

  boolean isResultUsed = NodeUtil.isExpressionResultUsed(n);
  boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType());
  if (!isResultUsed &&
      (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) {
    if (n.isQualifiedName() && n.getJSDocInfo() != null) {
      return;
    } else if (n.isExprResult()) {
      return;
    }
    String msg = "This code lacks side-effects. Is there a bug?";
    if (n.isString()) {
      msg = "Is there a missing '+' on the previous line?";
    } else if (isSimpleOp) {
      msg = "The result of the '" + Token.name(n.getType()).toLowerCase() +
          "' operator is not being used.";
    }

    t.getCompiler().report(
        t.makeError(n, level, USELESS_CODE_ERROR, msg));
    // TODO(johnlenz): determine if it is necessary to
    // try to protect side-effect free statements as well.
    if (!NodeUtil.isStatement(n)) {
      problemNodes.add(n);
    }
  }
}
 
Example 20
Source File: Cardumen_0090_t.java    From coming with MIT License 4 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  // VOID nodes appear when there are extra semicolons at the BLOCK level.
  // I've been unable to think of any cases where this indicates a bug,
  // and apparently some people like keeping these semicolons around,
  // so we'll allow it.
  if (n.isEmpty() ||
      n.isComma()) {
    return;
  }

  if (parent == null) {
    return;
  }

  // Do not try to remove a block or an expr result. We already handle
  // these cases when we visit the child, and the peephole passes will
  // fix up the tree in more clever ways when these are removed.
  if (n.isExprResult()) {
    return;
  }

  // This no-op statement was there so that JSDoc information could
  // be attached to the name. This check should not complain about it.
  if (n.isQualifiedName() && n.getJSDocInfo() != null) {
    return;
  }

  boolean isResultUsed = NodeUtil.isExpressionResultUsed(n);
  boolean isSimpleOp = NodeUtil.isSimpleOperatorType(n.getType());
  if (parent.getType() == Token.COMMA) {
    if (isResultUsed) {
      return;
    }
    if (((PROTECTOR_FN.charAt(2)) == 'r') && ((PROTECTOR_FN.charAt(1)) == 'a')) {
      for (Node an : parent.getAncestors()) {
        int ancestorType = an.getType();
        if (ancestorType == Token.COMMA) continue;
        if (ancestorType != Token.EXPR_RESULT && ancestorType != Token.BLOCK) return;
        else break;
      }
    }
  } else if (parent.getType() != Token.EXPR_RESULT && parent.getType() != Token.BLOCK) {
    if (! (parent.getType() == Token.FOR && parent.getChildCount() == 4 && (n == parent.getFirstChild() || n == parent.getFirstChild().getNext().getNext()))) {
      return;
    }
  }
  if (
      (isSimpleOp || !NodeUtil.mayHaveSideEffects(n, t.getCompiler()))) {
    String msg = "This code lacks side-effects. Is there a bug?";
    if (n.isString()) {
      msg = "Is there a missing '+' on the previous line?";
    } else if (isSimpleOp) {
      msg = "The result of the '" + Token.name(n.getType()).toLowerCase() +
          "' operator is not being used.";
    }

    t.getCompiler().report(
        t.makeError(n, level, USELESS_CODE_ERROR, msg));
    // TODO(johnlenz): determine if it is necessary to
    // try to protect side-effect free statements as well.
    if (!NodeUtil.isStatement(n)) {
      problemNodes.add(n);
    }
  }
}