Java Code Examples for com.google.javascript.rhino.Node#getNext()

The following examples show how to use com.google.javascript.rhino.Node#getNext() . 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: DisambiguateProperties.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Processes a OBJECTLIT node.
 */
private void handleObjectLit(NodeTraversal t, Node n) {
  Node child = n.getFirstChild();
  while (child != null) {
    // Maybe STRING, GET, SET

    // We should never see a mix of numbers and strings.
    String name = child.getString();
    T type = typeSystem.getType(getScope(), n, name);

    Property prop = getProperty(name);
    if (!prop.scheduleRenaming(child,
                               processProperty(t, prop, type, null))) {
      // TODO(user): It doesn't look like the user can do much in this
      // case right now.
      if (propertiesToErrorFor.containsKey(name)) {
        compiler.report(JSError.make(
            t.getSourceName(), child, propertiesToErrorFor.get(name),
            Warnings.INVALIDATION, name,
            (type == null ? "null" : type.toString()), n.toString(), ""));
      }
    }
    child = child.getNext();
  }
}
 
Example 2
Source File: Cardumen_0089_s.java    From coming with MIT License 6 votes vote down vote up
private void traverse(Node node) {
  // The goal here is to avoid retraversing
  // the entire AST to catch newly created opportunities.
  // So we track whether a "unit of code" has changed,
  // and revisit immediately.
  if (!shouldVisit(node)) {
    return;
  }

  int visits = 0;
  do {
    Node c = node.getFirstChild();
    while(c != null) {
      traverse(c);
      Node next = c.getNext();
      c = next;
    }

    visit(node);
    visits++;

    Preconditions.checkState(visits < 10000, "too many interations");
  } while (shouldRetraverse(node));

  exitNode(node);
}
 
Example 3
Source File: ExternExportsPass.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
private void handleSymbolExport(Node parent) {
  // Ensure that we only check valid calls with the 2 arguments
  // (plus the GETPROP node itself).
  if (parent.getChildCount() != 3) {
    return;
  }

  Node thisNode = parent.getFirstChild();
  Node nameArg = thisNode.getNext();
  Node valueArg = nameArg.getNext();

  // Confirm the arguments are the expected types. If they are not,
  // then we have an export that we cannot statically identify.
  if (!nameArg.isString()) {
    return;
  }

  // Add the export to the list.
  this.exports.add(new SymbolExport(nameArg.getString(), valueArg));
}
 
Example 4
Source File: PeepholeOptimizationsPass.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
private void traverse(Node node) {
  // The goal here is to avoid retraversing
  // the entire AST to catch newly created opportunities.
  // So we track whether a "unit of code" has changed,
  // and revisit immediately.
  if (!shouldVisit(node)) {
    return;
  }

  int visits = 0;
  do {
    Node c = node.getFirstChild();
    while(c != null) {
      Node next = c.getNext();
      traverse(c);
      c = next;
    }

    visit(node);
    visits++;

    Preconditions.checkState(visits < 10000, "too many interations");
  } while (shouldRetraverse(node));

  exitNode(node);
}
 
Example 5
Source File: Closure_87_PeepholeSubstituteAlternateSyntax_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Checks if it is safe to fold Array() constructor into []. It can be
 * obviously done, if the initial constructor has either no arguments or
 * at least two. The remaining case may be unsafe since Array(number)
 * actually reserves memory for an empty array which contains number elements.
 */
private FoldArrayAction isSafeToFoldArrayConstructor(Node arg) {
  FoldArrayAction action = FoldArrayAction.NOT_SAFE_TO_FOLD;

  if (arg == null) {
    action = FoldArrayAction.SAFE_TO_FOLD_WITHOUT_ARGS;
  } else if (arg.getNext() != null) {
    action = FoldArrayAction.SAFE_TO_FOLD_WITH_ARGS;
  } else {
    switch (arg.getType()) {
      case (Token.STRING):
        // "Array('a')" --> "['a']"
        action = FoldArrayAction.SAFE_TO_FOLD_WITH_ARGS;
        break;
      case (Token.NUMBER):
        // "Array(0)" --> "[]"
        if (arg.getDouble() == 0) {
          action = FoldArrayAction.SAFE_TO_FOLD_WITHOUT_ARGS;
        }
        break;
      case (Token.ARRAYLIT):
        // "Array([args])" --> "[[args]]"
        action = FoldArrayAction.SAFE_TO_FOLD_WITH_ARGS;
        break;
      default:
    }
  }
  return action;
}
 
Example 6
Source File: IRFactoryTest.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
public void testPlusEqLocation() {
  Node root = newParse(
      "a\n" +
      "+=\n" +
      "b\n");

  Node condClause = root.getFirstChild().getFirstChild();
  Node lhs = condClause.getFirstChild();
  Node rhs = lhs.getNext();

  assertNodePosition(1, 0, condClause);
  assertNodePosition(1, 0, lhs);
  assertNodePosition(3, 0, rhs);
}
 
Example 7
Source File: Closure_102_Normalize_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Move all the functions that are valid at the execution of the first
 * statement of the function to the beginning of the function definition.
 */
private void moveNamedFunctions(Node functionBody) {
  Preconditions.checkState(
      functionBody.getParent().getType() == Token.FUNCTION);
  Node previous = null;
  Node current = functionBody.getFirstChild();
  // Skip any declarations at the beginning of the function body, they
  // are already in the right place.
  while (current != null && NodeUtil.isFunctionDeclaration(current)) {
    previous = current;
    current = current.getNext();
  }

  // Find any remaining declarations and move them.
  Node insertAfter = previous;
  while (current != null) {
    // Save off the next node as the current node maybe removed.
    Node next = current.getNext();
    if (NodeUtil.isFunctionDeclaration(current)) {
      // Remove the declaration from the body.
      Preconditions.checkNotNull(previous);
      functionBody.removeChildAfter(previous);

      // Readd the function at the top of the function body (after any
      // previous declarations).
      insertAfter = addToFront(functionBody, current, insertAfter);
      compiler.reportCodeChange();
    } else {
      // Update the previous only if the current node hasn't been moved.
      previous = current;
    }
    current = next;
  }
}
 
Example 8
Source File: Closure_114_NameAnalyzer_s.java    From coming with MIT License 5 votes vote down vote up
@Override
public void keepSimplifiedShortCircuitExpression(Node original) {
  Node condition = original.getFirstChild();
  Node thenBranch = condition.getNext();
  addAllChildren(condition);
  addSimplifiedChildren(thenBranch);
}
 
Example 9
Source File: PeepholeRemoveDeadCode.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Remove try blocks without catch blocks and with empty or not
 * existent finally blocks.
 * Or, only leave the finally blocks if try body blocks are empty
 * @return the replacement node, if changed, or the original if not
 */
private Node tryFoldTry(Node n) {
  Preconditions.checkState(n.isTry());
  Node body = n.getFirstChild();
  Node catchBlock = body.getNext();
  Node finallyBlock = catchBlock.getNext();

  // Removes TRYs that had its CATCH removed and/or empty FINALLY.
  if (!catchBlock.hasChildren() &&
      (finallyBlock == null || !finallyBlock.hasChildren())) {
    n.removeChild(body);
    n.getParent().replaceChild(n, body);
    reportCodeChange();
    return body;
  }

  // Only leave FINALLYs if TRYs are empty
  if (!body.hasChildren()) {
    NodeUtil.redeclareVarsInsideBranch(catchBlock);
    if (finallyBlock != null) {
      n.removeChild(finallyBlock);
      n.getParent().replaceChild(n, finallyBlock);
    } else {
      n.getParent().removeChild(n);
    }
    reportCodeChange();
    return finallyBlock;
  }

  return n;
}
 
Example 10
Source File: Cardumen_0014_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * For an assignment or variable declaration get the assigned value.
 * @return The value node representing the new value.
 */
static Node getAssignedValue(Node n) {
  Preconditions.checkState(n.isName());
  Node parent = n.getParent();
  if (parent.isVar()) {
    return n.getFirstChild();
  } else if (parent.isAssign() && parent.getFirstChild() == n) {
    return n.getNext();
  } else {
    return null;
  }
}
 
Example 11
Source File: Closure_114_NameAnalyzer_t.java    From coming with MIT License 5 votes vote down vote up
@Override
public void keepSimplifiedHookExpression(Node hook,
                                         boolean thenHasSideEffects,
                                         boolean elseHasSideEffects) {
  Node condition = hook.getFirstChild();
  Node thenBranch = condition.getNext();
  Node elseBranch = thenBranch.getNext();
  addAllChildren(condition);
  if (thenHasSideEffects) {
    addSimplifiedChildren(thenBranch);
  }
  if (elseHasSideEffects) {
    addSimplifiedChildren(elseBranch);
  }
}
 
Example 12
Source File: Cardumen_0093_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Remove all references to a parameter if possible otherwise simplify the
 * side-effect free parameters.
 */
private void tryRemoveArgFromCallSites(
    Node function, int argIndex, boolean canModifyAllSites) {
  Definition definition = getFunctionDefinition(function);

  for (UseSite site : defFinder.getUseSites(definition)) {
    if (isModifiableCallSite(site)) {
      Node arg = getArgumentForCallOrNewOrDotCall(site, argIndex);
      if (arg != null) {
        Node argParent = arg.getParent();
        // Even if we can't change the signature in general we can always
        // remove an unused value off the end of the parameter list.
        if (canModifyAllSites
            || (arg.getNext() == null
                && !NodeUtil.mayHaveSideEffects(arg, compiler))) {
          toRemove.add(arg);
        } else {
          // replace the node in the arg with 0
          if (!NodeUtil.mayHaveSideEffects(arg, compiler)
              && (!arg.isNumber() || arg.getDouble() != 0)) {
            toReplaceWithZero.add(arg);
          }
        }
      }
    }
  }
}
 
Example 13
Source File: Closure_112_TypeInference_s.java    From coming with MIT License 5 votes vote down vote up
private FlowScope tightenTypesAfterAssertions(FlowScope scope,
    Node callNode) {
  Node left = callNode.getFirstChild();
  Node firstParam = left.getNext();
  AssertionFunctionSpec assertionFunctionSpec =
      assertionFunctionsMap.get(left.getQualifiedName());
  if (assertionFunctionSpec == null || firstParam == null) {
    return scope;
  }
  Node assertedNode = assertionFunctionSpec.getAssertedParam(firstParam);
  if (assertedNode == null) {
    return scope;
  }
  JSType assertedType = assertionFunctionSpec.getAssertedType(
      callNode, registry);
  String assertedNodeName = assertedNode.getQualifiedName();

  JSType narrowed;
  // Handle assertions that enforce expressions evaluate to true.
  if (assertedType == null) {
    // Handle arbitrary expressions within the assert.
    scope = reverseInterpreter.getPreciserScopeKnowingConditionOutcome(
        assertedNode, scope, true);
    // Build the result of the assertExpression
    narrowed = getJSType(assertedNode).restrictByNotNullOrUndefined();
  } else {
    // Handle assertions that enforce expressions are of a certain type.
    JSType type = getJSType(assertedNode);
    narrowed = type.getGreatestSubtype(assertedType);
    if (assertedNodeName != null && type.differsFrom(narrowed)) {
      scope = narrowScope(scope, assertedNode, narrowed);
    }
  }

  callNode.setJSType(narrowed);
  return scope;
}
 
Example 14
Source File: Cardumen_00152_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Remove all references to a parameter if possible otherwise simplify the
 * side-effect free parameters.
 */
private void tryRemoveArgFromCallSites(
    Node function, int argIndex, boolean canModifyAllSites) {
  Definition definition = getFunctionDefinition(function);

  for (UseSite site : defFinder.getUseSites(definition)) {
    if (isModifiableCallSite(site)) {
      Node arg = getArgumentForCallOrNewOrDotCall(site, argIndex);
      if (arg != null) {
        Node argParent = arg.getParent();
        // Even if we can't change the signature in general we can always
        // remove an unused value off the end of the parameter list.
        if (canModifyAllSites
            || (arg.getNext() == null
                && !NodeUtil.mayHaveSideEffects(arg, compiler))) {
          toRemove.add(arg);
        } else {
          // replace the node in the arg with 0
          if (!NodeUtil.mayHaveSideEffects(arg, compiler)
              && (!arg.isNumber() || arg.getDouble() != 0)) {
            toReplaceWithZero.add(arg);
          }
        }
      }
    }
  }
}
 
Example 15
Source File: Cardumen_00202_s.java    From coming with MIT License 5 votes vote down vote up
@Override
public void keepSimplifiedHookExpression(Node hook,
                                         boolean thenHasSideEffects,
                                         boolean elseHasSideEffects) {
  Node condition = hook.getFirstChild();
  Node thenBranch = condition.getNext();
  Node elseBranch = thenBranch.getNext();
  addAllChildren(condition);
  if (thenHasSideEffects) {
    addSimplifiedChildren(thenBranch);
  }
  if (elseHasSideEffects) {
    addSimplifiedChildren(elseBranch);
  }
}
 
Example 16
Source File: Cardumen_00200_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * For an assignment or variable declaration get the assigned value.
 * @return The value node representing the new value.
 */
static Node getAssignedValue(Node n) {
  Preconditions.checkState(n.isName());
  Node parent = n.getParent();
  if (parent.isVar()) {
    return n.getFirstChild();
  } else if (parent.isAssign() && parent.getFirstChild() == n) {
    return n.getNext();
  } else {
    return null;
  }
}
 
Example 17
Source File: Nopol2017_0019_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Look for exits (returns, breaks, or continues, depending on the context) at
 * the end of a block and removes them by moving the if node's siblings,
 * if any, into the opposite condition block.
 *
 * @param srcBlock The block to inspect.
 * @param destBlock The block to move sibling nodes into.
 * @param ifNode The if node to work with.
 * @param exitType The type of exit to look for.
 * @param labelName The name associated with the exit, if any.
 * @nullable labelName null for anything excepted for named-break associated
 *           with a label.
 */
private void tryMinimizeIfBlockExits(Node srcBlock, Node destBlock,
    Node ifNode, int exitType, String labelName) {
  Node exitNodeParent = null;
  Node exitNode = null;

  // Pick an exit node candidate.
  if (srcBlock.isBlock()) {
    if (!srcBlock.hasChildren()) {
      return;
    }
    exitNodeParent = srcBlock;
    exitNode = exitNodeParent.getLastChild();
  } else {
    // Just a single statement, if it isn't an exit bail.
    exitNodeParent = ifNode;
    exitNode = srcBlock;
  }

  // Verify the candidate.
  if (!matchingExitNode(exitNode, exitType, labelName)) {
    return;
  }

  // Take case of the if nodes siblings, if any.
  if (ifNode.getNext() != null) {
    // Move siblings of the if block into the opposite
    // logic block of the exit.
    Node newDestBlock = IR.block().srcref(ifNode);
    if (destBlock == null) {
      // Only possible if this is the false block.
      ifNode.addChildToBack(newDestBlock);
    } else if (destBlock.isEmpty()) {
      // Use the new block.
      ifNode.replaceChild(destBlock, newDestBlock);
    } else if (destBlock.isBlock()) {
      // Reuse the existing block.
      newDestBlock = destBlock;
    } else {
      // Add the existing statement to the new block.
      ifNode.replaceChild(destBlock, newDestBlock);
      newDestBlock.addChildToBack(destBlock);
    }

    // Move all the if node's following siblings.
    moveAllFollowing(ifNode, ifNode.getParent(), newDestBlock);
    compiler.reportCodeChange();
  }
}
 
Example 18
Source File: Closure_126_MinimizeExitPoints_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Look for exits (returns, breaks, or continues, depending on the context) at
 * the end of a block and removes them by moving the if node's siblings,
 * if any, into the opposite condition block.
 *
 * @param srcBlock The block to inspect.
 * @param destBlock The block to move sibling nodes into.
 * @param ifNode The if node to work with.
 * @param exitType The type of exit to look for.
 * @param labelName The name associated with the exit, if any.
 * @nullable labelName null for anything excepted for named-break associated
 *           with a label.
 */
private void tryMinimizeIfBlockExits(Node srcBlock, Node destBlock,
    Node ifNode, int exitType, String labelName) {
  Node exitNodeParent = null;
  Node exitNode = null;

  // Pick an exit node candidate.
  if (srcBlock.isBlock()) {
    if (!srcBlock.hasChildren()) {
      return;
    }
    exitNodeParent = srcBlock;
    exitNode = exitNodeParent.getLastChild();
  } else {
    // Just a single statement, if it isn't an exit bail.
    exitNodeParent = ifNode;
    exitNode = srcBlock;
  }

  // Verify the candidate.
  if (!matchingExitNode(exitNode, exitType, labelName)) {
    return;
  }

  // Take case of the if nodes siblings, if any.
  if (ifNode.getNext() != null) {
    // Move siblings of the if block into the opposite
    // logic block of the exit.
    Node newDestBlock = IR.block().srcref(ifNode);
    if (destBlock == null) {
      // Only possible if this is the false block.
      ifNode.addChildToBack(newDestBlock);
    } else if (destBlock.isEmpty()) {
      // Use the new block.
      ifNode.replaceChild(destBlock, newDestBlock);
    } else if (destBlock.isBlock()) {
      // Reuse the existing block.
      newDestBlock = destBlock;
    } else {
      // Add the existing statement to the new block.
      ifNode.replaceChild(destBlock, newDestBlock);
      newDestBlock.addChildToBack(destBlock);
    }

    // Move all the if node's following siblings.
    moveAllFollowing(ifNode, ifNode.getParent(), newDestBlock);
    compiler.reportCodeChange();
  }
}
 
Example 19
Source File: Closure_116_FunctionInjector_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Determines whether a function can be inlined at a particular call site.
 * There are several criteria that the function and reference must hold in
 * order for the functions to be inlined:
 * 1) If a call's arguments have side effects,
 * the corresponding argument in the function must only be referenced once.
 * For instance, this will not be inlined:
 * <pre>
 *     function foo(a) { return a + a }
 *     x = foo(i++);
 * </pre>
 */
private CanInlineResult canInlineReferenceDirectly(
    Node callNode, Node fnNode) {
  if (!isDirectCallNodeReplacementPossible(fnNode)) {
    return CanInlineResult.NO;
  }

  Node block = fnNode.getLastChild();

  boolean hasSideEffects = false;  // empty function case
  if (block.hasChildren()) {
    Preconditions.checkState(block.hasOneChild());
    Node stmt = block.getFirstChild();
    if (stmt.isReturn()) {
      hasSideEffects = NodeUtil.mayHaveSideEffects(
          stmt.getFirstChild(), compiler);
    }
  }

  // CALL NODE: [ NAME, ARG1, ARG2, ... ]
  Node cArg = callNode.getFirstChild().getNext();

  // Functions called via 'call' and 'apply' have a this-object as
  // the first parameter, but this is not part of the called function's
  // parameter list.
  if (!callNode.getFirstChild().isName()) {
    if (NodeUtil.isFunctionObjectCall(callNode)) {
      // TODO(johnlenz): Support replace this with a value.
      if (cArg == null || !cArg.isThis()) {
        return CanInlineResult.NO;
      }
      cArg = cArg.getNext();
    } else {
      // ".apply" call should be filtered before this.
      Preconditions.checkState(!NodeUtil.isFunctionObjectApply(callNode));
    }
  }

  // FUNCTION NODE -> LP NODE: [ ARG1, ARG2, ... ]
  Node fnParam = NodeUtil.getFunctionParameters(fnNode).getFirstChild();
  while (cArg != null || fnParam != null) {
    // For each named parameter check if a mutable argument use more than one.
    if (fnParam != null) {
      if (cArg != null) {
        if (hasSideEffects && NodeUtil.canBeSideEffected(cArg)) {
          return CanInlineResult.NO;
        }

        // Check for arguments that are evaluated more than once.
        // Note: Unlike block inlining, there it is not possible that a
        // parameter reference will be in a loop.
        if (NodeUtil.mayEffectMutableState(cArg, compiler)
            && NodeUtil.getNameReferenceCount(
                block, fnParam.getString()) > 1) {
          return CanInlineResult.NO;
        }
      }

      // Move to the next name.
      fnParam = fnParam.getNext();
    }

    // For every call argument check for side-effects, even if there
    // isn't a named parameter to match.
    if (cArg != null) {
      if (NodeUtil.mayHaveSideEffects(cArg, compiler)) {
        return CanInlineResult.NO;
      }
      cArg = cArg.getNext();
    }
  }

  return CanInlineResult.YES;
}
 
Example 20
Source File: Closure_12_MaybeReachingVariableUse_s.java    From coming with MIT License 4 votes vote down vote up
private void computeMayUse(
    Node n, Node cfgNode, ReachingUses output, boolean conditional) {
  switch (n.getType()) {

    case Token.BLOCK:
    case Token.FUNCTION:
      return;

    case Token.NAME:
      addToUseIfLocal(n.getString(), cfgNode, output);
      return;

    case Token.WHILE:
    case Token.DO:
    case Token.IF:
      computeMayUse(
          NodeUtil.getConditionExpression(n), cfgNode, output, conditional);
      return;

    case Token.FOR:
      if (!NodeUtil.isForIn(n)) {
        computeMayUse(
            NodeUtil.getConditionExpression(n), cfgNode, output, conditional);
      } else {
        // for(x in y) {...}
        Node lhs = n.getFirstChild();
        Node rhs = lhs.getNext();
        if (lhs.isVar()) {
          lhs = lhs.getLastChild(); // for(var x in y) {...}
        }
        if (lhs.isName() && !conditional) {
          removeFromUseIfLocal(lhs.getString(), output);
        }
        computeMayUse(rhs, cfgNode, output, conditional);
      }
      return;

    case Token.AND:
    case Token.OR:
      computeMayUse(n.getLastChild(), cfgNode, output, true);
      computeMayUse(n.getFirstChild(), cfgNode, output, conditional);
      return;

    case Token.HOOK:
      computeMayUse(n.getLastChild(), cfgNode, output, true);
      computeMayUse(n.getFirstChild().getNext(), cfgNode, output, true);
      computeMayUse(n.getFirstChild(), cfgNode, output, conditional);
      return;

    case Token.VAR:
      Node varName = n.getFirstChild();
      Preconditions.checkState(n.hasChildren(), "AST should be normalized");

      if (varName.hasChildren()) {
        computeMayUse(varName.getFirstChild(), cfgNode, output, conditional);
        if (!conditional) {
          removeFromUseIfLocal(varName.getString(), output);
        }
      }
      return;

    default:
      if (NodeUtil.isAssignmentOp(n) && n.getFirstChild().isName()) {
        Node name = n.getFirstChild();
        if (!conditional) {
          removeFromUseIfLocal(name.getString(), output);
        }

        // In case of a += "Hello". There is a read of a.
        if (!n.isAssign()) {
          addToUseIfLocal(name.getString(), cfgNode, output);
        }

        computeMayUse(name.getNext(), cfgNode, output, conditional);
      } else {
        /*
         * We want to traverse in reverse order because we want the LAST
         * definition in the sub-tree....
         * But we have no better way to traverse in reverse other :'(
         */
        for (Node c = n.getLastChild(); c != null; c = n.getChildBefore(c)) {
          computeMayUse(c, cfgNode, output, conditional);
        }
      }
  }
}