From 5f1eb0613944471ecc2ed2a2d3436ddac74c6f73 Mon Sep 17 00:00:00 2001 From: Mathieu Ledru Date: Tue, 13 Aug 2024 13:59:12 +0200 Subject: [PATCH] :construction: Validate some PHPStan --- examples/flow.php | 2 +- src/AsyncHandler/AsyncHandler.php | 5 +++++ src/AsyncHandler/BatchAsyncHandler.php | 14 +++++++++++++- src/AsyncHandler/DeferAsyncHandler.php | 5 +++++ src/AsyncHandlerInterface.php | 6 ++++++ src/Driver/AmpDriver.php | 20 ++++++++++++-------- src/Driver/FiberDriver.php | 6 +----- src/Driver/ReactDriver.php | 9 ++++----- src/Driver/SpatieDriver.php | 8 +------- src/Driver/SwooleDriver.php | 8 +------- src/DriverInterface.php | 2 ++ src/Event/AsyncEvent.php | 9 +++++++++ src/Flow/Flow.php | 1 + src/Flow/YFlow.php | 1 + tools/php-cs-fixer/.php-cs-fixer.php | 1 + 15 files changed, 63 insertions(+), 34 deletions(-) diff --git a/examples/flow.php b/examples/flow.php index 26edddd6..e697db3d 100644 --- a/examples/flow.php +++ b/examples/flow.php @@ -18,7 +18,7 @@ use Flow\Ip; use Flow\IpStrategy\MaxIpStrategy; -$driver = match (random_int(4, 4)) { +$driver = match (random_int(1, 4)) { 1 => new AmpDriver(), 2 => new FiberDriver(), 3 => new ReactDriver(), diff --git a/src/AsyncHandler/AsyncHandler.php b/src/AsyncHandler/AsyncHandler.php index 8e11d533..c81c5cc7 100644 --- a/src/AsyncHandler/AsyncHandler.php +++ b/src/AsyncHandler/AsyncHandler.php @@ -8,6 +8,11 @@ use Flow\Event; use Flow\Event\AsyncEvent; +/** + * @template T + * + * @implements AsyncHandlerInterface + */ final class AsyncHandler implements AsyncHandlerInterface { public static function getSubscribedEvents() diff --git a/src/AsyncHandler/BatchAsyncHandler.php b/src/AsyncHandler/BatchAsyncHandler.php index 136ffe35..54625085 100644 --- a/src/AsyncHandler/BatchAsyncHandler.php +++ b/src/AsyncHandler/BatchAsyncHandler.php @@ -12,12 +12,24 @@ use Symfony\Component\Messenger\Handler\BatchHandlerTrait; use Throwable; +/** + * @template T1 + * @template T2 + * + * @implements AsyncHandlerInterface + */ final class BatchAsyncHandler implements BatchHandlerInterface, AsyncHandlerInterface { use BatchHandlerTrait; + /** + * @var AsyncHandlerInterface + */ private AsyncHandlerInterface $asyncHandler; + /** + * @param null|AsyncHandlerInterface $asyncHandler + */ public function __construct( private int $batchSize = 10, ?AsyncHandlerInterface $asyncHandler = null, @@ -46,7 +58,7 @@ public function async(AsyncEvent $event): void * https://github.com/phpstan/phpstan/issues/6039 * https://phpstan.org/r/8f7de023-9888-4dcb-b12c-e2fcf9547b6c. * - * @param array{0: AsyncEvent, 1: Acknowledger}[] $jobs + * @param array{0: AsyncEvent, 1: Acknowledger}[] $jobs * * @phpstan-ignore method.unused */ diff --git a/src/AsyncHandler/DeferAsyncHandler.php b/src/AsyncHandler/DeferAsyncHandler.php index 8993af0c..b36727a9 100644 --- a/src/AsyncHandler/DeferAsyncHandler.php +++ b/src/AsyncHandler/DeferAsyncHandler.php @@ -8,6 +8,11 @@ use Flow\Event; use Flow\Event\AsyncEvent; +/** + * @template T + * + * @implements AsyncHandlerInterface + */ final class DeferAsyncHandler implements AsyncHandlerInterface { public static function getSubscribedEvents() diff --git a/src/AsyncHandlerInterface.php b/src/AsyncHandlerInterface.php index 2296c38e..c66ce8df 100644 --- a/src/AsyncHandlerInterface.php +++ b/src/AsyncHandlerInterface.php @@ -7,7 +7,13 @@ use Flow\Event\AsyncEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +/** + * @template T + */ interface AsyncHandlerInterface extends EventSubscriberInterface { + /** + * @param AsyncEvent $event + */ public function async(AsyncEvent $event): void; } diff --git a/src/Driver/AmpDriver.php b/src/Driver/AmpDriver.php index f9fe15f0..e4df3da1 100644 --- a/src/Driver/AmpDriver.php +++ b/src/Driver/AmpDriver.php @@ -46,6 +46,9 @@ public function __construct(?Driver $driver = null) } } + /** + * @return Closure(TArgs): Future + */ public function async(Closure $callback): Closure { return static function (...$args) use ($callback) { @@ -59,6 +62,9 @@ public function async(Closure $callback): Closure }; } + /** + * @return Future + */ public function defer(Closure $callback): Future { $deferred = new DeferredFuture(); @@ -84,20 +90,18 @@ public function await(array &$stream): void return function (mixed $data) use ($job) { $async = $this->async($job); - if ($data === null) { - $future = $async(); - } else { - $future = $async($data); - } + $future = $async($data); - return static function ($map) use ($future) { + return static function (Closure $map) use ($future) { + /** @var Closure(TReturn): mixed $map */ $future->map($map); }; }; }; $defer = function (Closure $job) { - return function ($map) use ($job) { + return function (Closure $map) use ($job) { + /** @var Closure(TReturn): mixed $map */ $future = $this->defer($job); $future->map($map); }; @@ -143,7 +147,7 @@ public function delay(float $seconds): void delay($seconds); } - public function tick($interval, Closure $callback): Closure + public function tick(float $interval, Closure $callback): Closure { $this->ticks++; $tickId = EventLoop::repeat($interval, $callback); diff --git a/src/Driver/FiberDriver.php b/src/Driver/FiberDriver.php index c8875ee0..538433fd 100644 --- a/src/Driver/FiberDriver.php +++ b/src/Driver/FiberDriver.php @@ -54,11 +54,7 @@ public function await(array &$stream): void $exception = null; try { - if ($data === null) { - $fiber->start(); - } else { - $fiber->start($data); - } + $fiber->start($data); } catch (Throwable $fiberException) { $exception = $fiberException; } diff --git a/src/Driver/ReactDriver.php b/src/Driver/ReactDriver.php index af0da320..60453b0c 100644 --- a/src/Driver/ReactDriver.php +++ b/src/Driver/ReactDriver.php @@ -59,6 +59,9 @@ public function async(Closure $callback): Closure }; } + /** + * @return Promise + */ public function defer(Closure $callback): Promise { $deferred = new Deferred(); @@ -82,11 +85,7 @@ public function await(array &$stream): void return function (mixed $data) use ($job) { $async = $this->async($job); - if ($data === null) { - $promise = $async(); - } else { - $promise = $async($data); - } + $promise = $async($data); return static function ($then) use ($promise) { $promise->then($then); diff --git a/src/Driver/SpatieDriver.php b/src/Driver/SpatieDriver.php index a05360ab..e7d67787 100644 --- a/src/Driver/SpatieDriver.php +++ b/src/Driver/SpatieDriver.php @@ -71,13 +71,7 @@ public function await(array &$stream): void return function (mixed $data) use ($job) { $async = $this->async($job); - if ($data === null) { - $fn = $async(); - } else { - $fn = $async($data); - } - - return $fn; + return $async($data); }; }; diff --git a/src/Driver/SwooleDriver.php b/src/Driver/SwooleDriver.php index 1b45d8b2..eff836e3 100644 --- a/src/Driver/SwooleDriver.php +++ b/src/Driver/SwooleDriver.php @@ -65,13 +65,7 @@ public function await(array &$stream): void return function (mixed $data) use ($job) { $async = $this->async($job); - if ($data === null) { - $fn = $async(); - } else { - $fn = $async($data); - } - - return $fn; + return $async($data); }; }; diff --git a/src/DriverInterface.php b/src/DriverInterface.php index 086eb869..55298e29 100644 --- a/src/DriverInterface.php +++ b/src/DriverInterface.php @@ -24,6 +24,8 @@ public function async(Closure $callback): Closure; * $callback will be given two callbacks * - an complete callback to store result * - an async callback to go to the next async call. + * + * @param Closure(callable(TReturn): void, callable(mixed, callable): void): void $callback */ public function defer(Closure $callback): mixed; diff --git a/src/Event/AsyncEvent.php b/src/Event/AsyncEvent.php index dd68f744..83046438 100644 --- a/src/Event/AsyncEvent.php +++ b/src/Event/AsyncEvent.php @@ -8,8 +8,14 @@ use Flow\Ip; use Symfony\Contracts\EventDispatcher\Event; +/** + * @template T + */ final class AsyncEvent extends Event { + /** + * @param Ip $ip + */ public function __construct( private Closure $async, private Closure $defer, @@ -33,6 +39,9 @@ public function getJob(): Closure return $this->job; } + /** + * @return Ip + */ public function getIp(): Ip { return $this->ip; diff --git a/src/Flow/Flow.php b/src/Flow/Flow.php index ccb8e13e..903625ce 100644 --- a/src/Flow/Flow.php +++ b/src/Flow/Flow.php @@ -62,6 +62,7 @@ class Flow implements FlowInterface * @param Closure(T1): T2 $job * @param Closure(ExceptionInterface): void $errorJob * @param null|IpStrategyInterface $ipStrategy + * @param null|AsyncHandlerInterface $asyncHandler * @param null|DriverInterface $driver */ public function __construct( diff --git a/src/Flow/YFlow.php b/src/Flow/YFlow.php index 1c061e55..dd2eff77 100644 --- a/src/Flow/YFlow.php +++ b/src/Flow/YFlow.php @@ -22,6 +22,7 @@ class YFlow extends Flow /** * @param null|Closure(ExceptionInterface): void $errorJob * @param null|IpStrategyInterface $ipStrategy + * @param null|AsyncHandlerInterface $asyncHandler * @param null|DriverInterface $driver */ public function __construct( diff --git a/tools/php-cs-fixer/.php-cs-fixer.php b/tools/php-cs-fixer/.php-cs-fixer.php index c1321a1d..e159a0b6 100644 --- a/tools/php-cs-fixer/.php-cs-fixer.php +++ b/tools/php-cs-fixer/.php-cs-fixer.php @@ -26,6 +26,7 @@ 'php_unit_internal_class' => false, // From @PhpCsFixer but we don't want it 'php_unit_test_class_requires_covers' => false, // From @PhpCsFixer but we don't want it 'phpdoc_add_missing_param_annotation' => false, // From @PhpCsFixer but we don't want it + 'phpdoc_to_comment' => false, // We want PHPStan keep pass with anotation line comments 'concat_space' => ['spacing' => 'one'], 'ordered_class_elements' => true, // Symfony(PSR12) override the default value, but we don't want 'blank_line_before_statement' => true, // Symfony(PSR12) override the default value, but we don't want