diff --git a/src/com/google/javascript/jscomp/CollapseVariableDeclarations.java b/src/com/google/javascript/jscomp/CollapseVariableDeclarations.java index 13b9a5b11d3..76f461ade8a 100644 --- a/src/com/google/javascript/jscomp/CollapseVariableDeclarations.java +++ b/src/com/google/javascript/jscomp/CollapseVariableDeclarations.java @@ -230,7 +230,7 @@ private void applyCollapses() { Node next = n.getNext(); Preconditions.checkState(var.getNext() == n); - collapse.parent.removeChildAfter(var); + collapse.parent.removeChild(var.getNext()); if (n.isVar()) { while (n.hasChildren()) { diff --git a/src/com/google/javascript/jscomp/ExpandJqueryAliases.java b/src/com/google/javascript/jscomp/ExpandJqueryAliases.java index 0e3bb5e2e2a..1d812b678c3 100644 --- a/src/com/google/javascript/jscomp/ExpandJqueryAliases.java +++ b/src/com/google/javascript/jscomp/ExpandJqueryAliases.java @@ -271,7 +271,7 @@ private void maybeExpandJqueryExtendCall(Node n) { // remove any other pre-existing call arguments while (newCallTarget.getNext() != null) { - n.removeChildAfter(newCallTarget); + n.removeChild(newCallTarget.getNext()); } n.addChildToBack(IR.thisNode().srcref(n)); } @@ -501,7 +501,7 @@ private void replaceOriginalJqueryEachCall(Node n, Node expandedBlock) { // remove any other pre-existing call arguments while (fnc.getNext() != null) { - n.removeChildAfter(fnc); + n.removeChild(fnc.getNext()); } } compiler.reportCodeChange(); diff --git a/src/com/google/javascript/jscomp/Normalize.java b/src/com/google/javascript/jscomp/Normalize.java index 8a5791c95a7..7b8e4c6822e 100644 --- a/src/com/google/javascript/jscomp/Normalize.java +++ b/src/com/google/javascript/jscomp/Normalize.java @@ -655,32 +655,27 @@ private void splitVarDeclarations(Node n) { private void moveNamedFunctions(Node functionBody) { Preconditions.checkState( functionBody.getParent().isFunction()); - Node previous = null; + Node insertAfter = 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; + insertAfter = 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); + functionBody.removeChild(current); // Read the function at the top of the function body (after any // previous declarations). insertAfter = addToFront(functionBody, current, insertAfter); reportCodeChange("Move function declaration not at top of function"); - } else { - // Update the previous only if the current node hasn't been moved. - previous = current; } current = next; } diff --git a/src/com/google/javascript/jscomp/PeepholeRemoveDeadCode.java b/src/com/google/javascript/jscomp/PeepholeRemoveDeadCode.java index 4174dfab97f..53494e7314f 100644 --- a/src/com/google/javascript/jscomp/PeepholeRemoveDeadCode.java +++ b/src/com/google/javascript/jscomp/PeepholeRemoveDeadCode.java @@ -552,16 +552,15 @@ private Node tryFoldComma(Node n) { */ Node tryOptimizeBlock(Node n) { // Remove any useless children - for (Node c = n.getFirstChild(), prev = null; c != null; ) { + for (Node c = n.getFirstChild(); c != null; ) { Node next = c.getNext(); // save c.next, since 'c' may be removed if (!isUnremovableNode(c) && !mayHaveSideEffects(c)) { // TODO(johnlenz): determine what this is actually removing. Candidates // include: EMPTY nodes, control structures without children // (removing infinite loops), empty try blocks. What else? - n.removeFirstOrChildAfter(prev); + n.removeChild(c); reportCodeChange(); } else { - prev = c; tryOptimizeConditionalAfterAssign(c); } c = next; diff --git a/src/com/google/javascript/rhino/Node.java b/src/com/google/javascript/rhino/Node.java index 271a6bc3875..06a2b95c981 100644 --- a/src/com/google/javascript/rhino/Node.java +++ b/src/com/google/javascript/rhino/Node.java @@ -660,6 +660,10 @@ public Node getNext() { return next; } + public Node getPrevious() { + return previous; + } + public Node getChildBefore(Node child) { return child.previous; } @@ -868,42 +872,14 @@ public void replaceChild(Node child, Node newChild) { } public void replaceChildAfter(Node prevChild, Node newChild) { - Preconditions.checkArgument(prevChild.parent == this, - "prev is not a child of this node."); Preconditions.checkArgument(prevChild.next != null, "prev is doesn't have a sibling to replace."); - Preconditions.checkArgument(newChild.next == null, - "The new child node has next siblings."); - Preconditions.checkArgument(newChild.previous == null, - "The new child node has previous siblings."); - Preconditions.checkArgument(newChild.parent == null, - "The new child node already has a parent."); - - // Copy over important information. - newChild.copyInformationFrom(prevChild.next); - - Node childToReplace = prevChild.next; - newChild.next = childToReplace.next; - newChild.previous = prevChild; - newChild.parent = this; - prevChild.next = newChild; - if (childToReplace == last) { - last = newChild; - } else { - childToReplace.next.previous = newChild; - } - childToReplace.next = null; - childToReplace.previous = null; - childToReplace.parent = null; + replaceChild(prevChild.next, newChild); } /** Detaches the child after the given child, or the first child if prev is null. */ public void replaceFirstOrChildAfter(@Nullable Node prev, Node newChild) { - if (prev == null) { - replaceChild(getFirstChild(), newChild); - } else { - replaceChildAfter(prev, newChild); - } + replaceChild(prev == null ? first : prev.next, newChild); } @VisibleForTesting @@ -2031,23 +2007,10 @@ public void detachChildren() { } public Node removeChildAfter(Node prev) { - Preconditions.checkArgument(prev.parent == this, - "prev is not a child of this node."); - Preconditions.checkArgument(prev.next != null, - "no next sibling."); - - Node childToRemove = prev.next; - prev.next = childToRemove.next; - if (childToRemove == last) { - last = prev; - } - if (childToRemove.next != null) { - childToRemove.next.previous = prev; - } - childToRemove.next = null; - childToRemove.previous = null; - childToRemove.parent = null; - return childToRemove; + Node next = prev.next; + Preconditions.checkArgument(next != null, "no next sibling."); + removeChild(next); + return next; } /** Remove the child after the given child, or the first child if given null. */