1: | <?php declare(strict_types=1); |
2: | |
3: | namespace PhpParser\NodeVisitor; |
4: | |
5: | use PhpParser\Node; |
6: | use PhpParser\NodeVisitorAbstract; |
7: | |
8: | |
9: | |
10: | |
11: | |
12: | |
13: | |
14: | |
15: | |
16: | |
17: | |
18: | |
19: | final class NodeConnectingVisitor extends NodeVisitorAbstract { |
20: | |
21: | |
22: | |
23: | private array $stack = []; |
24: | |
25: | |
26: | |
27: | |
28: | private $previous; |
29: | |
30: | private bool $weakReferences; |
31: | |
32: | public function __construct(bool $weakReferences = false) { |
33: | $this->weakReferences = $weakReferences; |
34: | } |
35: | |
36: | public function beforeTraverse(array $nodes) { |
37: | $this->stack = []; |
38: | $this->previous = null; |
39: | } |
40: | |
41: | public function enterNode(Node $node) { |
42: | if (!empty($this->stack)) { |
43: | $parent = $this->stack[count($this->stack) - 1]; |
44: | if ($this->weakReferences) { |
45: | $node->setAttribute('weak_parent', \WeakReference::create($parent)); |
46: | } else { |
47: | $node->setAttribute('parent', $parent); |
48: | } |
49: | } |
50: | |
51: | if ($this->previous !== null) { |
52: | if ( |
53: | $this->weakReferences |
54: | ) { |
55: | if ($this->previous->getAttribute('weak_parent') === $node->getAttribute('weak_parent')) { |
56: | $node->setAttribute('weak_previous', \WeakReference::create($this->previous)); |
57: | $this->previous->setAttribute('weak_next', \WeakReference::create($node)); |
58: | } |
59: | } elseif ($this->previous->getAttribute('parent') === $node->getAttribute('parent')) { |
60: | $node->setAttribute('previous', $this->previous); |
61: | $this->previous->setAttribute('next', $node); |
62: | } |
63: | } |
64: | |
65: | $this->stack[] = $node; |
66: | } |
67: | |
68: | public function leaveNode(Node $node) { |
69: | $this->previous = $node; |
70: | |
71: | array_pop($this->stack); |
72: | } |
73: | } |
74: | |