diff --git a/.gitattributes b/.gitattributes index 21be40ca..94a1c394 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,8 @@ /.gitattributes export-ignore /.github/ export-ignore /.gitignore export-ignore +/phpstan.neon.dist export-ignore /phpunit.xml.dist export-ignore /phpunit.xml.legacy export-ignore /tests/ export-ignore +/types/ export-ignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e20fa07c..749a5e87 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,3 +45,18 @@ jobs: - run: composer self-update --2.2 # downgrade Composer for HHVM - run: hhvm $(which composer) install - run: hhvm vendor/bin/phpunit + + PHPStan: + name: PHPStan + runs-on: ubuntu-20.04 + strategy: + matrix: + php: + - 8.1 + steps: + - uses: actions/checkout@v3 + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + - run: composer require phpstan/phpstan + - run: vendor/bin/phpstan diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 00000000..609d438c --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,4 @@ +parameters: + paths: + - types + level: max diff --git a/src/PromiseInterface.php b/src/PromiseInterface.php index edcb0077..f52f5443 100644 --- a/src/PromiseInterface.php +++ b/src/PromiseInterface.php @@ -2,6 +2,9 @@ namespace React\Promise; +/** + * @template T + */ interface PromiseInterface { /** @@ -32,10 +35,11 @@ interface PromiseInterface * than once. * 3. `$onProgress` (deprecated) may be called multiple times. * - * @param callable|null $onFulfilled + * @template TReturn of mixed + * @param callable(T): TReturn $onFulfilled * @param callable|null $onRejected * @param callable|null $onProgress This argument is deprecated and should not be used anymore. - * @return PromiseInterface + * @return (TReturn is PromiseInterface ? TReturn : PromiseInterface) */ public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null); } diff --git a/src/functions.php b/src/functions.php index 429f0e73..469fedc4 100644 --- a/src/functions.php +++ b/src/functions.php @@ -13,8 +13,9 @@ * * If `$promiseOrValue` is a promise, it will be returned as is. * - * @param mixed $promiseOrValue - * @return PromiseInterface + * @template T + * @param T $promiseOrValue + * @return PromiseInterface */ function resolve($promiseOrValue = null) { diff --git a/types/PromiseInterface.php b/types/PromiseInterface.php new file mode 100644 index 00000000..5fd5e8d8 --- /dev/null +++ b/types/PromiseInterface.php @@ -0,0 +1,9 @@ + $bool; + +assertType('React\Promise\PromiseInterface', resolve(true)); +assertType('React\Promise\PromiseInterface', resolve(true)->then($passThroughBoolFn));