From 4cac2f299bea00990af0ea616c23788394f47a03 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 1 Jan 2025 11:48:53 +0100 Subject: [PATCH 1/4] Support WeakReferences in NodeConnectingVisitor --- .../NodeVisitor/NodeConnectingVisitor.php | 21 +++++++++++++--- .../NodeVisitor/NodeConnectingVisitorTest.php | 24 +++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php b/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php index 38fedfd506..26bdd0857f 100644 --- a/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php +++ b/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php @@ -25,6 +25,12 @@ final class NodeConnectingVisitor extends NodeVisitorAbstract { */ private $previous; + private bool $weakReferences; + + public function __construct(bool $weakReferences = false) { + $this->weakReferences = $weakReferences; + } + public function beforeTraverse(array $nodes) { $this->stack = []; $this->previous = null; @@ -32,12 +38,21 @@ public function beforeTraverse(array $nodes) { public function enterNode(Node $node) { if (!empty($this->stack)) { - $node->setAttribute('parent', $this->stack[count($this->stack) - 1]); + $parent = $this->stack[count($this->stack) - 1]; + if ($this->weakReferences) { + $parent = \WeakReference::create($parent); + } + $node->setAttribute('parent', $parent); } if ($this->previous !== null && $this->previous->getAttribute('parent') === $node->getAttribute('parent')) { - $node->setAttribute('previous', $this->previous); - $this->previous->setAttribute('next', $node); + if ($this->weakReferences) { + $node->setAttribute('previous', \WeakReference::create($this->previous)); + $this->previous->setAttribute('next', \WeakReference::create($node)); + } else { + $node->setAttribute('previous', $this->previous); + $this->previous->setAttribute('next', $node); + } } $this->stack[] = $node; diff --git a/test/PhpParser/NodeVisitor/NodeConnectingVisitorTest.php b/test/PhpParser/NodeVisitor/NodeConnectingVisitorTest.php index eab58776cd..bdc57cca7b 100644 --- a/test/PhpParser/NodeVisitor/NodeConnectingVisitorTest.php +++ b/test/PhpParser/NodeVisitor/NodeConnectingVisitorTest.php @@ -30,4 +30,28 @@ public function testConnectsNodeToItsParentNodeAndItsSiblingNodes(): void { $this->assertSame(Else_::class, get_class($node->getAttribute('next'))); } + + public function testWeakReferences(): void { + $ast = (new ParserFactory())->createForNewestSupportedVersion()->parse( + 'addVisitor(new NodeConnectingVisitor(true)); + + $ast = $traverser->traverse($ast); + + $node = (new NodeFinder())->findFirstInstanceof($ast, Else_::class); + + $this->assertInstanceOf(\WeakReference::class, $node->getAttribute('parent')); + $this->assertSame(If_::class, get_class($node->getAttribute('parent')->get())); + $this->assertInstanceOf(\WeakReference::class, $node->getAttribute('previous')); + $this->assertSame(ConstFetch::class, get_class($node->getAttribute('previous')->get())); + + $node = (new NodeFinder())->findFirstInstanceof($ast, ConstFetch::class); + + $this->assertInstanceOf(\WeakReference::class, $node->getAttribute('next')); + $this->assertSame(Else_::class, get_class($node->getAttribute('next')->get())); + } } From e002a9538bf0b91e9f901effa5e9ef569b62623a Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 1 Jan 2025 11:49:38 +0100 Subject: [PATCH 2/4] Support WeakReferences in ParentConnectingVisitor --- .../NodeVisitor/ParentConnectingVisitor.php | 12 +++++++++++- .../ParentConnectingVisitorTest.php | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php b/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php index 1e7e9e8be5..e0f8a2f58c 100644 --- a/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php +++ b/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php @@ -20,13 +20,23 @@ final class ParentConnectingVisitor extends NodeVisitorAbstract { */ private array $stack = []; + private bool $weakReferences; + + public function __construct(bool $weakReferences = false) { + $this->weakReferences = $weakReferences; + } + public function beforeTraverse(array $nodes) { $this->stack = []; } public function enterNode(Node $node) { if (!empty($this->stack)) { - $node->setAttribute('parent', $this->stack[count($this->stack) - 1]); + $parent = $this->stack[count($this->stack) - 1]; + if ($this->weakReferences) { + $parent = \WeakReference::create($parent); + } + $node->setAttribute('parent', $parent); } $this->stack[] = $node; diff --git a/test/PhpParser/NodeVisitor/ParentConnectingVisitorTest.php b/test/PhpParser/NodeVisitor/ParentConnectingVisitorTest.php index 8f66a36479..b4e8479b54 100644 --- a/test/PhpParser/NodeVisitor/ParentConnectingVisitorTest.php +++ b/test/PhpParser/NodeVisitor/ParentConnectingVisitorTest.php @@ -23,4 +23,22 @@ public function testConnectsChildNodeToParentNode(): void { $this->assertSame('C', $node->getAttribute('parent')->name->toString()); } + + public function testWeakReferences(): void { + $ast = (new ParserFactory())->createForNewestSupportedVersion()->parse( + 'addVisitor(new ParentConnectingVisitor(true)); + + $ast = $traverser->traverse($ast); + + $node = (new NodeFinder())->findFirstInstanceof($ast, ClassMethod::class); + + $weakReference = $node->getAttribute('parent'); + $this->assertInstanceOf(\WeakReference::class, $weakReference); + $this->assertSame('C', $weakReference->get()->name->toString()); + } } From c0002a0c431c55b02faebd1a90f6a94f1d2af715 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 1 Jan 2025 11:49:50 +0100 Subject: [PATCH 3/4] Added tests make target --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 1473c9998c..a1057d052c 100644 --- a/Makefile +++ b/Makefile @@ -8,3 +8,6 @@ phpstan: tools/vendor php-cs-fixer: tools/vendor php tools/vendor/bin/php-cs-fixer fix + +tests: + php vendor/bin/phpunit \ No newline at end of file From 894fb3d9d6feeffba3a922f689248da58f848304 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Wed, 1 Jan 2025 20:13:19 +0100 Subject: [PATCH 4/4] Use "weak_"-prefix for attributenames --- .../NodeVisitor/NodeConnectingVisitor.php | 18 +++++++++++------- .../NodeVisitor/ParentConnectingVisitor.php | 5 +++-- .../NodeVisitor/NodeConnectingVisitorTest.php | 12 ++++++------ .../ParentConnectingVisitorTest.php | 2 +- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php b/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php index 26bdd0857f..a772a7d812 100644 --- a/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php +++ b/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php @@ -40,16 +40,20 @@ public function enterNode(Node $node) { if (!empty($this->stack)) { $parent = $this->stack[count($this->stack) - 1]; if ($this->weakReferences) { - $parent = \WeakReference::create($parent); + $node->setAttribute('weak_parent', \WeakReference::create($parent)); + } else { + $node->setAttribute('parent', $parent); } - $node->setAttribute('parent', $parent); } - if ($this->previous !== null && $this->previous->getAttribute('parent') === $node->getAttribute('parent')) { - if ($this->weakReferences) { - $node->setAttribute('previous', \WeakReference::create($this->previous)); - $this->previous->setAttribute('next', \WeakReference::create($node)); - } else { + if ($this->previous !== null) { + if ( + $this->weakReferences + && $this->previous->getAttribute('weak_parent') === $node->getAttribute('weak_parent') + ) { + $node->setAttribute('weak_previous', \WeakReference::create($this->previous)); + $this->previous->setAttribute('weak_next', \WeakReference::create($node)); + } elseif ($this->previous->getAttribute('parent') === $node->getAttribute('parent')) { $node->setAttribute('previous', $this->previous); $this->previous->setAttribute('next', $node); } diff --git a/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php b/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php index e0f8a2f58c..dc322528b5 100644 --- a/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php +++ b/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php @@ -34,9 +34,10 @@ public function enterNode(Node $node) { if (!empty($this->stack)) { $parent = $this->stack[count($this->stack) - 1]; if ($this->weakReferences) { - $parent = \WeakReference::create($parent); + $node->setAttribute('weak_parent', \WeakReference::create($parent)); + } else { + $node->setAttribute('parent', $parent); } - $node->setAttribute('parent', $parent); } $this->stack[] = $node; diff --git a/test/PhpParser/NodeVisitor/NodeConnectingVisitorTest.php b/test/PhpParser/NodeVisitor/NodeConnectingVisitorTest.php index bdc57cca7b..c9ac5e898a 100644 --- a/test/PhpParser/NodeVisitor/NodeConnectingVisitorTest.php +++ b/test/PhpParser/NodeVisitor/NodeConnectingVisitorTest.php @@ -44,14 +44,14 @@ public function testWeakReferences(): void { $node = (new NodeFinder())->findFirstInstanceof($ast, Else_::class); - $this->assertInstanceOf(\WeakReference::class, $node->getAttribute('parent')); - $this->assertSame(If_::class, get_class($node->getAttribute('parent')->get())); - $this->assertInstanceOf(\WeakReference::class, $node->getAttribute('previous')); - $this->assertSame(ConstFetch::class, get_class($node->getAttribute('previous')->get())); + $this->assertInstanceOf(\WeakReference::class, $node->getAttribute('weak_parent')); + $this->assertSame(If_::class, get_class($node->getAttribute('weak_parent')->get())); + $this->assertInstanceOf(\WeakReference::class, $node->getAttribute('weak_previous')); + $this->assertSame(ConstFetch::class, get_class($node->getAttribute('weak_previous')->get())); $node = (new NodeFinder())->findFirstInstanceof($ast, ConstFetch::class); - $this->assertInstanceOf(\WeakReference::class, $node->getAttribute('next')); - $this->assertSame(Else_::class, get_class($node->getAttribute('next')->get())); + $this->assertInstanceOf(\WeakReference::class, $node->getAttribute('weak_next')); + $this->assertSame(Else_::class, get_class($node->getAttribute('weak_next')->get())); } } diff --git a/test/PhpParser/NodeVisitor/ParentConnectingVisitorTest.php b/test/PhpParser/NodeVisitor/ParentConnectingVisitorTest.php index b4e8479b54..059c2260ff 100644 --- a/test/PhpParser/NodeVisitor/ParentConnectingVisitorTest.php +++ b/test/PhpParser/NodeVisitor/ParentConnectingVisitorTest.php @@ -37,7 +37,7 @@ public function testWeakReferences(): void { $node = (new NodeFinder())->findFirstInstanceof($ast, ClassMethod::class); - $weakReference = $node->getAttribute('parent'); + $weakReference = $node->getAttribute('weak_parent'); $this->assertInstanceOf(\WeakReference::class, $weakReference); $this->assertSame('C', $weakReference->get()->name->toString()); }