From 1f4e5f6a30bf45b6c2c932be7396ea70692ee607 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Mon, 1 Nov 2021 16:35:39 +0100 Subject: [PATCH] Traverser: can return different nodes --- src/Neon/Node/ArrayItemNode.php | 2 +- src/Neon/Node/ArrayNode.php | 6 ++++- src/Neon/Node/EntityChainNode.php | 6 ++++- src/Neon/Node/EntityNode.php | 6 ++++- src/Neon/Traverser.php | 10 ++++---- tests/Neon/Traverser.alter.phpt | 40 +++++++++++++++++++++++++++++++ 6 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 tests/Neon/Traverser.alter.phpt diff --git a/src/Neon/Node/ArrayItemNode.php b/src/Neon/Node/ArrayItemNode.php index 5897e72f..eae86116 100644 --- a/src/Neon/Node/ArrayItemNode.php +++ b/src/Neon/Node/ArrayItemNode.php @@ -85,6 +85,6 @@ public function toString(): string public function getSubNodes(): array { - return $this->key ? [$this->key, $this->value] : [$this->value]; + return $this->key ? [&$this->key, &$this->value] : [&$this->value]; } } diff --git a/src/Neon/Node/ArrayNode.php b/src/Neon/Node/ArrayNode.php index b4ed65c9..c5f1ecff 100644 --- a/src/Neon/Node/ArrayNode.php +++ b/src/Neon/Node/ArrayNode.php @@ -53,6 +53,10 @@ public function toString(): string public function getSubNodes(): array { - return $this->items; + $res = []; + foreach ($this->items as &$item) { + $res[] = &$item; + } + return $res; } } diff --git a/src/Neon/Node/EntityChainNode.php b/src/Neon/Node/EntityChainNode.php index 2e5fdff3..8501dff7 100644 --- a/src/Neon/Node/EntityChainNode.php +++ b/src/Neon/Node/EntityChainNode.php @@ -46,6 +46,10 @@ public function toString(): string public function getSubNodes(): array { - return $this->chain; + $res = []; + foreach ($this->chain as &$item) { + $res[] = &$item; + } + return $res; } } diff --git a/src/Neon/Node/EntityNode.php b/src/Neon/Node/EntityNode.php index 4bd0ba82..81a476eb 100644 --- a/src/Neon/Node/EntityNode.php +++ b/src/Neon/Node/EntityNode.php @@ -52,6 +52,10 @@ public function toString(): string public function getSubNodes(): array { - return array_merge([$this->value], $this->attributes); + $res = [&$this->value]; + foreach ($this->attributes as &$item) { + $res[] = &$item; + } + return $res; } } diff --git a/src/Neon/Traverser.php b/src/Neon/Traverser.php index 58fc39b9..f25bfe49 100644 --- a/src/Neon/Traverser.php +++ b/src/Neon/Traverser.php @@ -13,11 +13,11 @@ /** @internal */ final class Traverser { - /** @var callable(Node): void */ + /** @var callable(Node): ?Node */ private $callback; - /** @param callable(Node): void $callback */ + /** @param callable(Node): ?Node $callback */ public function traverse(Node $node, callable $callback): Node { $this->callback = $callback; @@ -27,9 +27,9 @@ public function traverse(Node $node, callable $callback): Node private function traverseNode(Node $node): Node { - ($this->callback)($node); - foreach ($node->getSubNodes() as $subnode) { - $this->traverseNode($subnode); + $node = ($this->callback)($node) ?? $node; + foreach ($node->getSubNodes() as &$subnode) { + $subnode = $this->traverseNode($subnode); } return $node; } diff --git a/tests/Neon/Traverser.alter.phpt b/tests/Neon/Traverser.alter.phpt new file mode 100644 index 00000000..6584b9c6 --- /dev/null +++ b/tests/Neon/Traverser.alter.phpt @@ -0,0 +1,40 @@ +parseToNode(' +a: foo(1, 2, 3) +'); + +$traverser = new Neon\Traverser; +$newNode = $traverser->traverse($node, $visitor); + +Assert::equal($node, $newNode); +Assert::notSame($node, $newNode); + +Assert::equal($node->items[0], $newNode->items[0]); +Assert::notSame($node->items[0], $newNode->items[0]); + +Assert::equal($node->items[0]->key, $newNode->items[0]->key); +Assert::notSame($node->items[0]->key, $newNode->items[0]->key); + +Assert::equal($node->items[0]->value, $newNode->items[0]->value); +Assert::notSame($node->items[0]->value, $newNode->items[0]->value); + +Assert::equal($node->items[0]->value->value, $newNode->items[0]->value->value); +Assert::notSame($node->items[0]->value->value, $newNode->items[0]->value->value); + +Assert::equal($node->items[0]->value->attributes[0], $newNode->items[0]->value->attributes[0]); +Assert::notSame($node->items[0]->value->attributes[0], $newNode->items[0]->value->attributes[0]);