From 9f1edd2c127bdce3b0db7f936ea0ceb1c5056bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20M=C3=B6nch?= Date: Thu, 16 May 2024 10:15:10 +0200 Subject: [PATCH] use generics for node value --- .php-cs-fixer.php | 1 + composer.lock | 16 +++---- psalm-baseline.xml | 73 ++++++++++++++------------------ src/Node/Node.php | 9 +++- src/Node/NodeInterface.php | 18 ++++---- src/Node/NodeTrait.php | 22 +++++++--- src/Visitor/PostOrderVisitor.php | 2 +- src/Visitor/YieldVisitor.php | 2 +- test/Unit/Node/NodeTest.php | 1 + 9 files changed, 78 insertions(+), 66 deletions(-) diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 65d2bd4..11817e8 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -30,6 +30,7 @@ 'declare_strict_types' => false, 'final_class' => false, 'void_return' => false, + 'phpdoc_to_property_type' => false, // when turned on it breaks generics phpdoc types ])); $config = PhpCsFixer\Config\Factory::fromRuleSet($ruleSet); diff --git a/composer.lock b/composer.lock index be2f241..4c532ba 100644 --- a/composer.lock +++ b/composer.lock @@ -1592,16 +1592,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.56.1", + "version": "v3.56.2", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "69c6168ae8bc96dc656c7f6c7271120a68ae5903" + "reference": "e8c12f9501f6b66caf9072404f960b6af5672b2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/69c6168ae8bc96dc656c7f6c7271120a68ae5903", - "reference": "69c6168ae8bc96dc656c7f6c7271120a68ae5903", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/e8c12f9501f6b66caf9072404f960b6af5672b2e", + "reference": "e8c12f9501f6b66caf9072404f960b6af5672b2e", "shasum": "" }, "require": { @@ -1673,7 +1673,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.56.1" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.56.2" }, "funding": [ { @@ -1681,7 +1681,7 @@ "type": "github" } ], - "time": "2024-05-10T11:31:15+00:00" + "time": "2024-05-15T14:37:10+00:00" }, { "name": "infection/abstract-testframework-adapter", @@ -6166,13 +6166,13 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, - "platform-dev": [], + "platform-dev": {}, "platform-overrides": { "php": "8.0.25" }, diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 1ceb46c..2a6614e 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,62 +1,59 @@ - + - $value + - static - static + + - mixed - static - static - static + + + + - $heights + - array - array - array + + + - $child + - $child - $child - $child - $child - $heights[] - $size + + + + + + - int - int + + - getHeight - getSize - setParent + + + getSize()]]> - \max($heights) + - - ?static - - getDepth + @@ -64,7 +61,7 @@ accept($this)]]> - $nodes + ]]> @@ -73,7 +70,7 @@ accept($this)]]> - $nodes + ]]> @@ -82,7 +79,7 @@ accept($this)]]> - $yield + ]]> @@ -91,18 +88,10 @@ - array[Node] + - - static function (Node $node) { - - leaf + - - - assertSame - - diff --git a/src/Node/Node.php b/src/Node/Node.php index e92441e..9cb4b3c 100644 --- a/src/Node/Node.php +++ b/src/Node/Node.php @@ -11,15 +11,22 @@ namespace Tree\Node; +/** + * @template TValue + * + * @template-implements NodeInterface + */ class Node implements NodeInterface { + /** @use NodeTrait */ use NodeTrait; /** + * @param null|TValue $value * @param array $children */ public function __construct( - mixed $value = null, + $value = null, array $children = [], ) { $this->setValue($value); diff --git a/src/Node/NodeInterface.php b/src/Node/NodeInterface.php index 52b9726..e8b8ad7 100644 --- a/src/Node/NodeInterface.php +++ b/src/Node/NodeInterface.php @@ -17,23 +17,27 @@ * Interface for tree nodes. * * @author Nicolò Martini + * + * @template TValue */ interface NodeInterface { /** * Set the value of the current node. + * + * @param TValue $value */ - public function setValue(mixed $value): static; + public function setValue($value): static; /** * Get the current node value. + * + * @return TValue */ - public function getValue(): mixed; + public function getValue(); /** * Add a child. - * - * @return mixed */ public function addChild(self $child): static; @@ -58,8 +62,6 @@ public function getChildren(): array; * Replace the children set with the given one. * * @param array $children - * - * @return mixed */ public function setChildren(array $children): static; @@ -71,7 +73,7 @@ public function setParent(?self $parent = null): void; /** * Return the parent node. */ - public function getParent(): ?static; + public function getParent(): ?self; /** * Retrieves all ancestors of node excluding current node. @@ -115,7 +117,7 @@ public function isLeaf(): bool; /** * Find the root of the node. */ - public function root(): static; + public function root(): self; /** * Return the distance from the current node to the root. diff --git a/src/Node/NodeTrait.php b/src/Node/NodeTrait.php index 4e6684f..3510485 100644 --- a/src/Node/NodeTrait.php +++ b/src/Node/NodeTrait.php @@ -13,9 +13,15 @@ use Tree\Visitor\Visitor; +/** + * @template TValue + */ trait NodeTrait { - private mixed $value = null; + /** + * @var TValue + */ + private $value; private ?NodeInterface $parent = null; /** @@ -23,14 +29,20 @@ trait NodeTrait */ private array $children = []; - public function setValue(mixed $value): static + /** + * @param TValue $value + */ + public function setValue($value): static { $this->value = $value; return $this; } - public function getValue(): mixed + /** + * @return TValue + */ + public function getValue() { return $this->value; } @@ -90,7 +102,7 @@ public function setParent(?NodeInterface $parent = null): void $this->parent = $parent; } - public function getParent(): ?static + public function getParent(): ?NodeInterface { return $this->parent; } @@ -153,7 +165,7 @@ public function isLeaf(): bool return [] === $this->children; } - public function root(): static + public function root(): NodeInterface { $node = $this; diff --git a/src/Visitor/PostOrderVisitor.php b/src/Visitor/PostOrderVisitor.php index 620a160..7cca5c6 100644 --- a/src/Visitor/PostOrderVisitor.php +++ b/src/Visitor/PostOrderVisitor.php @@ -18,7 +18,7 @@ class PostOrderVisitor implements Visitor /** * @return array $node */ - public function visit(NodeInterface $node): mixed + public function visit(NodeInterface $node): array { $nodes = []; diff --git a/src/Visitor/YieldVisitor.php b/src/Visitor/YieldVisitor.php index 8d84835..6510d34 100644 --- a/src/Visitor/YieldVisitor.php +++ b/src/Visitor/YieldVisitor.php @@ -18,7 +18,7 @@ class YieldVisitor implements Visitor /** * @return array */ - public function visit(NodeInterface $node): mixed + public function visit(NodeInterface $node): array { if ($node->isLeaf()) { return [$node]; diff --git a/test/Unit/Node/NodeTest.php b/test/Unit/Node/NodeTest.php index f915835..24fa8cc 100644 --- a/test/Unit/Node/NodeTest.php +++ b/test/Unit/Node/NodeTest.php @@ -69,6 +69,7 @@ public function testConstructorSetsChildren(): void public function testSetValue(): void { + /** @var Node<\stdClass|string> $node */ $node = new Node(); $node->setValue('string value');