diff --git a/psalm.xml b/psalm.xml index 1bcd67b..ae0443a 100644 --- a/psalm.xml +++ b/psalm.xml @@ -7,6 +7,7 @@ xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" > + diff --git a/src/Combinator.php b/src/Combinator.php index bb1725b..56ccb78 100644 --- a/src/Combinator.php +++ b/src/Combinator.php @@ -6,14 +6,16 @@ use Closure; use InvalidArgumentException; +use loophp\combinator\Contract\Combinator as CombinatorInterface; -use function get_called_class; use function is_callable; /** * Class Combinator. + * + * @psalm-immutable */ -abstract class Combinator implements \loophp\combinator\Contract\Combinator +abstract class Combinator implements CombinatorInterface { /** * @return Closure @@ -26,6 +28,6 @@ public static function with(): Closure return Closure::fromCallable($possibleCallable); } - throw new InvalidArgumentException('Implement on() method in ' . get_called_class() . '.'); + throw new InvalidArgumentException('Implement on() method in ' . static::class . '.'); } } diff --git a/src/Combinator/A.php b/src/Combinator/A.php index b4dea88..565fc25 100644 --- a/src/Combinator/A.php +++ b/src/Combinator/A.php @@ -12,15 +12,21 @@ * * @psalm-template AType * @psalm-template BType + * + * @psalm-immutable */ final class A extends Combinator { /** + * @psalm-var callable(AType): BType + * * @var callable */ private $f; /** + * @psalm-var AType + * * @var mixed */ private $x; @@ -29,7 +35,7 @@ final class A extends Combinator * A constructor. * * @psalm-param callable(AType): BType $f - * @psalm-param BType $x + * @psalm-param AType $x * * @param callable $f * @param mixed $x @@ -49,16 +55,19 @@ public function __invoke() } /** - * @psalm-param callable(AType): BType $f + * @template NewAType + * @template NewBType * - * @param callable $f + * @param callable(NewAType): NewBType $f * - * @return Closure + * @return Closure(NewAType): NewBType */ public static function on(callable $f): Closure { - return static function ($x) use ($f) { - return (new self($f, $x))(); - }; + return + /** @param NewAType $x */ + static function ($x) use ($f) { + return (new self($f, $x))(); + }; } } diff --git a/src/Combinator/B.php b/src/Combinator/B.php index 6441e45..573d72c 100644 --- a/src/Combinator/B.php +++ b/src/Combinator/B.php @@ -13,20 +13,28 @@ * @psalm-template AType * @psalm-template BType * @psalm-template CType + * + * @psalm-immutable */ final class B extends Combinator { /** + * @psalm-var callable(AType): BType + * * @var callable */ private $f; /** + * @psalm-var callable(CType): AType + * * @var callable */ private $g; /** + * @psalm-var CType + * * @var mixed */ private $x; @@ -58,16 +66,23 @@ public function __invoke() } /** - * @param callable $a + * @template AParam + * @template AReturn + * + * @param callable(AParam): AReturn $f * - * @return Closure + * @return Closure(callable(mixed): AParam): Closure(mixed): AReturn */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function (callable $b) use ($a): Closure { - return static function ($c) use ($a, $b) { - return (new self($a, $b, $c))(); + return + /** @param callable(mixed): AParam $g */ + static function (callable $g) use ($f): Closure { + return + /** @param mixed $x */ + static function ($x) use ($f, $g) { + return (new self($f, $g, $x))(); + }; }; - }; } } diff --git a/src/Combinator/C.php b/src/Combinator/C.php index f2ade47..3235a4d 100644 --- a/src/Combinator/C.php +++ b/src/Combinator/C.php @@ -13,20 +13,28 @@ * @psalm-template AType * @psalm-template BType * @psalm-template CType + * + * @psalm-immutable */ final class C extends Combinator { /** + * @psalm-var callable(AType): callable(BType): CType + * * @var callable */ private $f; /** + * @psalm-var BType + * * @var mixed */ private $x; /** + * @psalm-var AType + * * @var mixed */ private $y; @@ -51,6 +59,8 @@ public function __construct(callable $f, $x, $y) /** * @psalm-return CType + * + * @return mixed */ public function __invoke() { @@ -58,16 +68,26 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * @template NewCType + * + * @psalm-param callable(NewAType): callable(NewBType): NewCType $f + * + * @param callable(NewAType): NewCType $f * - * @return Closure + * @return Closure(NewBType): Closure(NewAType): NewCType */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function ($b) use ($a): Closure { - return static function ($c) use ($a, $b) { - return (new self($a, $b, $c))(); + return + /** @param NewBType $x */ + static function ($x) use ($f): Closure { + return + /** @param NewAType $y */ + static function ($y) use ($f, $x) { + return (new self($f, $x, $y))(); + }; }; - }; } } diff --git a/src/Combinator/D.php b/src/Combinator/D.php index 2797e09..46775ac 100644 --- a/src/Combinator/D.php +++ b/src/Combinator/D.php @@ -14,48 +14,58 @@ * @psalm-template BType * @psalm-template CType * @psalm-template DType + * + * @psalm-immutable */ final class D extends Combinator { /** + * @psalm-var callable(AType): callable(CType): DType + * * @var callable */ - private $f; + private $a; /** - * @var callable + * @psalm-var AType + * + * @var mixed */ - private $g; + private $b; /** - * @var mixed + * @psalm-var callable(BType): CType + * + * @var callable */ - private $x; + private $c; /** + * @psalm-var BType + * * @var mixed */ - private $y; + private $d; /** * D constructor. * - * @psalm-param callable(AType): callable(CType): DType $f - * @psalm-param AType $x - * @psalm-param callable(BType): CType $g - * @psalm-param BType $y + * @psalm-param callable(AType): callable(CType): DType $a + * @psalm-param AType $b + * @psalm-param callable(BType): CType $c + * @psalm-param BType $d * - * @param callable $f - * @param callable $g - * @param mixed $x - * @param mixed $y + * @param callable $a + * @param mixed $b + * @param callable $c + * @param mixed $d */ - public function __construct(callable $f, $x, callable $g, $y) + public function __construct(callable $a, $b, callable $c, $d) { - $this->f = $f; - $this->x = $x; - $this->g = $g; - $this->y = $y; + $this->a = $a; + $this->b = $b; + $this->c = $c; + $this->d = $d; } /** @@ -63,22 +73,35 @@ public function __construct(callable $f, $x, callable $g, $y) */ public function __invoke() { - return (($this->f)($this->x))(($this->g)($this->y)); + return (($this->a)($this->b))(($this->c)($this->d)); } /** - * @param callable $a + * @template NewAType + * @template NewBType + * @template NewCType + * @template NewDType + * + * @psalm-param callable(NewAType): callable(NewCType): NewDType $f + * + * @param callable(NewCType): NewDType $f * - * @return Closure + * @return Closure(NewAType): Closure(Closure(NewBType): NewCType): Closure(NewBType): NewDType */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function ($b) use ($a): Closure { - return static function (callable $c) use ($a, $b): Closure { - return static function ($d) use ($a, $b, $c) { - return (new self($a, $b, $c, $d))(); - }; + return + /** @param NewAType $x */ + static function ($x) use ($f): Closure { + return + /** @param callable(NewBType): NewCType $g */ + static function (callable $g) use ($f, $x): Closure { + return + /** @param NewBType $y */ + static function ($y) use ($f, $x, $g) { + return (new self($f, $x, $g, $y))(); + }; + }; }; - }; } } diff --git a/src/Combinator/E.php b/src/Combinator/E.php index db8d405..b6647d1 100644 --- a/src/Combinator/E.php +++ b/src/Combinator/E.php @@ -15,30 +15,44 @@ * @psalm-template CType * @psalm-template DType * @psalm-template EType + * + * @psalm-immutable + * + * phpcs:disable Generic.Files.LineLength.TooLong */ final class E extends Combinator { /** + * @psalm-var callable(AType): callable(DType): EType + * * @var callable */ private $f; /** + * @psalm-var callable(BType): callable(CType): DType + * * @var callable */ private $g; /** + * @psalm-var AType + * * @var mixed */ private $x; /** + * @psalm-var BType + * * @var mixed */ private $y; /** + * @psalm-var CType + * * @var mixed */ private $z; @@ -72,26 +86,42 @@ public function __construct(callable $f, $x, callable $g, $y, $z) */ public function __invoke() { - // Demander à Danny :-) - // const E = a => b => c => d => e => a(b)(c(d)(e)) return (($this->f)($this->x))((($this->g)($this->y))($this->z)); } /** - * @param callable $a + * @template NewAType + * @template NewBType + * @template NewCType + * @template NewDType + * @template NewEType + * + * @psalm-param callable(NewAType): callable(NewDType): NewEType $f + * + * @param callable $f + * + * @psalm-return Closure(NewAType): Closure(callable(NewBType): callable(NewCType): NewDType): Closure(NewBType): Closure(NewCType) * * @return Closure */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function ($b) use ($a): Closure { - return static function (callable $c) use ($a, $b): Closure { - return static function ($d) use ($a, $b, $c): Closure { - return static function ($e) use ($a, $b, $c, $d) { - return (new self($a, $b, $c, $d, $e))(); + return + /** @param NewAType $x */ + static function ($x) use ($f): Closure { + return + /** @psalm-param callable(NewBType): callable(NewCType): NewDType $g */ + static function (callable $g) use ($f, $x): Closure { + return + /** @param NewBType $y */ + static function ($y) use ($f, $x, $g): Closure { + return + /** @param NewCType $z */ + static function ($z) use ($f, $x, $g, $y) { + return (new self($f, $x, $g, $y, $z))(); + }; + }; }; - }; }; - }; } } diff --git a/src/Combinator/F.php b/src/Combinator/F.php index c849bdc..ac24701 100644 --- a/src/Combinator/F.php +++ b/src/Combinator/F.php @@ -13,20 +13,28 @@ * @psalm-template AType * @psalm-template BType * @psalm-template CType + * + * @psalm-immutable */ final class F extends Combinator { /** + * @psalm-var callable(BType): callable(AType): CType + * * @var callable */ private $f; /** + * @psalm-var AType + * * @var mixed */ private $x; /** + * @psalm-var BType + * * @var mixed */ private $y; @@ -58,16 +66,26 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * @template NewCType + * + * @psalm-param NewAType $a + * + * @param mixed $a * - * @return Closure + * @return Closure(NewBType): Closure(callable(NewBType): callable(NewAType): NewCType): NewCType */ public static function on($a): Closure { - return static function ($b) use ($a): Closure { - return static function (callable $c) use ($a, $b) { - return (new self($a, $b, $c))(); + return + /** @param NewBType $b */ + static function ($b) use ($a): Closure { + return + /** @psalm-param callable(NewBType): callable(NewAType): NewCType $c */ + static function (callable $c) use ($a, $b) { + return (new self($a, $b, $c))(); + }; }; - }; } } diff --git a/src/Combinator/G.php b/src/Combinator/G.php index fad7e09..263d468 100644 --- a/src/Combinator/G.php +++ b/src/Combinator/G.php @@ -14,25 +14,35 @@ * @psalm-template BType * @psalm-template CType * @psalm-template DType + * + * @psalm-immutable */ final class G extends Combinator { /** + * @psalm-var callable(AType): callable(BType): CType + * * @var callable */ private $f; /** + * @psalm-var callable(DType): BType + * * @var callable */ private $g; /** + * @psalm-var DType + * * @var mixed */ private $x; /** + * @psalm-var AType + * * @var mixed */ private $y; @@ -67,18 +77,31 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * @template NewCType + * @template NewDType + * + * @psalm-param callable(NewAType): callable(NewBType): NewCType $f + * + * @param callable $f * - * @return Closure + * @return Closure(callable(NewDType): NewBType): Closure(NewDType): Closure(NewAType): NewCType */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function (callable $b) use ($a): Closure { - return static function ($c) use ($a, $b): Closure { - return static function ($d) use ($a, $b, $c) { - return (new self($a, $b, $c, $d))(); - }; + return + /** @param callable(NewDType): NewBType $g */ + static function (callable $g) use ($f): Closure { + return + /** @param NewDType $x */ + static function ($x) use ($f, $g): Closure { + return + /** @param NewAType $y */ + static function ($y) use ($f, $g, $x) { + return (new self($f, $g, $x, $y))(); + }; + }; }; - }; } } diff --git a/src/Combinator/H.php b/src/Combinator/H.php index 3fb80ff..7139967 100644 --- a/src/Combinator/H.php +++ b/src/Combinator/H.php @@ -13,20 +13,28 @@ * @psalm-template AType * @psalm-template BType * @psalm-template CType + * + * @psalm-immutable */ final class H extends Combinator { /** + * @psalm-var callable(AType): callable(BType): callable(AType): CType + * * @var callable */ private $f; /** + * @psalm-var AType + * * @var mixed */ private $x; /** + * @psalm-var BType + * * @var mixed */ private $y; @@ -58,16 +66,26 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * @template NewCType + * + * @psalm-param callable(NewAType): callable(NewBType): callable(NewAType): NewCType $f + * + * @param callable $f * - * @return Closure + * @return Closure(NewAType): Closure(NewBType): NewCType */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function ($b) use ($a): Closure { - return static function ($c) use ($a, $b) { - return (new self($a, $b, $c))(); + return + /** @param NewAType $x */ + static function ($x) use ($f): Closure { + return + /** @param NewBType $y */ + static function ($y) use ($f, $x) { + return (new self($f, $x, $y))(); + }; }; - }; } } diff --git a/src/Combinator/I.php b/src/Combinator/I.php index dc9ad9b..7bb99ca 100644 --- a/src/Combinator/I.php +++ b/src/Combinator/I.php @@ -10,10 +10,14 @@ * Class I. * * @psalm-template AType + * + * @psalm-immutable */ final class I extends Combinator { /** + * @psalm-var AType + * * @var mixed */ private $x; @@ -39,12 +43,16 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * + * @psalm-param NewAType $x + * + * @param mixed $x * - * @return mixed + * @return NewAType */ - public static function on($a) + public static function on($x) { - return (new self($a))(); + return (new self($x))(); } } diff --git a/src/Combinator/J.php b/src/Combinator/J.php index 3586a4c..66368e3 100644 --- a/src/Combinator/J.php +++ b/src/Combinator/J.php @@ -12,25 +12,35 @@ * * @psalm-template AType * @psalm-template BType + * + * @psalm-immutable */ final class J extends Combinator { /** + * @psalm-var callable(AType): callable(BType): BType + * * @var callable */ private $f; /** + * @psalm-var AType + * * @var mixed */ private $x; /** + * @psalm-var BType + * * @var mixed */ private $y; /** + * @psalm-var AType + * * @var mixed */ private $z; @@ -65,18 +75,31 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * + * @psalm-param callable(NewAType): callable(NewBType): NewBType $f + * + * @param callable $f + * + * @psalm-return Closure(NewAType): Closure(NewBType): Closure(NewAType): NewBType * - * @return Closure + * @return NewBType */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function ($b) use ($a): Closure { - return static function ($c) use ($a, $b): Closure { - return static function ($d) use ($a, $b, $c) { - return (new self($a, $b, $c, $d))(); - }; + return + /** @param NewAType $x */ + static function ($x) use ($f): Closure { + return + /** @param NewBType $y */ + static function ($y) use ($f, $x): Closure { + return + /** @param NewAType $z */ + static function ($z) use ($f, $x, $y) { + return (new self($f, $x, $y, $z))(); + }; + }; }; - }; } } diff --git a/src/Combinator/K.php b/src/Combinator/K.php index d239fbb..cdcbd40 100644 --- a/src/Combinator/K.php +++ b/src/Combinator/K.php @@ -12,15 +12,21 @@ * * @psalm-template AType * @psalm-template BType + * + * @psalm-immutable */ final class K extends Combinator { /** + * @psalm-var AType + * * @var mixed */ private $x; /** + * @psalm-var BType + * * @var mixed */ private $y; @@ -41,7 +47,9 @@ public function __construct($x, $y) } /** - * @psalm-return BType + * @psalm-return AType + * + * @return mixed */ public function __invoke() { @@ -49,14 +57,21 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * + * @psalm-param NewAType $x + * + * @param mixed $x * - * @return Closure + * @return Closure(NewBType): NewAType */ - public static function on($a): Closure + public static function on($x): Closure { - return static function ($b) use ($a) { - return (new self($a, $b))(); - }; + return + /** @param NewBType $y */ + static function ($y) use ($x) { + return (new self($x, $y))(); + }; } } diff --git a/src/Combinator/Ki.php b/src/Combinator/Ki.php index 649a1d8..d506cf2 100644 --- a/src/Combinator/Ki.php +++ b/src/Combinator/Ki.php @@ -10,17 +10,23 @@ /** * Class Ki. * - * @psalm-template XType - * @psalm-template YType + * @psalm-template AType + * @psalm-template BType + * + * @psalm-immutable */ final class Ki extends Combinator { /** + * @psalm-var AType + * * @var mixed */ private $x; /** + * @psalm-var BType + * * @var mixed */ private $y; @@ -28,8 +34,8 @@ final class Ki extends Combinator /** * Ki constructor. * - * @psalm-param XType $x - * @psalm-param YType $y + * @psalm-param AType $x + * @psalm-param BType $y * * @param mixed $x * @param mixed $y @@ -41,7 +47,7 @@ public function __construct($x, $y) } /** - * @psalm-return YType + * @psalm-return BType */ public function __invoke() { @@ -49,14 +55,21 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * + * @psalm-param NewAType $x + * + * @param mixed $x * - * @return Closure + * @return Closure(NewBType): NewBType */ - public static function on($a): Closure + public static function on($x): Closure { - return static function ($b) use ($a) { - return (new self($a, $b))(); - }; + return + /** @param NewBType $y */ + static function ($y) use ($x) { + return (new self($x, $y))(); + }; } } diff --git a/src/Combinator/L.php b/src/Combinator/L.php index 4ea7d74..853941e 100644 --- a/src/Combinator/L.php +++ b/src/Combinator/L.php @@ -10,7 +10,7 @@ /** * Class L. * - * @psalm-template ResultType + * @psalm-immutable */ final class L extends Combinator { @@ -37,8 +37,6 @@ public function __construct(callable $f, callable $g) } /** - * @psalm-return ResultType - * * @return mixed */ public function __invoke() @@ -47,6 +45,8 @@ public function __invoke() } /** + * @psalm-suppress MissingClosureReturnType + * * @param callable $a * * @return Closure diff --git a/src/Combinator/M.php b/src/Combinator/M.php index a596e3f..87b8225 100644 --- a/src/Combinator/M.php +++ b/src/Combinator/M.php @@ -4,13 +4,12 @@ namespace loophp\combinator\Combinator; -use Closure; use loophp\combinator\Combinator; /** * Class M. * - * @psalm-template ResultType + * @psalm-immutable */ final class M extends Combinator { @@ -32,7 +31,7 @@ public function __construct(callable $f) } /** - * @psalm-return ResultType + * @return mixed */ public function __invoke() { @@ -42,7 +41,7 @@ public function __invoke() /** * @param callable $a * - * @return Closure + * @return mixed */ public static function on(callable $a) { diff --git a/src/Combinator/O.php b/src/Combinator/O.php index bdd6690..f84c9fa 100644 --- a/src/Combinator/O.php +++ b/src/Combinator/O.php @@ -12,15 +12,21 @@ * * @psalm-template AType * @psalm-template BType + * + * @psalm-immutable */ final class O extends Combinator { /** + * @psalm-var callable(callable(AType): BType): AType + * * @var callable */ private $f; /** + * @psalm-var callable(AType): BType + * * @var callable */ private $g; @@ -28,6 +34,9 @@ final class O extends Combinator /** * O constructor. * + * @psalm-param callable(callable(AType): BType): AType $f + * @psalm-param callable(AType): BType $g + * * @param callable(callable(AType): BType): AType $f * @param callable(AType): BType $g */ @@ -46,14 +55,23 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * + * @psalm-param callable(callable(NewAType): NewBType): NewAType $f + * + * @param callable $f + * + * @psalm-return Closure(callable(NewAType): NewBType): NewBType * * @return Closure */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function (callable $b) use ($a) { - return (new self($a, $b))(); - }; + return + /** @param callable(NewAType): NewBType $g */ + static function (callable $g) use ($f) { + return (new self($f, $g))(); + }; } } diff --git a/src/Combinator/Omega.php b/src/Combinator/Omega.php index 9d0aaea..ef4e6ce 100644 --- a/src/Combinator/Omega.php +++ b/src/Combinator/Omega.php @@ -10,7 +10,7 @@ /** * Class Omega. * - * @psalm-template ResultType + * @psalm-immutable */ final class Omega extends Combinator { @@ -22,8 +22,6 @@ final class Omega extends Combinator /** * Omega constructor. * - * @psalm-param callable $f - * * @param callable $f */ public function __construct(callable $f) @@ -32,7 +30,11 @@ public function __construct(callable $f) } /** - * @psalm-return ResultType + * @psalm-return mixed + * + * @return mixed + * + * @psalm-suppress MixedFunctionCall */ public function __invoke() { @@ -40,12 +42,12 @@ public function __invoke() } /** - * @param callable $a + * @param callable $f * - * @return Closure + * @return mixed */ - public static function on(callable $a) + public static function on(callable $f) { - return (new self($a))(); + return (new self($f))(); } } diff --git a/src/Combinator/Phoenix.php b/src/Combinator/Phoenix.php index de78b59..defc451 100644 --- a/src/Combinator/Phoenix.php +++ b/src/Combinator/Phoenix.php @@ -14,25 +14,37 @@ * @psalm-template BType * @psalm-template CType * @psalm-template DType + * + * @psalm-immutable + * + * phpcs:disable Generic.Files.LineLength.TooLong */ final class Phoenix extends Combinator { /** + * @psalm-var callable(AType): callable(BType): CType + * * @var callable */ private $f; /** + * @psalm-var callable(DType): AType + * * @var callable */ private $g; /** + * @psalm-var callable(DType): BType + * * @var callable */ private $h; /** + * @psalm-var DType + * * @var mixed */ private $x; @@ -67,18 +79,33 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * @template NewCType + * @template NewDType + * + * @psalm-param callable(NewAType): callable(NewBType): NewCType $f + * + * @param callable $f + * + * @psalm-return Closure(callable(NewDType): NewAType): Closure(callable(NewDType): NewBType): Closure(NewDType): NewCType * * @return Closure */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function (callable $b) use ($a): Closure { - return static function (callable $c) use ($a, $b): Closure { - return static function ($d) use ($a, $b, $c) { - return (new self($a, $b, $c, $d))(); - }; + return + /** @psalm-param callable(NewDType): NewAType $g */ + static function (callable $g) use ($f): Closure { + return + /** @psalm-param callable(NewDType): NewBType $h */ + static function (callable $h) use ($f, $g): Closure { + return + /** @psalm-param NewDType $x */ + static function ($x) use ($f, $g, $h) { + return (new self($f, $g, $h, $x))(); + }; + }; }; - }; } } diff --git a/src/Combinator/Psi.php b/src/Combinator/Psi.php index 05e0894..82d905f 100644 --- a/src/Combinator/Psi.php +++ b/src/Combinator/Psi.php @@ -13,25 +13,35 @@ * @psalm-template AType * @psalm-template BType * @psalm-template CType + * + * @psalm-immutable */ final class Psi extends Combinator { /** + * @psalm-var callable(AType): callable(AType): BType + * * @var callable */ private $f; /** + * @psalm-var callable(CType): AType + * * @var callable */ private $g; /** + * @psalm-var CType + * * @var mixed */ private $x; /** + * @psalm-var CType + * * @var mixed */ private $y; @@ -66,18 +76,32 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * @template NewCType + * + * @psalm-param callable(NewAType): callable(NewAType): NewBType $f + * + * @param callable $f + * + * @psalm-return Closure(callable(NewCType): NewAType): Closure(NewCType): Closure(NewCType): NewBType * * @return Closure */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function (callable $b) use ($a): Closure { - return static function ($c) use ($a, $b): Closure { - return static function ($d) use ($a, $b, $c) { - return (new self($a, $b, $c, $d))(); - }; + return + /** @psalm-param callable(NewCType): NewAType $g */ + static function (callable $g) use ($f): Closure { + return + /** @psalm-param NewCType $x */ + static function ($x) use ($f, $g): Closure { + return + /** @psalm-param NewCType $y */ + static function ($y) use ($f, $g, $x) { + return (new self($f, $g, $x, $y))(); + }; + }; }; - }; } } diff --git a/src/Combinator/Q.php b/src/Combinator/Q.php index 251b6a2..f0cc467 100644 --- a/src/Combinator/Q.php +++ b/src/Combinator/Q.php @@ -13,20 +13,28 @@ * @psalm-template AType * @psalm-template BType * @psalm-template CType + * + * @psalm-immutable */ final class Q extends Combinator { /** + * @psalm-var callable(AType): BType + * * @var callable */ private $f; /** + * @psalm-var callable(BType): CType + * * @var callable */ private $g; /** + * @psalm-var AType + * * @var mixed */ private $x; @@ -58,16 +66,28 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * @template NewCType + * + * @psalm-param callable(NewAType): NewBType $f + * + * @param callable $f + * + * @psalm-return Closure(callable(NewBType): NewCType): Closure(NewAType): NewCType * * @return Closure */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function (callable $b) use ($a): Closure { - return static function ($c) use ($a, $b) { - return (new self($a, $b, $c))(); + return + /** @psalm-param callable(NewBType): NewCType $g */ + static function (callable $g) use ($f): Closure { + return + /** @psalm-param NewAType $x */ + static function ($x) use ($f, $g) { + return (new self($f, $g, $x))(); + }; }; - }; } } diff --git a/src/Combinator/R.php b/src/Combinator/R.php index 7a0e34f..595cda7 100644 --- a/src/Combinator/R.php +++ b/src/Combinator/R.php @@ -13,20 +13,28 @@ * @psalm-template AType * @psalm-template BType * @psalm-template CType + * + * @psalm-immutable */ final class R extends Combinator { /** + * @psalm-var callable(BType): callable(AType): CType + * * @var callable */ private $f; /** + * @psalm-var AType + * * @var mixed */ private $x; /** + * @psalm-var BType + * * @var mixed */ private $y; @@ -58,16 +66,28 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * @template NewCType + * + * @psalm-param NewAType $x + * + * @param NewAType $x + * + * @psalm-return Closure(callable(NewBType): callable(NewAType): NewCType): Closure(NewBType): NewCType * * @return Closure */ - public static function on($a): Closure + public static function on($x): Closure { - return static function (callable $b) use ($a): Closure { - return static function ($c) use ($a, $b) { - return (new self($a, $b, $c))(); + return + /** @psalm-param callable(NewBType): callable(NewAType): NewCType $f */ + static function (callable $f) use ($x): Closure { + return + /** @psalm-param NewBType $y */ + static function ($y) use ($x, $f) { + return (new self($x, $f, $y))(); + }; }; - }; } } diff --git a/src/Combinator/S.php b/src/Combinator/S.php index 97d83a3..8daf6c2 100644 --- a/src/Combinator/S.php +++ b/src/Combinator/S.php @@ -13,20 +13,28 @@ * @psalm-template AType * @psalm-template BType * @psalm-template CType + * + * @psalm-immutable */ final class S extends Combinator { /** + * @psalm-var callable(AType): callable(BType): CType + * * @var callable */ private $f; /** + * @psalm-var callable(AType): BType + * * @var callable */ private $g; /** + * @psalm-var AType + * * @var mixed */ private $x; @@ -58,16 +66,28 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * @template NewCType + * + * @psalm-param callable(NewAType): callable(NewBType): NewCType $f + * + * @param callable $f + * + * @psalm-return Closure(callable(NewAType): NewBType): Closure(NewAType): NewCType * * @return Closure */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function (callable $b) use ($a): Closure { - return static function ($c) use ($a, $b) { - return (new self($a, $b, $c))(); + return + /** @psalm-param callable(NewAType): NewBType $g */ + static function (callable $g) use ($f): Closure { + return + /** @psalm-param NewAType $x */ + static function ($x) use ($f, $g) { + return (new self($f, $g, $x))(); + }; }; - }; } } diff --git a/src/Combinator/T.php b/src/Combinator/T.php index f726151..672dc13 100644 --- a/src/Combinator/T.php +++ b/src/Combinator/T.php @@ -12,15 +12,21 @@ * * @psalm-template AType * @psalm-template BType + * + * @psalm-immutable */ final class T extends Combinator { /** + * @psalm-var callable(AType): BType + * * @var callable */ private $f; /** + * @psalm-var AType + * * @var mixed */ private $x; @@ -49,14 +55,23 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * + * @psalm-param NewAType $x + * + * @param mixed $x + * + * @psalm-return Closure(callable(NewAType): NewBType): NewBType * * @return Closure */ - public static function on($a): Closure + public static function on($x): Closure { - return static function (callable $b) use ($a) { - return (new self($a, $b))(); + return + /** @psalm-param callable(NewAType): NewBType $f */ + static function (callable $f) use ($x) { + return (new self($x, $f))(); }; } } diff --git a/src/Combinator/U.php b/src/Combinator/U.php index 91d1029..1a33516 100644 --- a/src/Combinator/U.php +++ b/src/Combinator/U.php @@ -10,11 +10,13 @@ /** * Class U. * - * @psalm-template ResultType + * @psalm-immutable */ final class U extends Combinator { /** + * @psalm-var callable(callable): callable + * * @var callable */ private $f; @@ -27,8 +29,7 @@ final class U extends Combinator /** * U constructor. * - * @psalm-param callable $f - * @psalm-param callable $g + * @psalm-param callable(callable): callable $f * * @param callable $f * @param callable $g @@ -40,7 +41,7 @@ public function __construct(callable $f, callable $g) } /** - * @psalm-return ResultType + * @return mixed */ public function __invoke() { @@ -51,6 +52,10 @@ public function __invoke() } /** + * @psalm-suppress MissingClosureReturnType + * @psalm-suppress MissingClosureParamType + * @psalm-suppress MixedArgumentTypeCoercion + * * @param callable $a * * @return Closure diff --git a/src/Combinator/V.php b/src/Combinator/V.php index 7a4594f..c562f2c 100644 --- a/src/Combinator/V.php +++ b/src/Combinator/V.php @@ -13,20 +13,28 @@ * @psalm-template AType * @psalm-template BType * @psalm-template CType + * + * @psalm-immutable */ final class V extends Combinator { /** + * @psalm-var callable(AType): callable(BType): CType + * * @var callable */ private $f; /** + * @psalm-var AType + * * @var mixed */ private $x; /** + * @psalm-var BType + * * @var mixed */ private $y; @@ -58,16 +66,28 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * @template NewCType + * + * @psalm-param NewAType $x + * + * @param mixed $x + * + * @psalm-return Closure(NewBType): Closure(callable(NewAType): callable(NewBType): NewCType): NewCType * * @return Closure */ - public static function on($a): Closure + public static function on($x): Closure { - return static function ($b) use ($a): Closure { - return static function (callable $c) use ($a, $b) { - return (new self($a, $b, $c))(); + return + /** @psalm-param NewBType $y */ + static function ($y) use ($x): Closure { + return + /** @psalm-param callable(NewAType): callable(NewBType): NewCType $f */ + static function (callable $f) use ($x, $y) { + return (new self($x, $y, $f))(); + }; }; - }; } } diff --git a/src/Combinator/W.php b/src/Combinator/W.php index 64397b8..62af4d5 100644 --- a/src/Combinator/W.php +++ b/src/Combinator/W.php @@ -12,15 +12,21 @@ * * @psalm-template AType * @psalm-template BType + * + * @psalm-immutable */ final class W extends Combinator { /** + * @psalm-var callable(AType): callable(AType): BType + * * @var callable */ private $f; /** + * @psalm-var AType + * * @var mixed */ private $x; @@ -49,14 +55,23 @@ public function __invoke() } /** - * @param callable $a + * @template NewAType + * @template NewBType + * + * @psalm-param callable(NewAType): callable(NewAType): NewBType $f + * + * @param callable $f + * + * @psalm-return Closure(NewAType): NewBType * * @return Closure */ - public static function on(callable $a): Closure + public static function on(callable $f): Closure { - return static function ($b) use ($a) { - return (new self($a, $b))(); - }; + return + /** @psalm-param NewAType $x */ + static function ($x) use ($f) { + return (new self($f, $x))(); + }; } } diff --git a/src/Combinator/Y.php b/src/Combinator/Y.php index 076c3cc..f988dd8 100644 --- a/src/Combinator/Y.php +++ b/src/Combinator/Y.php @@ -10,11 +10,13 @@ /** * Class Y. * - * @psalm-template ResultType + * @psalm-immutable */ final class Y extends Combinator { /** + * @psalm-var callable(callable): Closure + * * @var callable */ private $f; @@ -22,7 +24,7 @@ final class Y extends Combinator /** * Y constructor. * - * @psalm-param callable $f + * @psalm-param callable(callable): Closure $f * * @param callable $f */ @@ -32,24 +34,38 @@ public function __construct(callable $f) } /** - * @psalm-return Closure(Closure(callable): mixed): mixed + * @psalm-suppress MixedInferredReturnType + * + * @return Closure */ public function __invoke() { $callable = $this->f; - $f = static function (callable $f) use ($callable): Closure { - return $callable( - static function (...$arguments) use ($f) { - return M::with()($f)(...$arguments); - } - ); - }; - - return M::with()($f); + /** + * @psalm-suppress MissingClosureReturnType + * @psalm-suppress MissingClosureParamType + * @psalm-suppress MixedArgumentTypeCoercion + * @psalm-suppress ImpureMethodCall + * @psalm-suppress MixedFunctionCall + * @psalm-suppress MixedReturnStatement + */ + return M::with()( + static function (callable $f) use ($callable): Closure { + return $callable( + static function (...$arguments) use ($f) { + return M::with()($f)(...$arguments); + } + ); + } + ); } /** + * @psalm-suppress MissingClosureReturnType + * @psalm-suppress MissingClosureParamType + * @psalm-suppress MixedArgumentTypeCoercion + * * @param callable $a * * @return Closure diff --git a/src/Combinator/Z.php b/src/Combinator/Z.php index a4b1eb4..af6676a 100644 --- a/src/Combinator/Z.php +++ b/src/Combinator/Z.php @@ -10,7 +10,7 @@ /** * Class Z. * - * @psalm-template ResultType + * @psalm-immutable */ final class Z extends Combinator { @@ -32,26 +32,40 @@ public function __construct(callable $f) } /** - * @psalm-return Closure(Closure(callable): mixed): mixed + * @psalm-suppress MixedInferredReturnType + * + * @return Closure */ public function __invoke() { $callable = $this->f; - $f = static function (callable $f) use ($callable): Closure { - return $callable( - static function () use ($f) { - return static function (...$arguments) use ($f) { - return M::with()($f)(...$arguments); - }; - } - ); - }; - - return M::with()($f); + /** + * @psalm-suppress MissingClosureReturnType + * @psalm-suppress MissingClosureParamType + * @psalm-suppress MixedArgumentTypeCoercion + * @psalm-suppress ImpureMethodCall + * @psalm-suppress MixedFunctionCall + * @psalm-suppress MixedReturnStatement + */ + return M::with()( + static function (callable $f) use ($callable): Closure { + return $callable( + static function () use ($f) { + return static function (...$arguments) use ($f) { + return M::with()($f)(...$arguments); + }; + } + ); + } + ); } /** + * @psalm-suppress MissingClosureReturnType + * @psalm-suppress MissingClosureParamType + * @psalm-suppress MixedArgumentTypeCoercion + * * @param callable $a * * @return Closure diff --git a/tests/src/BadCombinator.php b/tests/src/BadCombinator.php index 0f28a27..0b694ba 100644 --- a/tests/src/BadCombinator.php +++ b/tests/src/BadCombinator.php @@ -6,6 +6,11 @@ use loophp\combinator\Combinator; +/** + * Class BadCombinator. + * + * @psalm-immutable + */ class BadCombinator extends Combinator { } diff --git a/tests/static-analysis/A.php b/tests/static-analysis/A.php index 0e3c578..abed6dc 100644 --- a/tests/static-analysis/A.php +++ b/tests/static-analysis/A.php @@ -8,7 +8,7 @@ /** * @param callable(int): string $f - * @param string $x + * @param int $x * * @return string */ diff --git a/tests/static-analysis/K.php b/tests/static-analysis/K.php index faf13c4..13aaf6b 100644 --- a/tests/static-analysis/K.php +++ b/tests/static-analysis/K.php @@ -10,7 +10,7 @@ * @param string $x * @param int $y * - * @return int + * @return string */ function test($x, $y) { diff --git a/tests/static-analysis/U.php b/tests/static-analysis/U.php index 9a45a12..eeeda5f 100644 --- a/tests/static-analysis/U.php +++ b/tests/static-analysis/U.php @@ -7,7 +7,7 @@ use loophp\combinator\Combinator\U as Combinator; /** - * @param callable(int): mixed $f + * @param callable(callable):callable $f * @param callable(int): mixed $g * * @return mixed diff --git a/tests/static-analysis/Y.php b/tests/static-analysis/Y.php index 06b11d1..042ce34 100644 --- a/tests/static-analysis/Y.php +++ b/tests/static-analysis/Y.php @@ -4,14 +4,15 @@ namespace loophp\combinator\Tests\StaticAnalysis; +use Closure; use loophp\combinator\Combinator\Y as Combinator; /** - * @param callable(int): callable $f + * @param callable(callable): Closure $f * - * @return callable + * @return Closure */ -function test(callable $f) +function test(callable $f): Closure { return (new Combinator($f))(); } diff --git a/tests/static-analysis/Z.php b/tests/static-analysis/Z.php index 9237705..d538b82 100644 --- a/tests/static-analysis/Z.php +++ b/tests/static-analysis/Z.php @@ -4,14 +4,15 @@ namespace loophp\combinator\Tests\StaticAnalysis; +use Closure; use loophp\combinator\Combinator\Z as Combinator; /** - * @param callable(int): callable $f + * @param callable(callable): Closure $f * - * @return callable + * @return Closure */ -function test(callable $f) +function test(callable $f): Closure { return (new Combinator($f))(); }