annotate vendor/nikic/php-parser/doc/component/FAQ.markdown @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 5fb285c0d0e3
children
rev   line source
Chris@13 1 Frequently Asked Questions
Chris@13 2 ==========================
Chris@13 3
Chris@13 4 * [How can the parent of a node be obtained?](#how-can-the-parent-of-a-node-be-obtained)
Chris@13 5 * [How can the next/previous sibling of a node be obtained?](#how-can-the-nextprevious-sibling-of-a-node-be-obtained)
Chris@13 6
Chris@13 7 How can the parent of a node be obtained?
Chris@13 8 -----
Chris@13 9
Chris@13 10 The AST does not store parent nodes by default. However, it is easy to add a custom parent node
Chris@13 11 attribute using a custom node visitor:
Chris@13 12
Chris@13 13 ```php
Chris@13 14 use PhpParser\Node;
Chris@13 15 use PhpParser\NodeVisitorAbstract;
Chris@13 16
Chris@13 17 class ParentConnector extends NodeVisitorAbstract {
Chris@13 18 private $stack;
Chris@13 19 public function beforeTraverse(array $nodes) {
Chris@13 20 $this->stack = [];
Chris@13 21 }
Chris@13 22 public function enterNode(Node $node) {
Chris@13 23 if (!empty($this->stack)) {
Chris@13 24 $node->setAttribute('parent', $this->stack[count($this->stack)-1]);
Chris@13 25 }
Chris@13 26 $this->stack[] = $node;
Chris@13 27 }
Chris@13 28 public function leaveNode(Node $node) {
Chris@13 29 array_pop($this->stack);
Chris@13 30 }
Chris@13 31 }
Chris@13 32 ```
Chris@13 33
Chris@13 34 After running this visitor, the parent node can be obtained through `$node->getAttribute('parent')`.
Chris@13 35
Chris@13 36 How can the next/previous sibling of a node be obtained?
Chris@13 37 -----
Chris@13 38
Chris@13 39 Again, siblings are not stored by default, but the visitor from the previous entry can be easily
Chris@13 40 extended to store the previous / next node with a common parent as well:
Chris@13 41
Chris@13 42 ```php
Chris@13 43 use PhpParser\Node;
Chris@13 44 use PhpParser\NodeVisitorAbstract;
Chris@13 45
Chris@13 46 class NodeConnector extends NodeVisitorAbstract {
Chris@13 47 private $stack;
Chris@13 48 private $prev;
Chris@13 49 public function beforeTraverse(array $nodes) {
Chris@13 50 $this->stack = [];
Chris@13 51 $this->prev = null;
Chris@13 52 }
Chris@13 53 public function enterNode(Node $node) {
Chris@13 54 if (!empty($this->stack)) {
Chris@13 55 $node->setAttribute('parent', $this->stack[count($this->stack)-1]);
Chris@13 56 }
Chris@13 57 if ($this->prev && $this->prev->getAttribute('parent') == $node->getAttribute('parent')) {
Chris@13 58 $node->setAttribute('prev', $this->prev);
Chris@13 59 $this->prev->setAttribute('next', $node);
Chris@13 60 }
Chris@13 61 $this->stack[] = $node;
Chris@13 62 }
Chris@13 63 public function leaveNode(Node $node) {
Chris@13 64 $this->prev = $node;
Chris@13 65 array_pop($this->stack);
Chris@13 66 }
Chris@13 67 }
Chris@13 68 ```