diff --git a/lib/PHPParser/NodeTraverser.php b/lib/PHPParser/NodeTraverser.php index 0111488b..3de3549f 100644 --- a/lib/PHPParser/NodeTraverser.php +++ b/lib/PHPParser/NodeTraverser.php @@ -41,21 +41,54 @@ class PHPParser_NodeTraverser } protected function _traverse(&$node) { - if ($node instanceof PHPParser_NodeAbstract) { - foreach ($this->visitors as $visitor) { - $visitor->enterNode($node); + if (!is_array($node) && !$node instanceof Traversable) { + return; + } + + $delNodes = array(); + $mrgNodes = array(); + + foreach ($node as $subNodeKey => &$subNode) { + if ($subNode instanceof PHPParser_NodeAbstract) { + foreach ($this->visitors as $visitor) { + $visitor->enterNode($subNode); + } + } + + $this->_traverse($subNode); + + if ($subNode instanceof PHPParser_NodeAbstract) { + foreach ($this->visitors as $visitor) { + $return = $visitor->leaveNode($subNode); + + if (false === $return) { + $delNodes[] = $subNodeKey; + } elseif (is_array($return)) { + $mrgNodes[] = array($subNodeKey, $return); + } + } } } - if (is_array($node) || $node instanceof Traversable) { - foreach ($node as &$subNode) { - $this->_traverse($subNode); + if (!empty($delNodes)) { + if (is_array($node)) { + while ($delKey = array_pop($delNodes)) { + array_splice($node, $delKey, 1, array()); + } + } else { + while ($delKey = array_pop($delNodes)) { + unset($node[$delKey]); + } } } - if ($node instanceof PHPParser_NodeAbstract) { - foreach ($this->visitors as $visitor) { - $visitor->leaveNode($node); + if (!empty($mrgNodes)) { + if (is_array($node)) { + while (list($mrgKey, $mrgItems) = array_pop($mrgNodes)) { + array_splice($node, $mrgKey, 1, $mrgItems); + } + } else { + throw new Exception('Nodes can only be merged if the parent is an array'); } } }