1: <?php declare(strict_types=1);
2:
3: namespace PhpParser\NodeVisitor;
4:
5: use PhpParser\Node;
6: use PhpParser\NodeVisitorAbstract;
7:
8: /**
9: * Visitor that connects a child node to its parent node
10: * as well as its sibling nodes.
11: *
12: * On the child node, the parent node can be accessed through
13: * <code>$node->getAttribute('parent')</code>, the previous
14: * node can be accessed through <code>$node->getAttribute('previous')</code>,
15: * and the next node can be accessed through <code>$node->getAttribute('next')</code>.
16: */
17: final class NodeConnectingVisitor extends NodeVisitorAbstract
18: {
19: /**
20: * @var Node[]
21: */
22: private $stack = [];
23:
24: /**
25: * @var ?Node
26: */
27: private $previous;
28:
29: public function beforeTraverse(array $nodes) {
30: $this->stack = [];
31: $this->previous = null;
32: }
33:
34: public function enterNode(Node $node) {
35: if (!empty($this->stack)) {
36: $node->setAttribute('parent', $this->stack[count($this->stack) - 1]);
37: }
38:
39: if ($this->previous !== null && $this->previous->getAttribute('parent') === $node->getAttribute('parent')) {
40: $node->setAttribute('previous', $this->previous);
41: $this->previous->setAttribute('next', $node);
42: }
43:
44: $this->stack[] = $node;
45: }
46:
47: public function leaveNode(Node $node) {
48: $this->previous = $node;
49:
50: array_pop($this->stack);
51: }
52: }
53: