annotate vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php @ 2:92f882872392

Trusted hosts, + remove migration modules
author Chris Cannam
date Tue, 05 Dec 2017 09:26:43 +0000
parents 4c8ae668cc8c
children 5fb285c0d0e3
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace PhpParser;
Chris@0 4
Chris@0 5 class NodeTraverser implements NodeTraverserInterface
Chris@0 6 {
Chris@0 7 /**
Chris@0 8 * If NodeVisitor::enterNode() returns DONT_TRAVERSE_CHILDREN, child nodes
Chris@0 9 * of the current node will not be traversed for any visitors.
Chris@0 10 *
Chris@0 11 * For subsequent visitors enterNode() will still be called on the current
Chris@0 12 * node and leaveNode() will also be invoked for the current node.
Chris@0 13 */
Chris@0 14 const DONT_TRAVERSE_CHILDREN = 1;
Chris@0 15
Chris@0 16 /**
Chris@0 17 * If NodeVisitor::enterNode() or NodeVisitor::leaveNode() returns
Chris@0 18 * STOP_TRAVERSAL, traversal is aborted.
Chris@0 19 *
Chris@0 20 * The afterTraverse() method will still be invoked.
Chris@0 21 */
Chris@0 22 const STOP_TRAVERSAL = 2;
Chris@0 23
Chris@0 24 /**
Chris@0 25 * If NodeVisitor::leaveNode() returns REMOVE_NODE for a node that occurs
Chris@0 26 * in an array, it will be removed from the array.
Chris@0 27 *
Chris@0 28 * For subsequent visitors leaveNode() will still be invoked for the
Chris@0 29 * removed node.
Chris@0 30 */
Chris@0 31 const REMOVE_NODE = false;
Chris@0 32
Chris@0 33 /** @var NodeVisitor[] Visitors */
Chris@0 34 protected $visitors;
Chris@0 35
Chris@0 36 /** @var bool Whether traversal should be stopped */
Chris@0 37 protected $stopTraversal;
Chris@0 38
Chris@0 39 /**
Chris@0 40 * Constructs a node traverser.
Chris@0 41 */
Chris@0 42 public function __construct() {
Chris@0 43 $this->visitors = array();
Chris@0 44 }
Chris@0 45
Chris@0 46 /**
Chris@0 47 * Adds a visitor.
Chris@0 48 *
Chris@0 49 * @param NodeVisitor $visitor Visitor to add
Chris@0 50 */
Chris@0 51 public function addVisitor(NodeVisitor $visitor) {
Chris@0 52 $this->visitors[] = $visitor;
Chris@0 53 }
Chris@0 54
Chris@0 55 /**
Chris@0 56 * Removes an added visitor.
Chris@0 57 *
Chris@0 58 * @param NodeVisitor $visitor
Chris@0 59 */
Chris@0 60 public function removeVisitor(NodeVisitor $visitor) {
Chris@0 61 foreach ($this->visitors as $index => $storedVisitor) {
Chris@0 62 if ($storedVisitor === $visitor) {
Chris@0 63 unset($this->visitors[$index]);
Chris@0 64 break;
Chris@0 65 }
Chris@0 66 }
Chris@0 67 }
Chris@0 68
Chris@0 69 /**
Chris@0 70 * Traverses an array of nodes using the registered visitors.
Chris@0 71 *
Chris@0 72 * @param Node[] $nodes Array of nodes
Chris@0 73 *
Chris@0 74 * @return Node[] Traversed array of nodes
Chris@0 75 */
Chris@0 76 public function traverse(array $nodes) {
Chris@0 77 $this->stopTraversal = false;
Chris@0 78
Chris@0 79 foreach ($this->visitors as $visitor) {
Chris@0 80 if (null !== $return = $visitor->beforeTraverse($nodes)) {
Chris@0 81 $nodes = $return;
Chris@0 82 }
Chris@0 83 }
Chris@0 84
Chris@0 85 $nodes = $this->traverseArray($nodes);
Chris@0 86
Chris@0 87 foreach ($this->visitors as $visitor) {
Chris@0 88 if (null !== $return = $visitor->afterTraverse($nodes)) {
Chris@0 89 $nodes = $return;
Chris@0 90 }
Chris@0 91 }
Chris@0 92
Chris@0 93 return $nodes;
Chris@0 94 }
Chris@0 95
Chris@0 96 protected function traverseNode(Node $node) {
Chris@0 97 foreach ($node->getSubNodeNames() as $name) {
Chris@0 98 $subNode =& $node->$name;
Chris@0 99
Chris@0 100 if (is_array($subNode)) {
Chris@0 101 $subNode = $this->traverseArray($subNode);
Chris@0 102 if ($this->stopTraversal) {
Chris@0 103 break;
Chris@0 104 }
Chris@0 105 } elseif ($subNode instanceof Node) {
Chris@0 106 $traverseChildren = true;
Chris@0 107 foreach ($this->visitors as $visitor) {
Chris@0 108 $return = $visitor->enterNode($subNode);
Chris@0 109 if (self::DONT_TRAVERSE_CHILDREN === $return) {
Chris@0 110 $traverseChildren = false;
Chris@0 111 } else if (self::STOP_TRAVERSAL === $return) {
Chris@0 112 $this->stopTraversal = true;
Chris@0 113 break 2;
Chris@0 114 } else if (null !== $return) {
Chris@0 115 $subNode = $return;
Chris@0 116 }
Chris@0 117 }
Chris@0 118
Chris@0 119 if ($traverseChildren) {
Chris@0 120 $subNode = $this->traverseNode($subNode);
Chris@0 121 if ($this->stopTraversal) {
Chris@0 122 break;
Chris@0 123 }
Chris@0 124 }
Chris@0 125
Chris@0 126 foreach ($this->visitors as $visitor) {
Chris@0 127 $return = $visitor->leaveNode($subNode);
Chris@0 128 if (self::STOP_TRAVERSAL === $return) {
Chris@0 129 $this->stopTraversal = true;
Chris@0 130 break 2;
Chris@0 131 } else if (null !== $return) {
Chris@0 132 if (is_array($return)) {
Chris@0 133 throw new \LogicException(
Chris@0 134 'leaveNode() may only return an array ' .
Chris@0 135 'if the parent structure is an array'
Chris@0 136 );
Chris@0 137 }
Chris@0 138 $subNode = $return;
Chris@0 139 }
Chris@0 140 }
Chris@0 141 }
Chris@0 142 }
Chris@0 143
Chris@0 144 return $node;
Chris@0 145 }
Chris@0 146
Chris@0 147 protected function traverseArray(array $nodes) {
Chris@0 148 $doNodes = array();
Chris@0 149
Chris@0 150 foreach ($nodes as $i => &$node) {
Chris@0 151 if (is_array($node)) {
Chris@0 152 $node = $this->traverseArray($node);
Chris@0 153 if ($this->stopTraversal) {
Chris@0 154 break;
Chris@0 155 }
Chris@0 156 } elseif ($node instanceof Node) {
Chris@0 157 $traverseChildren = true;
Chris@0 158 foreach ($this->visitors as $visitor) {
Chris@0 159 $return = $visitor->enterNode($node);
Chris@0 160 if (self::DONT_TRAVERSE_CHILDREN === $return) {
Chris@0 161 $traverseChildren = false;
Chris@0 162 } else if (self::STOP_TRAVERSAL === $return) {
Chris@0 163 $this->stopTraversal = true;
Chris@0 164 break 2;
Chris@0 165 } else if (null !== $return) {
Chris@0 166 $node = $return;
Chris@0 167 }
Chris@0 168 }
Chris@0 169
Chris@0 170 if ($traverseChildren) {
Chris@0 171 $node = $this->traverseNode($node);
Chris@0 172 if ($this->stopTraversal) {
Chris@0 173 break;
Chris@0 174 }
Chris@0 175 }
Chris@0 176
Chris@0 177 foreach ($this->visitors as $visitor) {
Chris@0 178 $return = $visitor->leaveNode($node);
Chris@0 179
Chris@0 180 if (self::REMOVE_NODE === $return) {
Chris@0 181 $doNodes[] = array($i, array());
Chris@0 182 break;
Chris@0 183 } else if (self::STOP_TRAVERSAL === $return) {
Chris@0 184 $this->stopTraversal = true;
Chris@0 185 break 2;
Chris@0 186 } elseif (is_array($return)) {
Chris@0 187 $doNodes[] = array($i, $return);
Chris@0 188 break;
Chris@0 189 } elseif (null !== $return) {
Chris@0 190 $node = $return;
Chris@0 191 }
Chris@0 192 }
Chris@0 193 }
Chris@0 194 }
Chris@0 195
Chris@0 196 if (!empty($doNodes)) {
Chris@0 197 while (list($i, $replace) = array_pop($doNodes)) {
Chris@0 198 array_splice($nodes, $i, 1, $replace);
Chris@0 199 }
Chris@0 200 }
Chris@0 201
Chris@0 202 return $nodes;
Chris@0 203 }
Chris@0 204 }