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

The following examples show how to use com.google.javascript.rhino.Token#RETURN . 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: Closure_114_NameAnalyzer_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 effectively 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 2
Source File: Closure_114_NameAnalyzer_t.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 effectively 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_20_PeepholeSubstituteAlternateSyntax_t.java    From coming with MIT License 6 votes vote down vote up
private boolean statementMustExitParent(Node n) {
  switch (n.getType()) {
    case Token.THROW:
    case Token.RETURN:
      return true;
    case Token.BLOCK:
      if (n.hasChildren()) {
        Node child = n.getLastChild();
        return statementMustExitParent(child);
      }
      return false;
    // TODO(johnlenz): handle TRY/FINALLY
    case Token.FUNCTION:
    default:
      return false;
  }
}
 
Example 4
Source File: Closure_55_FunctionRewriter_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * @return function return value node if function body contains a
 * single return statement.  Otherwise, null.
 */
protected final Node maybeGetSingleReturnRValue(Node functionNode) {
  Node body = functionNode.getLastChild();
  if (!body.hasOneChild()) {
    return null;
  }

  Node statement = body.getFirstChild();
  if (statement.getType() == Token.RETURN) {
    return statement.getFirstChild();
  }
  return null;
}
 
Example 5
Source File: Closure_105_FoldConstants_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * @return Whether the node is a block with a single statement that is
 *     an return.
 */
private boolean isReturnExpressBlock(Node n) {
  if (n.getType() == Token.BLOCK) {
    if (n.hasOneChild()) {
      Node first = n.getFirstChild();
      if (first.getType() == Token.RETURN) {
        return first.hasOneChild();
      }
    }
  }

  return false;
}
 
Example 6
Source File: Nopol2017_0047_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * @return function return value node if function body contains a
 * single return statement.  Otherwise, null.
 */
protected final Node maybeGetSingleReturnRValue(Node functionNode) {
  Node body = functionNode.getLastChild();
  if (!body.hasOneChild()) {
    return null;
  }

  Node statement = body.getFirstChild();
  if (statement.getType() == Token.RETURN) {
    return statement.getFirstChild();
  }
  return null;
}
 
Example 7
Source File: StatementFusion.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
private void fuseIntoOneStatement(Node block) {
  Node cur = block.removeFirstChild();

  // Starts building a tree.
  Node commaTree = cur.removeFirstChild();


  while (block.hasMoreThanOneChild()) {
    Node next = block.removeFirstChild().removeFirstChild();
    commaTree = fuseExpressionIntoExpression(commaTree, next);
  }

  Preconditions.checkState(block.hasOneChild());
  Node last = block.getLastChild();

  // Now we are just left with two statements. The comma tree of the first
  // n - 1 statements (which can be used in an expression) and the last
  // statement. We perform specific fusion based on the last statement's type.
  switch(last.getType()) {
    case Token.IF:
    case Token.RETURN:
    case Token.THROW:
    case Token.SWITCH:
    case Token.EXPR_RESULT:
      fuseExpresssonIntoFirstChild(commaTree, last);
      return;
    case Token.FOR:
      if (NodeUtil.isForIn(last)) {
        fuseExpresssonIntoSecondChild(commaTree, last);
      }
      return ;
    default:
      throw new IllegalStateException("Statement fusion missing.");
  }
}
 
Example 8
Source File: ExpressionDecomposer.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/**
 * @return The statement containing the expression. null if subExpression
 *     is not contain by in by a Node where inlining is known to be possible.
 *     For example, a WHILE node condition expression.
 */
static Node findExpressionRoot(Node subExpression) {
  Node child = subExpression;
  for (Node parent : child.getAncestors()) {
    int parentType = parent.getType();
    switch (parentType) {
      // Supported expression roots:
      // SWITCH and IF can have multiple children, but the CASE, DEFAULT,
      // or BLOCK will be encountered first for any of the children other
      // than the condition.
      case Token.EXPR_RESULT:
      case Token.IF:
      case Token.SWITCH:
      case Token.RETURN:
      case Token.VAR:
        Preconditions.checkState(child == parent.getFirstChild());
        return parent;
      // Any of these indicate an unsupported expression:
      case Token.SCRIPT:
      case Token.BLOCK:
      case Token.LABEL:
      case Token.CASE:
      case Token.DEFAULT_CASE:
        return null;
    }
    child = parent;
  }

  throw new IllegalStateException("Unexpected AST structure.");
}
 
Example 9
Source File: Cardumen_0023_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * @return function return value node if function body contains a
 * single return statement.  Otherwise, null.
 */
protected final Node maybeGetSingleReturnRValue(Node functionNode) {
  Node body = functionNode.getLastChild();
  if (!body.hasOneChild()) {
    return null;
  }

  Node statement = body.getFirstChild();
  if (statement.getType() == Token.RETURN) {
    return statement.getFirstChild();
  }
  return null;
}
 
Example 10
Source File: UnreachableCodeElimination.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Tries to remove n if it is an unconditional branch node (break, continue,
 * or return) and the target of n is the same as the the follow of n.
 * That is, if removing n preserves the control flow. Also if n targets
 * another unconditional branch, this function will recursively try to remove
 * the target branch as well. The reason why we want to cascade this removal
 * is because we only run this pass once. If we have code such as
 *
 * break -> break -> break
 *
 * where all 3 breaks are useless, then the order of removal matters. When we
 * first look at the first break, we see that it branches to the 2nd break.
 * However, if we remove the last break, the 2nd break becomes useless and
 * finally the first break becomes useless as well.
 *
 * @return The target of this jump. If the target is also useless jump,
 *     the target of that useless jump recursively.
 */
@SuppressWarnings("fallthrough")
private Node tryRemoveUnconditionalBranching(Node n) {
  /*
   * For each unconditional branching control flow node, check to see
   * if the ControlFlowAnalysis.computeFollowNode of that node is same as
   * the branching target. If it is, the branch node is safe to be removed.
   *
   * This is not as clever as MinimizeExitPoints because it doesn't do any
   * if-else conversion but it handles more complicated switch statements
   * much more nicely.
   */

  // If n is null the target is the end of the function, nothing to do.
  if (n == null) {
     return n;
  }

  DiGraphNode<Node, Branch> gNode = cfg.getDirectedGraphNode(n);

  if (gNode == null) {
    return n;
  }

  switch (n.getType()) {
    case Token.RETURN:
      if (n.hasChildren()) {
        break;
      }
    case Token.BREAK:
    case Token.CONTINUE:

      // We are looking for a control flow changing statement that always
      // branches to the same node. If after removing it control still
      // branches to the same node, it is safe to remove.
      List<DiGraphEdge<Node,Branch>> outEdges = gNode.getOutEdges();
      if (outEdges.size() == 1 &&
          // If there is a next node, there is no chance this jump is useless.
          (n.getNext() == null || n.getNext().isFunction())) {

        Preconditions.checkState(outEdges.get(0).getValue() == Branch.UNCOND);
        Node fallThrough = computeFollowing(n);
        Node nextCfgNode = outEdges.get(0).getDestination().getValue();
        if (nextCfgNode == fallThrough) {
          removeDeadExprStatementSafely(n);
          return fallThrough;
        }
      }
  }
  return n;
}
 
Example 11
Source File: Closure_24_ScopedAliases_t.java    From coming with MIT License 4 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  if (isCallToScopeMethod(n)) {
    validateScopeCall(t, n, n.getParent());
  }

  if (t.getScopeDepth() < 2) {
    return;
  }

  int type = n.getType();
  Var aliasVar = null;
  if (type == Token.NAME) {
    String name = n.getString();
    Var lexicalVar = t.getScope().getVar(n.getString());
    if (lexicalVar != null && lexicalVar == aliases.get(name)) {
      aliasVar = lexicalVar;
    }
  }

  // Validate the top-level of the goog.scope block.
  if (t.getScopeDepth() == 2) {
    if (aliasVar != null && NodeUtil.isLValue(n)) {
      if (aliasVar.getNode() == n) {
        aliasDefinitionsInOrder.add(n);

        // Return early, to ensure that we don't record a definition
        // twice.
        return;
      } else {
        report(t, n, GOOG_SCOPE_ALIAS_REDEFINED, n.getString());
      }
    }

    if (type == Token.RETURN) {
      report(t, n, GOOG_SCOPE_USES_RETURN);
    } else if (type == Token.THIS) {
      report(t, n, GOOG_SCOPE_REFERENCES_THIS);
    } else if (type == Token.THROW) {
      report(t, n, GOOG_SCOPE_USES_THROW);
    }
  }

  // Validate all descendent scopes of the goog.scope block.
  if (t.getScopeDepth() >= 2) {
    // Check if this name points to an alias.
    if (aliasVar != null) {
      // Note, to support the transitive case, it's important we don't
      // clone aliasedNode here.  For example,
      // var g = goog; var d = g.dom; d.createElement('DIV');
      // The node in aliasedNode (which is "g") will be replaced in the
      // changes pass above with "goog".  If we cloned here, we'd end up
      // with <code>g.dom.createElement('DIV')</code>.
      Node aliasedNode = aliasVar.getInitialValue();
      aliasUsages.add(new AliasedNode(n, aliasedNode));
    }

    JSDocInfo info = n.getJSDocInfo();
    if (info != null) {
      for (Node node : info.getTypeNodes()) {
        fixTypeNode(node);
      }
    }

    // TODO(robbyw): Error for goog.scope not at root.
  }
}
 
Example 12
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 13
Source File: Closure_103_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 14
Source File: Closure_80_NodeUtil_t.java    From coming with MIT License 4 votes vote down vote up
static int precedence(int type) {
  switch (type) {
    case Token.COMMA:  return 0;
    case Token.ASSIGN_BITOR:
    case Token.ASSIGN_BITXOR:
    case Token.ASSIGN_BITAND:
    case Token.ASSIGN_LSH:
    case Token.ASSIGN_RSH:
    case Token.ASSIGN_URSH:
    case Token.ASSIGN_ADD:
    case Token.ASSIGN_SUB:
    case Token.ASSIGN_MUL:
    case Token.ASSIGN_DIV:
    case Token.ASSIGN_MOD:
    case Token.ASSIGN: return 1;
    case Token.HOOK:   return 2;  // ?: operator
    case Token.OR:     return 3;
    case Token.AND:    return 4;
    case Token.BITOR:  return 5;
    case Token.BITXOR: return 6;
    case Token.BITAND: return 7;
    case Token.EQ:
    case Token.NE:
    case Token.SHEQ:
    case Token.SHNE:   return 8;
    case Token.LT:
    case Token.GT:
    case Token.LE:
    case Token.GE:
    case Token.INSTANCEOF:
    case Token.IN:     return 9;
    case Token.LSH:
    case Token.RSH:
    case Token.URSH:   return 10;
    case Token.SUB:
    case Token.ADD:    return 11;
    case Token.MUL:
    case Token.MOD:
    case Token.DIV:    return 12;
    case Token.INC:
    case Token.DEC:
    case Token.NEW:
    case Token.DELPROP:
    case Token.TYPEOF:
    case Token.VOID:
    case Token.NOT:
    case Token.BITNOT:
    case Token.POS:
    case Token.NEG:    return 13;

    case Token.ARRAYLIT:
    case Token.CALL:
    case Token.EMPTY:
    case Token.FALSE:
    case Token.FUNCTION:
    case Token.GETELEM:
    case Token.GETPROP:
    case Token.GET_REF:
    case Token.IF:
    case Token.LP:
    case Token.NAME:
    case Token.NULL:
    case Token.NUMBER:
    case Token.OBJECTLIT:
    case Token.REGEXP:
    case Token.RETURN:
    case Token.STRING:
    case Token.THIS:
    case Token.TRUE:
      return 15;

    default: throw new Error("Unknown precedence for " +
                             Node.tokenToName(type) +
                             " (type " + type + ")");
  }
}
 
Example 15
Source File: Closure_72_FunctionToBlockMutator_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * @return Whether the given block end with an return statement.
 */
private static boolean hasReturnAtExit(Node block) {
  // Only inline functions that return something (empty returns
  // will be handled by ConstFolding+EmptyFunctionRemoval)
  return (block.getLastChild().getType() == Token.RETURN);
}
 
Example 16
Source File: Closure_103_ControlFlowAnalysis_s.java    From coming with MIT License 4 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  switch (n.getType()) {
    case Token.IF:
      handleIf(n);
      return;
    case Token.WHILE:
      handleWhile(n);
      return;
    case Token.DO:
      handleDo(n);
      return;
    case Token.FOR:
      handleFor(n);
      return;
    case Token.SWITCH:
      handleSwitch(n);
      return;
    case Token.CASE:
      handleCase(n);
      return;
    case Token.DEFAULT:
      handleDefault(n);
      return;
    case Token.BLOCK:
    case Token.SCRIPT:
      handleStmtList(n);
      return;
    case Token.FUNCTION:
      handleFunction(n);
      return;
    case Token.EXPR_RESULT:
      handleExpr(n);
      return;
    case Token.THROW:
      handleThrow(n);
      return;
    case Token.TRY:
      handleTry(n);
      return;
    case Token.CATCH:
      handleCatch(n);
      return;
    case Token.BREAK:
      handleBreak(n);
      return;
    case Token.CONTINUE:
      handleContinue(n);
      return;
    case Token.RETURN:
      handleReturn(n);
      return;
    case Token.WITH:
      handleWith(n);
      return;
    case Token.LABEL:
      return;
    default:
      handleStmt(n);
      return;
  }
}
 
Example 17
Source File: RemoveTryCatch.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  switch (n.getType()) {
    case Token.TRY:
      // Ignore the try statement if it has the @preserveTry annotation
      // (for expected exceptions).
      JSDocInfo info = n.getJSDocInfo();
      if (info != null && info.shouldPreserveTry()) {
        return;
      }

      Node tryBlock = n.getFirstChild();
      Node catchBlock = tryBlock.getNext();  // may be null or empty
      Node finallyBlock = catchBlock != null ? catchBlock.getNext() : null;

      // Ignore the try statement if it has a finally part and the try
      // block contains an early return.
      if (finallyBlock != null &&
          tryNodesContainingReturnStatements.contains(n)) {
        return;
      }

      // Redeclare vars declared in the catch node to be removed.
      if (catchBlock.hasOneChild()) {
        NodeUtil.redeclareVarsInsideBranch(catchBlock);
      }

      // Disconnect the try/catch/finally nodes from the parent
      // and each other.
      n.detachChildren();

      // try node
      Node block;
      if (!NodeUtil.isStatementBlock(parent)) {
        block = IR.block();
        parent.replaceChild(n, block);
        block.addChildToFront(tryBlock);
      } else {
        parent.replaceChild(n, tryBlock);
        block = parent;
      }

      // finally node
      if (finallyBlock != null) {
        block.addChildAfter(finallyBlock, tryBlock);
      }
      compiler.reportCodeChange();
      break;

    case Token.RETURN:
      boolean isInTryBlock = false;
      for (Node anc = parent;
           anc != null && !anc.isFunction();
           anc = anc.getParent()) {
        if (anc.isTry()) {
          tryNodesContainingReturnStatements.add(anc);
          break;
        }
      }
      break;
  }
}
 
Example 18
Source File: Closure_127_UnreachableCodeElimination_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Tries to remove n if it is an unconditional branch node (break, continue,
 * or return) and the target of n is the same as the the follow of n.
 * That is, if removing n preserves the control flow. Also if n targets
 * another unconditional branch, this function will recursively try to
 * remove the target branch as well. The reason why we want to cascade this
 * removal is because we only run this pass once. If we have code such as
 *
 * break -> break -> break
 *
 * where all 3 breaks are useless, then the order of removal matters. When
 * we first look at the first break, we see that it branches to the 2nd
 * break. However, if we remove the last break, the 2nd break becomes
 * useless and finally the first break becomes useless as well.
 *
 * @returns The target of this jump. If the target is also useless jump,
 *     the target of that useless jump recursively.
 */
@SuppressWarnings("fallthrough")
private void tryRemoveUnconditionalBranching(Node n) {
  /*
   * For each unconditional branching control flow node, check to see
   * if the ControlFlowAnalysis.computeFollowNode of that node is same as
   * the branching target. If it is, the branch node is safe to be removed.
   *
   * This is not as clever as MinimizeExitPoints because it doesn't do any
   * if-else conversion but it handles more complicated switch statements
   * much more nicely.
   */

  // If n is null the target is the end of the function, nothing to do.
  if (n == null) {
     return;
  }

  DiGraphNode<Node, Branch> gNode = cfg.getDirectedGraphNode(n);

  if (gNode == null) {
    return;
  }

  switch (n.getType()) {
    case Token.RETURN:
      if (n.hasChildren()) {
        break;
      }
    case Token.BREAK:
    case Token.CONTINUE:
      // We are looking for a control flow changing statement that always
      // branches to the same node. If after removing it control still
      // branches to the same node, it is safe to remove.
      List<DiGraphEdge<Node, Branch>> outEdges = gNode.getOutEdges();
      if (outEdges.size() == 1 &&
          // If there is a next node, this jump is not useless.
          (n.getNext() == null || n.getNext().isFunction())) {

        Preconditions.checkState(
            outEdges.get(0).getValue() == Branch.UNCOND);
        Node fallThrough = computeFollowing(n);
        Node nextCfgNode = outEdges.get(0).getDestination().getValue();
        if (nextCfgNode == fallThrough && !inFinally(n.getParent(), n)) {
          removeNode(n);
        }
      }
  }
}
 
Example 19
Source File: Closure_103_ControlFlowAnalysis_s.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 20
Source File: Closure_94_NodeUtil_s.java    From coming with MIT License 4 votes vote down vote up
static int precedence(int type) {
  switch (type) {
    case Token.COMMA:  return 0;
    case Token.ASSIGN_BITOR:
    case Token.ASSIGN_BITXOR:
    case Token.ASSIGN_BITAND:
    case Token.ASSIGN_LSH:
    case Token.ASSIGN_RSH:
    case Token.ASSIGN_URSH:
    case Token.ASSIGN_ADD:
    case Token.ASSIGN_SUB:
    case Token.ASSIGN_MUL:
    case Token.ASSIGN_DIV:
    case Token.ASSIGN_MOD:
    case Token.ASSIGN: return 1;
    case Token.HOOK:   return 2;  // ?: operator
    case Token.OR:     return 3;
    case Token.AND:    return 4;
    case Token.BITOR:  return 5;
    case Token.BITXOR: return 6;
    case Token.BITAND: return 7;
    case Token.EQ:
    case Token.NE:
    case Token.SHEQ:
    case Token.SHNE:   return 8;
    case Token.LT:
    case Token.GT:
    case Token.LE:
    case Token.GE:
    case Token.INSTANCEOF:
    case Token.IN:     return 9;
    case Token.LSH:
    case Token.RSH:
    case Token.URSH:   return 10;
    case Token.SUB:
    case Token.ADD:    return 11;
    case Token.MUL:
    case Token.MOD:
    case Token.DIV:    return 12;
    case Token.INC:
    case Token.DEC:
    case Token.NEW:
    case Token.DELPROP:
    case Token.TYPEOF:
    case Token.VOID:
    case Token.NOT:
    case Token.BITNOT:
    case Token.POS:
    case Token.NEG:    return 13;

    case Token.ARRAYLIT:
    case Token.CALL:
    case Token.EMPTY:
    case Token.FALSE:
    case Token.FUNCTION:
    case Token.GETELEM:
    case Token.GETPROP:
    case Token.GET_REF:
    case Token.IF:
    case Token.LP:
    case Token.NAME:
    case Token.NULL:
    case Token.NUMBER:
    case Token.OBJECTLIT:
    case Token.REGEXP:
    case Token.RETURN:
    case Token.STRING:
    case Token.THIS:
    case Token.TRUE:
      return 15;

    default: throw new Error("Unknown precedence for " +
                             Node.tokenToName(type) +
                             " (type " + type + ")");
  }
}