mirror of
https://github.com/phabelio/PHP-Parser.git
synced 2025-01-22 13:21:12 +01:00
b49c55c9e5
a) ->traverseNode() now operates on a clone of the node, otherwise the original node will be modified too b) before nodes were passed to the following visitor unchanged, even though they were already changed in the tree
124 lines
3.6 KiB
PHP
124 lines
3.6 KiB
PHP
<?php
|
|
|
|
class PHPParser_NodeTraverser
|
|
{
|
|
/**
|
|
* @var PHPParser_NodeVisitor[] Visitors
|
|
*/
|
|
protected $visitors;
|
|
|
|
/**
|
|
* Constructs a node traverser.
|
|
*/
|
|
public function __construct() {
|
|
$this->visitors = array();
|
|
}
|
|
|
|
/**
|
|
* Adds a visitor.
|
|
*
|
|
* @param PHPParser_NodeVisitor $visitor Visitor to add
|
|
*/
|
|
public function addVisitor(PHPParser_NodeVisitor $visitor) {
|
|
$this->visitors[] = $visitor;
|
|
}
|
|
|
|
/**
|
|
* Traverses an array of nodes using the registered visitors.
|
|
*
|
|
* @param PHPParser_Node[] $nodes Array of nodes
|
|
*
|
|
* @return PHPParser_Node[] Traversed array of nodes
|
|
*/
|
|
public function traverse(array $nodes) {
|
|
foreach ($this->visitors as $visitor) {
|
|
if (null !== $return = $visitor->beforeTraverse($nodes)) {
|
|
$nodes = $return;
|
|
}
|
|
}
|
|
|
|
$nodes = $this->traverseArray($nodes);
|
|
|
|
foreach ($this->visitors as $visitor) {
|
|
if (null !== $return = $visitor->afterTraverse($nodes)) {
|
|
$nodes = $return;
|
|
}
|
|
}
|
|
|
|
return $nodes;
|
|
}
|
|
|
|
protected function traverseNode(PHPParser_Node $node) {
|
|
$node = clone $node;
|
|
|
|
foreach ($node->getSubNodeNames() as $name) {
|
|
$subNode =& $node->$name;
|
|
|
|
if (is_array($subNode)) {
|
|
$subNode = $this->traverseArray($subNode);
|
|
} elseif ($subNode instanceof PHPParser_Node) {
|
|
foreach ($this->visitors as $visitor) {
|
|
if (null !== $return = $visitor->enterNode($subNode)) {
|
|
$subNode = $return;
|
|
}
|
|
}
|
|
|
|
$subNode = $this->traverseNode($subNode);
|
|
|
|
foreach ($this->visitors as $visitor) {
|
|
if (null !== $return = $visitor->leaveNode($subNode)) {
|
|
$subNode = $return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $node;
|
|
}
|
|
|
|
protected function traverseArray(array $nodes) {
|
|
$doNodes = array();
|
|
|
|
foreach ($nodes as $i => &$node) {
|
|
if (is_array($node)) {
|
|
$node = $this->traverseArray($node);
|
|
} elseif ($node instanceof PHPParser_Node) {
|
|
foreach ($this->visitors as $visitor) {
|
|
if (null !== $return = $visitor->enterNode($node)) {
|
|
$node = $return;
|
|
}
|
|
}
|
|
|
|
$node = $this->traverseNode($node);
|
|
|
|
foreach ($this->visitors as $j => $visitor) {
|
|
$return = $visitor->leaveNode($node);
|
|
|
|
if (false === $return) {
|
|
$doNodes[] = array($i, array());
|
|
break;
|
|
} elseif (is_array($return)) {
|
|
// traverse replacement nodes using all visitors apart from the one that
|
|
// did the change
|
|
unset($this->visitors[$j]);
|
|
$return = $this->traverseArray($return);
|
|
$this->visitors[$j] = $visitor;
|
|
|
|
$doNodes[] = array($i, $return);
|
|
break;
|
|
} elseif (null !== $return) {
|
|
$node = $return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($doNodes)) {
|
|
while (list($i, $replace) = array_pop($doNodes)) {
|
|
array_splice($nodes, $i, 1, $replace);
|
|
}
|
|
}
|
|
|
|
return $nodes;
|
|
}
|
|
} |