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 ```
|