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

The following examples show how to use com.google.javascript.rhino.Node#replaceChild() . 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: InlineProperties.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  if (n.isGetProp() && !NodeUtil.isLValue(n)) {
    Node target = n.getFirstChild();
    String propName = n.getLastChild().getString();
    PropertyInfo info = props.get(propName);
    if (info != null
        && info != INVALIDATED
        && isMatchingType(target, info.type)) {
      Node replacement = info.value.cloneTree();
      if (NodeUtil.mayHaveSideEffects(n.getFirstChild(), compiler)) {
        replacement = IR.comma(n.removeFirstChild(), replacement).srcref(n);
      }
      parent.replaceChild(n, replacement);
      compiler.reportCodeChange();
    }
  }
}
 
Example 2
Source File: ProcessCommonJSModules.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Visit require calls. Emit corresponding goog.require and rewrite require
 * to be a direct reference to name of require module.
 */
private void visitRequireCall(NodeTraversal t, Node require, Node parent) {
  String moduleName = toModuleName(require.getChildAtIndex(1).getString(),
      normalizeSourceName(t.getSourceName()));
  Node moduleRef = IR.name(moduleName).srcref(require);
  parent.replaceChild(require, moduleRef);
  Node script = getCurrentScriptNode(parent);
  if (reportDependencies) {
    t.getInput().addRequire(moduleName);
  }
  // Rewrite require("name").
  script.addChildToFront(IR.exprResult(
      IR.call(IR.getprop(IR.name("goog"), IR.string("require")),
          IR.string(moduleName))).copyInformationFromForTree(require));
  compiler.reportCodeChange();
}
 
Example 3
Source File: SpecializeModule.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Generates a definition of the original function that can be added as
 * a fixup in the modules that directly depend on the specialized module.
 *
 * <PRE>
 * The trick here is that even if the original function is declared as:
 *
 * function foo() {
 *   // stuff
 * }
 *
 * the fixup will have to be of the form
 *
 * foo = function() {
 *   // stuff
 * }
 * </PRE>
 *
 */
private Node generateFixupDefinition() {
  Node functionCopy = copiedOriginalFunction();

  Node nameNode;

  if (isAssignFunction) {
    nameNode =
       NodeUtil.newQualifiedNameNode(
           compiler.getCodingConvention(), name, functionCopy, name);
  } else {
    // Grab the name node from the original function and make that
    // function anonymous.
    nameNode = functionCopy.getFirstChild();
    functionCopy.replaceChild(nameNode,
        NodeUtil.newName(compiler.getCodingConvention(), "", nameNode));
  }

  Node assignment = IR.assign(nameNode, functionCopy);
  assignment.copyInformationFrom(functionCopy);

  return NodeUtil.newExpr(assignment);
}
 
Example 4
Source File: RemoveGoogScopePass.java    From clutz with MIT License 6 votes vote down vote up
private void maybeReassignAlias(Node assign) {
  Node lhs = assign.getFirstChild();
  if (!lhs.isGetProp()) {
    // TODO(dpurpura): Add support for GET_ELEM.  (e.g. Foo['abc'])
    return;
  }

  // Find the name of the deepest first child.
  String alias = null;
  for (Node child = lhs; child != null; child = child.getFirstChild()) {
    if (child.isName()) {
      alias = child.getQualifiedName();
    }
  }

  checkNotNull(alias, "Missing name for alias");
  if (aliasToProvidedNamespace.containsKey(alias)) {
    String providedNamespace = aliasToProvidedNamespace.get(alias);

    String suffix = lhs.getQualifiedName().substring(alias.length());
    Node fullName = NodeUtil.newQName(compiler, providedNamespace + suffix);
    assign.replaceChild(lhs, fullName);
  }
  return;
}
 
Example 5
Source File: Closure_79_Normalize_t.java    From coming with MIT License 6 votes vote down vote up
/**
 * Limit the number of special cases where LABELs need to be handled. Only
 * BLOCK and loops are allowed to be labeled.  Loop labels must remain in
 * place as the named continues are not allowed for labeled blocks.
 */
private void normalizeLabels(Node n) {
  Preconditions.checkArgument(n.getType() == Token.LABEL);

  Node last = n.getLastChild();
  switch (last.getType()) {
    case Token.LABEL:
    case Token.BLOCK:
    case Token.FOR:
    case Token.WHILE:
    case Token.DO:
      return;
    default:
      Node block = new Node(Token.BLOCK);
      block.copyInformationFrom(last);
      n.replaceChild(last, block);
      block.addChildToFront(last);
      reportCodeChange("LABEL normalization");
      return;
  }
}
 
Example 6
Source File: Closure_105_FoldConstants_s.java    From coming with MIT License 6 votes vote down vote up
/**
 * Try to fold a ADD node
 */
void tryFoldAdd(NodeTraversal t, Node n, Node left, Node right,
                Node parent) {
  if (left.getType() == Token.STRING ||
      right.getType() == Token.STRING) {

    // Add strings.
    String leftString = NodeUtil.getStringValue(left);
    String rightString = NodeUtil.getStringValue(right);
    if (leftString != null && rightString != null) {
      parent.replaceChild(n, Node.newString(leftString + rightString));
      t.getCompiler().reportCodeChange();
    }
  } else {
    // Try arithmetic add
    tryFoldArithmetic(t, n, left, right, parent);
  }
}
 
Example 7
Source File: Closure_105_FoldConstants_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Try to fold array-length. e.g [1, 2, 3].length ==> 3, [x, y].length ==> 2
 */
void tryFoldGetProp(NodeTraversal t, Node n, Node left, Node right,
                    Node parent) {
  if (right.getType() == Token.STRING &&
      right.getString().equals("length")) {
    int knownLength = -1;
    switch (left.getType()) {
      case Token.ARRAYLIT:
        if (NodeUtil.mayHaveSideEffects(left)) {
          // Nope, can't fold this, without handling the side-effects.
          return;
        }
        knownLength = left.getChildCount();
        break;
      case Token.STRING:
        knownLength = left.getString().length();
        break;
      default:
        // Not a foldable case, forget it.
        return;
    }

    Preconditions.checkState(knownLength != -1);
    Node lengthNode = Node.newNumber(knownLength);
    parent.replaceChild(n, lengthNode);
    t.getCompiler().reportCodeChange();
  }
}
 
Example 8
Source File: Closure_23_PeepholeFoldConstants_t.java    From coming with MIT License 5 votes vote down vote up
private Node tryFoldInForcedStringContext(Node n) {
  // For now, we only know how to fold ctors.
  Preconditions.checkArgument(n.isNew());

  Node objectType = n.getFirstChild();
  if (!objectType.isName()) {
    return n;
  }

  if (objectType.getString().equals("String")) {
    Node value = objectType.getNext();
    String stringValue = null;
    if (value == null) {
      stringValue = "";
    } else {
      if (!NodeUtil.isImmutableValue(value)) {
        return n;
      }

      stringValue = NodeUtil.getStringValue(value);
    }

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

    Node parent = n.getParent();
    Node newString = IR.string(stringValue);

    parent.replaceChild(n, newString);
    newString.copyInformationFrom(parent);
    reportCodeChange();

    return newString;
  }
  return n;
}
 
Example 9
Source File: Closure_23_PeepholeFoldConstants_s.java    From coming with MIT License 5 votes vote down vote up
private Node tryFoldInForcedStringContext(Node n) {
  // For now, we only know how to fold ctors.
  Preconditions.checkArgument(n.isNew());

  Node objectType = n.getFirstChild();
  if (!objectType.isName()) {
    return n;
  }

  if (objectType.getString().equals("String")) {
    Node value = objectType.getNext();
    String stringValue = null;
    if (value == null) {
      stringValue = "";
    } else {
      if (!NodeUtil.isImmutableValue(value)) {
        return n;
      }

      stringValue = NodeUtil.getStringValue(value);
    }

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

    Node parent = n.getParent();
    Node newString = IR.string(stringValue);

    parent.replaceChild(n, newString);
    newString.copyInformationFrom(parent);
    reportCodeChange();

    return newString;
  }
  return n;
}
 
Example 10
Source File: Closure_23_PeepholeFoldConstants_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Expressions such as [foo() * 10 * 20] generate parse trees
 * where no node has two const children ((foo() * 10) * 20), so
 * performArithmeticOp() won't fold it -- tryFoldLeftChildOp() will.
 * Specifically, it folds associative expressions where:
 *  - The left child is also an associative expression of the same time.
 *  - The right child is a constant NUMBER constant.
 *  - The left child's right child is a NUMBER constant.
 */
private Node tryFoldLeftChildOp(Node n, Node left, Node right) {
  int opType = n.getType();
  Preconditions.checkState(
      (NodeUtil.isAssociative(opType) && NodeUtil.isCommutative(opType))
      || n.isAdd());

  Preconditions.checkState(
      !n.isAdd()|| !NodeUtil.mayBeString(n));

  // Use getNumberValue to handle constants like "NaN" and "Infinity"
  // other values are converted to numbers elsewhere.
  Double rightValObj = NodeUtil.getNumberValue(right);
  if (rightValObj != null && left.getType() == opType) {
    Preconditions.checkState(left.getChildCount() == 2);

    Node ll = left.getFirstChild();
    Node lr = ll.getNext();

    Node valueToCombine = ll;
    Node replacement = performArithmeticOp(opType, valueToCombine, right);
    if (replacement == null) {
      valueToCombine = lr;
      replacement = performArithmeticOp(opType, valueToCombine, right);
    }
    if (replacement != null) {
      // Remove the child that has been combined
      left.removeChild(valueToCombine);
      // Replace the left op with the remaining child.
      n.replaceChild(left, left.removeFirstChild());
      // New "-Infinity" node need location info explicitly
      // added.
      replacement.copyInformationFromForTree(right);
      n.replaceChild(right, replacement);
      reportCodeChange();
    }
  }

  return n;
}
 
Example 11
Source File: Closure_50_PeepholeReplaceKnownMethods_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Try to fold .charAt() calls on strings
 */
private Node tryFoldStringCharAt(Node n, Node stringNode, Node arg1) {
  Preconditions.checkArgument(n.getType() == Token.CALL);
  Preconditions.checkArgument(stringNode.getType() == Token.STRING);

  int index;
  String stringAsString = stringNode.getString();

  if (arg1 != null && arg1.getType() == Token.NUMBER
      && arg1.getNext() == null) {
    index = (int) arg1.getDouble();
  } else {
    return n;
  }

  if (index < 0 || stringAsString.length() <= index) {
    // http://es5.github.com/#x15.5.4.4 says "" is returned when index is
    // out of bounds but we bail.
    return n;
  }

  Node resultNode = Node.newString(
      stringAsString.substring(index, index + 1));
  Node parent = n.getParent();
  parent.replaceChild(n, resultNode);
  reportCodeChange();
  return resultNode;
}
 
Example 12
Source File: Closure_74_PeepholeFoldConstants_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Try to fold a AND/OR node.
 */
private Node tryFoldAndOr(Node n, Node left, Node right) {
  Node parent = n.getParent();

  Node result = null;

  int type = n.getType();

  TernaryValue leftVal = NodeUtil.getImpureBooleanValue(left);

  if (leftVal != TernaryValue.UNKNOWN) {
    boolean lval = leftVal.toBoolean(true);

    // (TRUE || x) => TRUE (also, (3 || x) => 3)
    // (FALSE && x) => FALSE
    if (lval && type == Token.OR ||
        !lval && type == Token.AND) {
      result = left;

    } else if (!mayHaveSideEffects(left)) {
      // (FALSE || x) => x
      // (TRUE && x) => x
      result = right;
    }
  }

  // Note: Right hand side folding is handled by
  // PeepholeSubstituteAlternateSyntax#tryMinimizeCondition

  if (result != null) {
    // Fold it!
    n.removeChild(result);
    parent.replaceChild(n, result);
    reportCodeChange();

    return result;
  } else {
    return n;
  }
}
 
Example 13
Source File: Cardumen_00201_t.java    From coming with MIT License 5 votes vote down vote up
@Override
public void visit(NodeTraversal t, Node n, Node parent) {
  if (n.isCall()) {
    Node target = n.getFirstChild();
    // TODO(johnlenz): add this to the coding convention
    // so we can remove goog.reflect.sinkValue as well.
    if (target.isName() && target.getString().equals(PROTECTOR_FN)) {
      Node expr = n.getLastChild();
      n.detachChildren();
      parent.replaceChild(n, expr);
    }
  }
}
 
Example 14
Source File: Closure_105_FoldConstants_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Try to fold an array join: ['a', 'b', 'c'].join('') -> 'abc';
 */
void tryFoldStringJoin(NodeTraversal t, Node n, Node left, Node right,
                       Node parent) {
  if (!NodeUtil.isGetProp(left) || !NodeUtil.isImmutableValue(right)) {
    return;
  }

  Node arrayNode = left.getFirstChild();
  Node functionName = arrayNode.getNext();

  if ((arrayNode.getType() != Token.ARRAYLIT) ||
      !functionName.getString().equals("join")) {
    return;
  }

  String joinString = NodeUtil.getStringValue(right);
  List<Node> arrayFoldedChildren = Lists.newLinkedList();
  StringBuilder sb = new StringBuilder();
  int foldedSize = 0;
  Node elem = arrayNode.getFirstChild();
  // Merges adjacent String nodes.
  while (elem != null) {
    if (NodeUtil.isImmutableValue(elem)) {
      if (sb.length() > 0) {
        sb.append(joinString);
      }
      sb.append(NodeUtil.getStringValue(elem));
    } else {
      if (sb.length() > 0) {
        // + 2 for the quotes.
        foldedSize += sb.length() + 2;
        arrayFoldedChildren.add(Node.newString(sb.toString()));
        sb = new StringBuilder();
      }
      foldedSize += InlineCostEstimator.getCost(elem);
      arrayFoldedChildren.add(elem);
    }
    elem = elem.getNext();
  }

  if (sb.length() > 0) {
    // + 2 for the quotes.
    foldedSize += sb.length() + 2;
    arrayFoldedChildren.add(Node.newString(sb.toString()));
  }
  // one for each comma.
  foldedSize += arrayFoldedChildren.size() - 1;

  int originalSize = InlineCostEstimator.getCost(n);
  switch (arrayFoldedChildren.size()) {
    case 0:
      Node emptyStringNode = Node.newString("");
      parent.replaceChild(n, emptyStringNode);
      break;

    case 1:
      Node foldedStringNode = arrayFoldedChildren.remove(0);
      if (foldedSize > originalSize) {
        return;
      }
      arrayNode.detachChildren();
      if (foldedStringNode.getType() != Token.STRING) {
        // If the Node is not a string literal, ensure that
        // it is coerced to a string.
        Node replacement = new Node(Token.ADD,
            Node.newString(""), foldedStringNode);
        foldedStringNode = replacement;
      }
      parent.replaceChild(n, foldedStringNode);
      break;

    default:
      // No folding could actually be performed.
      if (arrayFoldedChildren.size() == arrayNode.getChildCount()) {
        return;
      }
      int kJoinOverhead = "[].join()".length();
      foldedSize += kJoinOverhead;
      foldedSize += InlineCostEstimator.getCost(right);
      if (foldedSize > originalSize) {
        return;
      }
      arrayNode.detachChildren();
      for (Node node : arrayFoldedChildren) {
        arrayNode.addChildToBack(node);
      }
      break;
  }
  t.getCompiler().reportCodeChange();
}
 
Example 15
Source File: Closure_97_PeepholeFoldConstants_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Try to fold a AND/OR node.
 */
private Node tryFoldAndOr(Node n, Node left, Node right) {
  Node parent = n.getParent();

  Node result = null;

  int type = n.getType();

  TernaryValue leftVal = NodeUtil.getBooleanValue(left);

  if (leftVal != TernaryValue.UNKNOWN) {
    boolean lval = leftVal.toBoolean(true);

    // (TRUE || x) => TRUE (also, (3 || x) => 3)
    // (FALSE && x) => FALSE
    if (lval && type == Token.OR ||
        !lval && type == Token.AND) {
      result = left;

    } else {
      // (FALSE || x) => x
      // (TRUE && x) => x
      result = right;
    }
  } else {
    TernaryValue rightVal = NodeUtil.getBooleanValue(right);
    if (rightVal != TernaryValue.UNKNOWN) {

    // Note: We cannot always fold when the constant is on the
    // right, because the typed value of the expression will depend
    // on the type of the constant on the right, even if the boolean
    // equivalent of the value does not. Specifically, in "a = x ||
    // 0", a will be numeric 0 if x is undefined (and hence is
    // e.g. a valid array index). However, it is safe to fold
    // e.g. "if (x || true)" because 'if' doesn't care if the
    // expression is 'true' or '3'.
    int pt = parent.getType();
    if (pt == Token.IF || pt == Token.WHILE || pt == Token.DO ||
        (pt == Token.FOR && NodeUtil.getConditionExpression(parent) == n) ||
        (pt == Token.HOOK && parent.getFirstChild() == n)) {
      boolean rval = rightVal.toBoolean(true);

      // (x || FALSE) => x
      // (x && TRUE) => x
      if (type == Token.OR && !rval ||
          type == Token.AND && rval) {
        result = left;
      } else {
        // If x has no side-effects:
        //   (x || TRUE) => TRUE
        //   (x && FALSE) => FALSE
        if (!NodeUtil.mayHaveSideEffects(left)) {
          result = right;
        }
      }
      }
    }
  }

  // Note: The parser parses 'x && FALSE && y' as 'x && (FALSE && y)', so
  // there is not much need to worry about const values on left's
  // right child.

  if (result != null) {
    // Fold it!
    n.removeChild(result);
    parent.replaceChild(n, result);
    reportCodeChange();

    return result;
  } else {
    return n;
  }
}
 
Example 16
Source File: Closure_1_RemoveUnusedVars_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Removes any vars in the scope that were not referenced. Removes any
 * assignments to those variables as well.
 */
private void removeUnreferencedVars() {
  CodingConvention convention = codingConvention;

  for (Iterator<Var> it = maybeUnreferenced.iterator(); it.hasNext(); ) {
    Var var = it.next();

    // Remove calls to inheritance-defining functions where the unreferenced
    // class is the subclass.
    for (Node exprCallNode : classDefiningCalls.get(var)) {
      NodeUtil.removeChild(exprCallNode.getParent(), exprCallNode);
      compiler.reportCodeChange();
    }

    // Regardless of what happens to the original declaration,
    // we need to remove all assigns, because they may contain references
    // to other unreferenced variables.
    removeAllAssigns(var);

    compiler.addToDebugLog("Unreferenced var: " + var.name);
    Node nameNode = var.nameNode;
    Node toRemove = nameNode.getParent();
    Node parent = toRemove.getParent();

    Preconditions.checkState(
        toRemove.isVar() ||
        toRemove.isFunction() ||
        toRemove.isParamList() &&
        parent.isFunction(),
        "We should only declare vars and functions and function args");

    if (toRemove.isParamList() &&
        parent.isFunction()) {
      // Don't remove function arguments here. That's a special case
      // that's taken care of in removeUnreferencedFunctionArgs.
    } else if (NodeUtil.isFunctionExpression(toRemove)) {
      if (!preserveFunctionExpressionNames) {
        toRemove.getFirstChild().setString("");
        compiler.reportCodeChange();
      }
      // Don't remove bleeding functions.
    } else if (parent != null &&
        parent.isFor() &&
        parent.getChildCount() < 4) {
      // foreach iterations have 3 children. Leave them alone.
    } else if (toRemove.isVar() &&
        nameNode.hasChildren() &&
        NodeUtil.mayHaveSideEffects(nameNode.getFirstChild(), compiler)) {
      // If this is a single var declaration, we can at least remove the
      // declaration itself and just leave the value, e.g.,
      // var a = foo(); => foo();
      if (toRemove.getChildCount() == 1) {
        parent.replaceChild(toRemove,
            IR.exprResult(nameNode.removeFirstChild()));
        compiler.reportCodeChange();
      }
    } else if (toRemove.isVar() &&
        toRemove.getChildCount() > 1) {
      // For var declarations with multiple names (i.e. var a, b, c),
      // only remove the unreferenced name
      toRemove.removeChild(nameNode);
      compiler.reportCodeChange();
    } else if (parent != null) {
      NodeUtil.removeChild(parent, toRemove);
      compiler.reportCodeChange();
    }
  }
}
 
Example 17
Source File: Cardumen_00152_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Removes any vars in the scope that were not referenced. Removes any
 * assignments to those variables as well.
 */
private void removeUnreferencedVars() {
  CodingConvention convention = codingConvention;

  for (Iterator<Var> it = maybeUnreferenced.iterator(); it.hasNext(); ) {
    Var var = it.next();

    // Remove calls to inheritance-defining functions where the unreferenced
    // class is the subclass.
    for (Node exprCallNode : inheritsCalls.get(var)) {
      NodeUtil.removeChild(exprCallNode.getParent(), exprCallNode);
      compiler.reportCodeChange();
    }

    // Regardless of what happens to the original declaration,
    // we need to remove all assigns, because they may contain references
    // to other unreferenced variables.
    removeAllAssigns(var);

    compiler.addToDebugLog("Unreferenced var: " + var.name);
    Node nameNode = var.nameNode;
    Node toRemove = nameNode.getParent();
    Node parent = toRemove.getParent();

    Preconditions.checkState(
        toRemove.isVar() ||
        toRemove.isFunction() ||
        toRemove.isParamList() &&
        parent.isFunction(),
        "We should only declare vars and functions and function args");

    if (toRemove.isParamList() &&
        parent.isFunction()) {
      // Don't remove function arguments here. That's a special case
      // that's taken care of in removeUnreferencedFunctionArgs.
    } else if (NodeUtil.isFunctionExpression(toRemove)) {
      if (!preserveFunctionExpressionNames) {
        toRemove.getFirstChild().setString("");
        compiler.reportCodeChange();
      }
      // Don't remove bleeding functions.
    } else if (parent != null &&
        parent.isFor() &&
        parent.getChildCount() < 4) {
      // foreach iterations have 3 children. Leave them alone.
    } else if (toRemove.isVar() &&
        nameNode.hasChildren() &&
        NodeUtil.mayHaveSideEffects(nameNode.getFirstChild())) {
      // If this is a single var declaration, we can at least remove the
      // declaration itself and just leave the value, e.g.,
      // var a = foo(); => foo();
      if (toRemove.getChildCount() == 1) {
        parent.replaceChild(toRemove,
            IR.exprResult(nameNode.removeFirstChild()));
        compiler.reportCodeChange();
      }
    } else if (toRemove.isVar() &&
        toRemove.getChildCount() > 1) {
      // For var declarations with multiple names (i.e. var a, b, c),
      // only remove the unreferenced name
      toRemove.removeChild(nameNode);
      compiler.reportCodeChange();
    } else if (parent != null) {
      NodeUtil.removeChild(parent, toRemove);
      compiler.reportCodeChange();
    }
  }
}
 
Example 18
Source File: Closure_126_MinimizeExitPoints_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 19
Source File: PeepholeReplaceKnownMethods.java    From astor with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Try to fold .split() calls on strings
 */
private Node tryFoldStringSplit(Node n, Node stringNode, Node arg1) {
  if (late) {
    return n;
  }

  Preconditions.checkArgument(n.isCall());
  Preconditions.checkArgument(stringNode.isString());

  String separator = null;
  String stringValue = stringNode.getString();

  // Maximum number of possible splits
  int limit = stringValue.length() + 1;

  if (arg1 != null) {
    if (arg1.isString()) {
      separator = arg1.getString();
    } else if (!arg1.isNull()) {
      return n;
    }

    Node arg2 = arg1.getNext();
    if (arg2 != null) {
      if (arg2.isNumber()) {
        limit = Math.min((int) arg2.getDouble(), limit);
        if (limit < 0) {
          return n;
        }
      } else {
        return n;
      }
    }
  }

  // Split the string and convert the returned array into JS nodes
  String[] stringArray = jsSplit(stringValue, separator, limit);
  Node arrayOfStrings = IR.arraylit();
  for (int i = 0; i < stringArray.length; i++) {
    arrayOfStrings.addChildToBack(
        IR.string(stringArray[i]).srcref(stringNode));
  }

  Node parent = n.getParent();
  parent.replaceChild(n, arrayOfStrings);
  reportCodeChange();
  return arrayOfStrings;
}
 
Example 20
Source File: StripCode.java    From astor with GNU General Public License v2.0 2 votes vote down vote up
/**
 * Replaces a node with a NULL node. This is useful where a value is
 * expected.
 *
 * @param n A node
 * @param parent {@code n}'s parent
 */
void replaceWithNull(Node n, Node parent) {
  parent.replaceChild(n, IR.nullNode());
}