/** * Replaces a node with an EMPTY node. This is useful where a statement is expected. * * @param n A node * @param parent {@code n}'s parent */ void replaceWithEmpty(Node n, Node parent) { NodeUtil.removeChild(parent, n); }
@Override public void remove() { compiler.reportChangeToEnclosingScope(var); NodeUtil.removeChild(var.getParent(), var); }
/** * 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.getType() == Token.VAR || toRemove.getType() == Token.FUNCTION || toRemove.getType() == Token.LP && parent.getType() == Token.FUNCTION, "We should only declare vars and functions and function args"); if (toRemove.getType() == Token.LP && parent.getType() == Token.FUNCTION) { // 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.getType() == Token.FOR && parent.getChildCount() < 4) { // foreach iterations have 3 children. Leave them alone. } else if (toRemove.getType() == Token.VAR && 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, new Node(Token.EXPR_RESULT, nameNode.removeFirstChild())); compiler.reportCodeChange(); } } else if (toRemove.getType() == Token.VAR && 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(); } } }