Skip to content

Commit f71ae65

Browse files
committed
Add basic template annotations
This adds basic type safety annotations for static analyzers like PHPStan and Psalm. This will cover around 80% of the use cases and a follow-up PR for all supported versions will be proposed later to get it to a 100% of close to a 100%. By adding these annotations methods returning a promise can hint their resolving type by adding `@return PromiseInterface<bool>` when they for example resolve to a boolean. By doing that Psalm and PHPStan will understand that the following bit of code will not become an issue because the method's contract promised a boolean through the promise: ```php $promise->then(static function (bool $isEnabled) {}); ``` However, the following will yield errors: ```php $promise->then(static function (string $isEnabled) {}); ``` This PR is a requirement for reactphp/async#40
1 parent 77aa876 commit f71ae65

File tree

6 files changed

+36
-4
lines changed

6 files changed

+36
-4
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/.gitattributes export-ignore
22
/.github/ export-ignore
33
/.gitignore export-ignore
4+
/phpstan.neon.dist export-ignore
45
/phpunit.xml.dist export-ignore
56
/phpunit.xml.legacy export-ignore
67
/tests/ export-ignore
8+
/types/ export-ignore

.github/workflows/ci.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,15 @@ jobs:
4545
- run: composer self-update --2.2 # downgrade Composer for HHVM
4646
- run: hhvm $(which composer) install
4747
- run: hhvm vendor/bin/phpunit
48+
49+
PHPStan:
50+
name: PHPStan
51+
runs-on: ubuntu-20.04
52+
continue-on-error: true
53+
steps:
54+
- uses: actions/checkout@v3
55+
- uses: shivammathur/setup-php@v2
56+
with:
57+
php-version: 8.1
58+
- run: composer require phpstan/phpstan
59+
- run: vendor/bin/phpstan

phpstan.neon.dist

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
parameters:
2+
paths:
3+
- types
4+
level: max

src/PromiseInterface.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace React\Promise;
44

5+
/**
6+
* @template T
7+
*/
58
interface PromiseInterface
69
{
710
/**
@@ -32,10 +35,11 @@ interface PromiseInterface
3235
* than once.
3336
* 3. `$onProgress` (deprecated) may be called multiple times.
3437
*
35-
* @param callable|null $onFulfilled
38+
* @template TReturn of mixed
39+
* @param callable(T): TReturn $onFulfilled
3640
* @param callable|null $onRejected
3741
* @param callable|null $onProgress This argument is deprecated and should not be used anymore.
38-
* @return PromiseInterface
42+
* @return (TReturn is PromiseInterface ? TReturn : PromiseInterface<TReturn>)
3943
*/
4044
public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
4145
}

src/functions.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
*
1414
* If `$promiseOrValue` is a promise, it will be returned as is.
1515
*
16-
* @param mixed $promiseOrValue
17-
* @return PromiseInterface
16+
* @template T
17+
* @param T $promiseOrValue
18+
* @return PromiseInterface<T>
1819
*/
1920
function resolve($promiseOrValue = null)
2021
{

types/PromiseInterface.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
use function PHPStan\Testing\assertType;
4+
use function React\Promise\resolve;
5+
6+
$passThroughBoolFn = static fn (bool $bool): bool => $bool;
7+
8+
assertType('React\Promise\PromiseInterface<bool>', resolve(true));
9+
assertType('React\Promise\PromiseInterface<bool>', resolve(true)->then($passThroughBoolFn));

0 commit comments

Comments
 (0)