Skip to content

Commit

Permalink
Add basic template annotations
Browse files Browse the repository at this point in the history
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
  • Loading branch information
WyriHaximus committed Jul 9, 2022
1 parent 77aa876 commit 4abe816
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 4 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -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
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,17 @@ 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: vendor/bin/phpstan
4 changes: 4 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
parameters:
paths:
- types
level: max
8 changes: 6 additions & 2 deletions src/PromiseInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace React\Promise;

/**
* @template T
*/
interface PromiseInterface
{
/**
Expand Down Expand Up @@ -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<TReturn>)
*/
public function then(callable $onFulfilled = null, callable $onRejected = null, callable $onProgress = null);
}
5 changes: 3 additions & 2 deletions src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -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<T>
*/
function resolve($promiseOrValue = null)
{
Expand Down
9 changes: 9 additions & 0 deletions types/PromiseInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

use function PHPStan\Testing\assertType;
use function React\Promise\resolve;

$passThroughBoolFn = static fn (bool $bool): bool => $bool;

assertType('React\Promise\PromiseInterface<bool>', resolve(true));
assertType('React\Promise\PromiseInterface<bool>', resolve(true)->then($passThroughBoolFn));

0 comments on commit 4abe816

Please sign in to comment.