From 98a3ce609686f54818fe1b850eb49cfcd1139231 Mon Sep 17 00:00:00 2001 From: Baptiste Langlade Date: Sat, 7 Feb 2026 11:39:07 +0100 Subject: [PATCH] add NoDiscard attributes --- psalm.xml | 3 +++ src/Edge.php | 13 +++++++++++++ src/Edge/Shape.php | 12 ++++++++++++ src/Graph.php | 14 ++++++++++++++ src/Graph/Name.php | 2 ++ src/Graph/Rankdir.php | 1 + src/Layout/DPI.php | 2 ++ src/Layout/Dot.php | 2 ++ src/Node.php | 9 +++++++++ src/Node/Name.php | 2 ++ src/Node/Shape.php | 29 +++++++++++++++++++++++++++++ tests/Graph/NameTest.php | 2 +- 12 files changed, 90 insertions(+), 1 deletion(-) diff --git a/psalm.xml b/psalm.xml index 510148d..feccc34 100644 --- a/psalm.xml +++ b/psalm.xml @@ -14,4 +14,7 @@ + + + diff --git a/src/Edge.php b/src/Edge.php index bd4ab09..b7ed0b0 100644 --- a/src/Edge.php +++ b/src/Edge.php @@ -30,6 +30,7 @@ private function __construct( /** * @psalm-pure */ + #[\NoDiscard] public static function between(Name $from, Name $to): self { /** @var Map */ @@ -38,26 +39,31 @@ public static function between(Name $from, Name $to): self return new self($from, $to, $attributes); } + #[\NoDiscard] public function from(): Name { return $this->from; } + #[\NoDiscard] public function to(): Name { return $this->to; } + #[\NoDiscard] public function asBidirectional(): self { return $this->with('dir', 'both'); } + #[\NoDiscard] public function withoutDirection(): self { return $this->with('dir', 'none'); } + #[\NoDiscard] public function shaped( Shape $shape, ?Shape $shape2 = null, @@ -85,6 +91,7 @@ public function shaped( /** * @param non-empty-string $label */ + #[\NoDiscard] public function displayAs(string $label): self { return $this->with( @@ -93,11 +100,13 @@ public function displayAs(string $label): self ); } + #[\NoDiscard] public function useColor(RGBA $color): self { return $this->with('color', $color->toString()); } + #[\NoDiscard] public function target(Url $url): self { return $this->with( @@ -106,16 +115,19 @@ public function target(Url $url): self ); } + #[\NoDiscard] public function dotted(): self { return $this->with('style', 'dotted'); } + #[\NoDiscard] public function bold(): self { return $this->with('style', 'bold'); } + #[\NoDiscard] public function filled(): self { return $this->with('style', 'filled'); @@ -126,6 +138,7 @@ public function filled(): self * * @return Map */ + #[\NoDiscard] public function attributes(): Map { return $this->attributes; diff --git a/src/Edge/Shape.php b/src/Edge/Shape.php index 15cb125..ec194b1 100644 --- a/src/Edge/Shape.php +++ b/src/Edge/Shape.php @@ -23,6 +23,7 @@ enum Shape /** * @psalm-pure */ + #[\NoDiscard] public static function box(): self { return self::box; @@ -31,6 +32,7 @@ public static function box(): self /** * @psalm-pure */ + #[\NoDiscard] public static function crow(): self { return self::crow; @@ -39,6 +41,7 @@ public static function crow(): self /** * @psalm-pure */ + #[\NoDiscard] public static function curve(): self { return self::curve; @@ -47,6 +50,7 @@ public static function curve(): self /** * @psalm-pure */ + #[\NoDiscard] public static function icurve(): self { return self::icurve; @@ -55,6 +59,7 @@ public static function icurve(): self /** * @psalm-pure */ + #[\NoDiscard] public static function diamond(): self { return self::diamond; @@ -63,6 +68,7 @@ public static function diamond(): self /** * @psalm-pure */ + #[\NoDiscard] public static function dot(): self { return self::dot; @@ -71,6 +77,7 @@ public static function dot(): self /** * @psalm-pure */ + #[\NoDiscard] public static function inv(): self { return self::inv; @@ -79,6 +86,7 @@ public static function inv(): self /** * @psalm-pure */ + #[\NoDiscard] public static function none(): self { return self::none; @@ -87,6 +95,7 @@ public static function none(): self /** * @psalm-pure */ + #[\NoDiscard] public static function normal(): self { return self::normal; @@ -95,6 +104,7 @@ public static function normal(): self /** * @psalm-pure */ + #[\NoDiscard] public static function tee(): self { return self::tee; @@ -103,11 +113,13 @@ public static function tee(): self /** * @psalm-pure */ + #[\NoDiscard] public static function vee(): self { return self::vee; } + #[\NoDiscard] public function toString(): string { return $this->name; diff --git a/src/Graph.php b/src/Graph.php index 984e3b0..4dbcfb2 100644 --- a/src/Graph.php +++ b/src/Graph.php @@ -44,6 +44,7 @@ private function __construct( * * @return self<'directed'> */ + #[\NoDiscard] public static function directed(string $name = 'G', ?Rankdir $rankdir = null): self { /** @var Set */ @@ -67,6 +68,7 @@ public static function directed(string $name = 'G', ?Rankdir $rankdir = null): s * * @return self<'undirected'> */ + #[\NoDiscard] public static function undirected(string $name = 'G', ?Rankdir $rankdir = null): self { /** @var Set */ @@ -83,11 +85,13 @@ public static function undirected(string $name = 'G', ?Rankdir $rankdir = null): return new self('undirected', Name::of($name), $nodes, $clusters, $attributes); } + #[\NoDiscard] public function isDirected(): bool { return $this->directed === 'directed'; } + #[\NoDiscard] public function name(): Name { return $this->name; @@ -98,6 +102,7 @@ public function name(): Name * * @return self */ + #[\NoDiscard] public function cluster(self $cluster): self { return new self( @@ -112,6 +117,7 @@ public function cluster(self $cluster): self /** * @return Set> */ + #[\NoDiscard] public function clusters(): Set { return $this->clusters; @@ -120,6 +126,7 @@ public function clusters(): Set /** * @return self */ + #[\NoDiscard] public function add(Node $node): self { return new self( @@ -136,6 +143,7 @@ public function add(Node $node): self * * @return Set */ + #[\NoDiscard] public function roots(): Set { $targeted = $this @@ -154,6 +162,7 @@ public function roots(): Set * * @return Set */ + #[\NoDiscard] public function nodes(): Set { return $this->nodes; @@ -165,6 +174,7 @@ public function nodes(): Set * * @return self */ + #[\NoDiscard] public function displayAs(string $label): self { return new self( @@ -182,6 +192,7 @@ public function displayAs(string $label): self /** * @return self */ + #[\NoDiscard] public function fillWithColor(RGBA $color): self { return new self( @@ -198,6 +209,7 @@ public function fillWithColor(RGBA $color): self /** * @return self */ + #[\NoDiscard] public function colorizeBorderWith(RGBA $color): self { return new self( @@ -212,6 +224,7 @@ public function colorizeBorderWith(RGBA $color): self /** * @return self */ + #[\NoDiscard] public function target(Url $url): self { return new self( @@ -231,6 +244,7 @@ public function target(Url $url): self * * @return Map */ + #[\NoDiscard] public function attributes(): Map { return $this->attributes; diff --git a/src/Graph/Name.php b/src/Graph/Name.php index 7d20a86..a6c1b03 100644 --- a/src/Graph/Name.php +++ b/src/Graph/Name.php @@ -26,6 +26,7 @@ private function __construct( * * @throws DomainException */ + #[\NoDiscard] public static function of(string $name): self { if (!Str::of($name)->matches('~[a-zA-Z0-9_]+~')) { @@ -38,6 +39,7 @@ public static function of(string $name): self /** * @return non-empty-string */ + #[\NoDiscard] public function toString(): string { return $this->value; diff --git a/src/Graph/Rankdir.php b/src/Graph/Rankdir.php index 09f46db..1b13191 100644 --- a/src/Graph/Rankdir.php +++ b/src/Graph/Rankdir.php @@ -11,6 +11,7 @@ enum Rankdir case leftToRight; case topToBottom; + #[\NoDiscard] public function toString(): string { return match ($this) { diff --git a/src/Layout/DPI.php b/src/Layout/DPI.php index bbc076d..f6a3ccf 100644 --- a/src/Layout/DPI.php +++ b/src/Layout/DPI.php @@ -21,6 +21,7 @@ private function __construct( * * @param int<1, max> $value */ + #[\NoDiscard] public static function of(int $value): self { return new self($value); @@ -29,6 +30,7 @@ public static function of(int $value): self /** * @return int<1, max> */ + #[\NoDiscard] public function toInt(): int { return $this->value; diff --git a/src/Layout/Dot.php b/src/Layout/Dot.php index 095d892..ceeb7fe 100644 --- a/src/Layout/Dot.php +++ b/src/Layout/Dot.php @@ -28,6 +28,7 @@ private function __construct( ) { } + #[\NoDiscard] public function __invoke(Graph $graph): Content { $type = $graph->isDirected() ? 'digraph' : 'graph'; @@ -47,6 +48,7 @@ public function __invoke(Graph $graph): Content /** * @psalm-pure */ + #[\NoDiscard] public static function of(?DPI $dpi = null): self { return new self(Maybe::of($dpi)); diff --git a/src/Node.php b/src/Node.php index 81a7b86..150ac27 100644 --- a/src/Node.php +++ b/src/Node.php @@ -36,6 +36,7 @@ private function __construct( /** * @psalm-pure */ + #[\NoDiscard] public static function of(Name $name): self { /** @var Set */ @@ -53,11 +54,13 @@ public static function of(Name $name): self * * @param non-empty-string $name */ + #[\NoDiscard] public static function named(string $name): self { return self::of(Name::of($name)); } + #[\NoDiscard] public function name(): Name { return $this->name; @@ -66,6 +69,7 @@ public function name(): Name /** * @return Set */ + #[\NoDiscard] public function edges(): Set { return $this->edges; @@ -74,6 +78,7 @@ public function edges(): Set /** * @param (pure-callable(Edge): Edge)|null $map */ + #[\NoDiscard] public function linkedTo(Name $node, ?callable $map = null): self { $map ??= static fn(Edge $edge): Edge => $edge; @@ -87,6 +92,7 @@ public function linkedTo(Name $node, ?callable $map = null): self ); } + #[\NoDiscard] public function target(Url $url): self { return new self( @@ -103,6 +109,7 @@ public function target(Url $url): self /** * @param non-empty-string $label */ + #[\NoDiscard] public function displayAs(string $label): self { return new self( @@ -116,6 +123,7 @@ public function displayAs(string $label): self ); } + #[\NoDiscard] public function shaped(Shape $shape): self { return new self( @@ -131,6 +139,7 @@ public function shaped(Shape $shape): self * * @return Map */ + #[\NoDiscard] public function attributes(): Map { return $this diff --git a/src/Node/Name.php b/src/Node/Name.php index beb636c..49d8801 100644 --- a/src/Node/Name.php +++ b/src/Node/Name.php @@ -24,6 +24,7 @@ private function __construct( * * @param non-empty-string $name */ + #[\NoDiscard] public static function of(string $name): self { $str = Str::of($name); @@ -43,6 +44,7 @@ public static function of(string $name): self /** * @return non-empty-string */ + #[\NoDiscard] public function toString(): string { return $this->value; diff --git a/src/Node/Shape.php b/src/Node/Shape.php index 6ee4ea8..64f8ada 100644 --- a/src/Node/Shape.php +++ b/src/Node/Shape.php @@ -22,6 +22,7 @@ private function __construct( /** * @psalm-pure */ + #[\NoDiscard] public static function box(): self { return self::shape('box'); @@ -33,6 +34,7 @@ public static function box(): self * @param ?int<3, max> $sides * @param ?int<1, max> $peripheries */ + #[\NoDiscard] public static function polygon( ?int $sides = null, ?int $peripheries = null, @@ -70,6 +72,7 @@ public static function polygon( /** * @psalm-pure */ + #[\NoDiscard] public static function ellipse(float $width = .75, float $height = .5): self { return new self(Map::of( @@ -82,6 +85,7 @@ public static function ellipse(float $width = .75, float $height = .5): self /** * @psalm-pure */ + #[\NoDiscard] public static function circle(): self { return self::shape('circle'); @@ -90,6 +94,7 @@ public static function circle(): self /** * @psalm-pure */ + #[\NoDiscard] public static function point(): self { return self::shape('point'); @@ -98,6 +103,7 @@ public static function point(): self /** * @psalm-pure */ + #[\NoDiscard] public static function egg(): self { return self::shape('egg'); @@ -106,6 +112,7 @@ public static function egg(): self /** * @psalm-pure */ + #[\NoDiscard] public static function triangle(): self { return self::shape('triangle'); @@ -114,6 +121,7 @@ public static function triangle(): self /** * @psalm-pure */ + #[\NoDiscard] public static function plaintext(): self { return self::shape('plaintext'); @@ -122,6 +130,7 @@ public static function plaintext(): self /** * @psalm-pure */ + #[\NoDiscard] public static function diamond(): self { return self::shape('diamond'); @@ -130,6 +139,7 @@ public static function diamond(): self /** * @psalm-pure */ + #[\NoDiscard] public static function trapezium(): self { return self::shape('trapezium'); @@ -138,6 +148,7 @@ public static function trapezium(): self /** * @psalm-pure */ + #[\NoDiscard] public static function parallelogram(): self { return self::shape('parallelogram'); @@ -146,6 +157,7 @@ public static function parallelogram(): self /** * @psalm-pure */ + #[\NoDiscard] public static function house(): self { return self::shape('house'); @@ -154,6 +166,7 @@ public static function house(): self /** * @psalm-pure */ + #[\NoDiscard] public static function hexagon(): self { return self::shape('hexagon'); @@ -162,6 +175,7 @@ public static function hexagon(): self /** * @psalm-pure */ + #[\NoDiscard] public static function octagon(): self { return self::shape('octagon'); @@ -170,6 +184,7 @@ public static function octagon(): self /** * @psalm-pure */ + #[\NoDiscard] public static function doublecircle(): self { return self::shape('doublecircle'); @@ -178,6 +193,7 @@ public static function doublecircle(): self /** * @psalm-pure */ + #[\NoDiscard] public static function doubleoctagon(): self { return self::shape('doubleoctagon'); @@ -186,6 +202,7 @@ public static function doubleoctagon(): self /** * @psalm-pure */ + #[\NoDiscard] public static function tripleoctagon(): self { return self::shape('tripleoctagon'); @@ -194,6 +211,7 @@ public static function tripleoctagon(): self /** * @psalm-pure */ + #[\NoDiscard] public static function invtriangle(): self { return self::shape('invtriangle'); @@ -202,6 +220,7 @@ public static function invtriangle(): self /** * @psalm-pure */ + #[\NoDiscard] public static function invtrapezium(): self { return self::shape('invtrapezium'); @@ -210,6 +229,7 @@ public static function invtrapezium(): self /** * @psalm-pure */ + #[\NoDiscard] public static function invhouse(): self { return self::shape('invhouse'); @@ -218,6 +238,7 @@ public static function invhouse(): self /** * @psalm-pure */ + #[\NoDiscard] public static function Mdiamond(): self { return self::shape('Mdiamond'); @@ -226,6 +247,7 @@ public static function Mdiamond(): self /** * @psalm-pure */ + #[\NoDiscard] public static function Msquare(): self { return self::shape('Msquare'); @@ -234,6 +256,7 @@ public static function Msquare(): self /** * @psalm-pure */ + #[\NoDiscard] public static function Mcircle(): self { return self::shape('Mcircle'); @@ -242,6 +265,7 @@ public static function Mcircle(): self /** * @psalm-pure */ + #[\NoDiscard] public static function none(): self { return self::shape('none'); @@ -250,6 +274,7 @@ public static function none(): self /** * @psalm-pure */ + #[\NoDiscard] public static function record(): self { return self::shape('record'); @@ -258,11 +283,13 @@ public static function record(): self /** * @psalm-pure */ + #[\NoDiscard] public static function Mrecord(): self { return self::shape('Mrecord'); } + #[\NoDiscard] public function withColor(RGBA $color): self { return new self( @@ -270,6 +297,7 @@ public function withColor(RGBA $color): self ); } + #[\NoDiscard] public function fillWithColor(RGBA $color): self { return new self( @@ -284,6 +312,7 @@ public function fillWithColor(RGBA $color): self * * @return Map */ + #[\NoDiscard] public function attributes(): Map { return $this->attributes; diff --git a/tests/Graph/NameTest.php b/tests/Graph/NameTest.php index d8b2aa5..5af300e 100644 --- a/tests/Graph/NameTest.php +++ b/tests/Graph/NameTest.php @@ -39,7 +39,7 @@ public function testThrowWhenContainingInvalidCharacters(): BlackBox\Proof ->prove(function(string $string): void { $this->expectException(DomainException::class); - Name::of($string); + $_ = Name::of($string); }); } }