Skip to content

Commit

Permalink
Merge pull request #47 from BedrockStreaming/feat/phpstan-update
Browse files Browse the repository at this point in the history
feat: update phpstan and fix reported errors
  • Loading branch information
valentin-claras authored Sep 1, 2021
2 parents 71849ca + b190dda commit aa078bb
Show file tree
Hide file tree
Showing 23 changed files with 134 additions and 75 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"ext-curl": "^7.1",
"react/event-loop": "^1.0",
"react/promise": "^2.7",
"phpstan/phpstan": "^0.10.5",
"phpstan/phpstan": "^0.12",
"symfony/http-client": "^4.3",
"psr/http-factory": "^1.0",
"http-interop/http-factory-guzzle": "^1.0"
Expand Down
2 changes: 1 addition & 1 deletion examples/tests/ExamplesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public function examplesProvider()
/**
* @dataProvider examplesProvider
*/
public function testExampleShouldRun(string $exampleFile, string $eventloopName, string $exampleCode)
public function testExampleShouldRun(string $exampleFile, string $eventloopName, string $exampleCode): void
{
// Sanitize loop name to create a relevant temporary filename
$eventLoopFileId = preg_replace('/[^a-z0-9]+/', '', strtolower($eventloopName));
Expand Down
24 changes: 24 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
parameters:
checkMissingIterableValueType: false
checkGenericClassInNonGenericObjectType: false
ignoreErrors:
-
message: '#Negated boolean expression is always true\.#'
path: src/Adapter/Amp/Internal/PromiseWrapper.php
count: 1
-
message: '#Negated boolean expression is always true\.#'
path: src/Adapter/ReactPhp/Internal/PromiseWrapper.php
count: 1
-
message: '#Anonymous function should return Generator but empty return statement found.#'
path: src/Adapter/Tornado/EventLoop.php
count: 1
-
message: '#Unreachable statement - code above always terminates\.#'
path: src/Adapter/Tornado/EventLoop.php
count: 1
-
message: '#Unreachable statement - code above always terminates\.#'
path: tests/EventLoopTest.php
count: 3
4 changes: 2 additions & 2 deletions src/Adapter/Amp/Internal/PromiseWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ private function __construct()
{
}

public static function createUnhandled(\Amp\Promise $ampPromise, FailingPromiseCollection $failingPromiseCollection)
public static function createUnhandled(\Amp\Promise $ampPromise, FailingPromiseCollection $failingPromiseCollection): self
{
$promiseWrapper = new self();
$promiseWrapper->isHandled = false;
Expand All @@ -40,7 +40,7 @@ function (?\Throwable $reason, $value) use ($promiseWrapper, $failingPromiseColl
return $promiseWrapper;
}

public static function createHandled(\Amp\Promise $ampPromise)
public static function createHandled(\Amp\Promise $ampPromise): self
{
$promiseWrapper = new self();
$promiseWrapper->isHandled = true;
Expand Down
4 changes: 3 additions & 1 deletion src/Adapter/Guzzle/HttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class HttpClient implements \M6Web\Tornado\HttpClient
/** @var GuzzleClientWrapper */
private $clientWrapper;

/** @var int */
private $nbConcurrentRequests = 0;

public function __construct(EventLoop $eventLoop, GuzzleClientWrapper $clientWrapper)
Expand Down Expand Up @@ -67,7 +68,8 @@ private function http2fallback(RequestInterface $request): RequestInterface
if (
'https' !== $request->getUri()->getScheme()
|| !\defined('CURL_VERSION_HTTP2')
|| !(CURL_VERSION_HTTP2 & curl_version()['features'])
|| (($curlVersion = curl_version()) === false)
|| !(CURL_VERSION_HTTP2 & $curlVersion['features'])
) {
return $request->withProtocolVersion('1.1');
}
Expand Down
4 changes: 2 additions & 2 deletions src/Adapter/ReactPhp/Internal/PromiseWrapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ private function __construct()
{
}

public static function createUnhandled(\React\Promise\PromiseInterface $reactPromise, FailingPromiseCollection $failingPromiseCollection)
public static function createUnhandled(\React\Promise\PromiseInterface $reactPromise, FailingPromiseCollection $failingPromiseCollection): self
{
$promiseWrapper = new self();
$promiseWrapper->isHandled = false;
Expand All @@ -41,7 +41,7 @@ function (?\Throwable $reason) use ($promiseWrapper, $failingPromiseCollection)
return $promiseWrapper;
}

public static function createHandled(\React\Promise\PromiseInterface $reactPromise)
public static function createHandled(\React\Promise\PromiseInterface $reactPromise): self
{
$promiseWrapper = new self();
$promiseWrapper->isHandled = true;
Expand Down
2 changes: 1 addition & 1 deletion src/Adapter/Symfony/HttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ private function symfonyEventLoop(): \Generator
$currentJobs = $this->jobs;
$this->jobs = [];
/**
* @var SfResponseInterface
* @var SfResponseInterface $response
* @var ChunkInterface $chunk
*/
foreach ($this->symfonyClient->stream($currentJobs, 0) as $response => $chunk) {
Expand Down
10 changes: 7 additions & 3 deletions src/Adapter/Tornado/Internal/PendingPromise.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@
*/
class PendingPromise implements Promise, Deferred
{
/** @var mixed */
private $value;
/** @var \Throwable */
private $throwable;
/** @var callable[][] */
private $callbacks = [];
/** @var bool */
private $isSettled = false;
/** @var ?FailingPromiseCollection */
private $failingPromiseCollection;
Expand All @@ -26,15 +30,15 @@ private function __construct()
{
}

public static function createUnhandled(FailingPromiseCollection $failingPromiseCollection)
public static function createUnhandled(FailingPromiseCollection $failingPromiseCollection): self
{
$promiseWrapper = new self();
$promiseWrapper->failingPromiseCollection = $failingPromiseCollection;

return $promiseWrapper;
}

public static function createHandled()
public static function createHandled(): self
{
$promiseWrapper = new self();
$promiseWrapper->failingPromiseCollection = null;
Expand Down Expand Up @@ -103,7 +107,7 @@ private function triggerCallbacks(): self
return $this;
}

private function settle()
private function settle(): void
{
if ($this->isSettled) {
throw new \LogicException('Cannot resolve/reject a promise already settled.');
Expand Down
9 changes: 9 additions & 0 deletions src/Adapter/Tornado/Internal/StreamEventLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@ class StreamEventLoop
/** @var PendingPromise[] */
private $pendingPromises = [];

/**
* @param resource $stream
*/
public function readable(EventLoop $eventLoop, $stream): PendingPromise
{
return $this->recordStream($eventLoop, $stream, $this->readStreams);
}

/**
* @param resource $stream
*/
public function writable(EventLoop $eventLoop, $stream): PendingPromise
{
return $this->recordStream($eventLoop, $stream, $this->writeStreams);
Expand Down Expand Up @@ -58,6 +64,9 @@ private function internalLoop(EventLoop $eventLoop): \Generator
}
}

/**
* @param resource $stream
*/
private function recordStream(EventLoop $eventLoop, $stream, array &$streamsList): PendingPromise
{
$streamId = (int) $stream;
Expand Down
2 changes: 2 additions & 0 deletions src/Adapter/Tornado/Internal/Task.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
*/
class Task
{
/** @var \Generator */
private $generator;
/** @var PendingPromise */
private $promise;

public function __construct(\Generator $generator, PendingPromise $pendingPromise)
Expand Down
5 changes: 3 additions & 2 deletions src/Adapter/Tornado/SynchronousEventLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,12 @@ public function deferred(): Deferred
$deferred = new class() implements Deferred {
/** @var SynchronousEventLoop */
public $eventLoop;
private $promise;
/** @var ?Promise */
private $promise = null;

public function getPromise(): Promise
{
if (!$this->promise) {
if ($this->promise === null) {
throw new \Error('Synchronous Deferred must be resolved/rejected before to retrieve its promise.');
}

Expand Down
1 change: 1 addition & 0 deletions src/Deferred.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public function getPromise(): Promise;

/**
* Resolves associated promise.
* @param mixed $value
*/
public function resolve($value): void;

Expand Down
1 change: 1 addition & 0 deletions src/EventLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public function promiseRace(Promise ...$promises): Promise;

/**
* Creates a promise already resolved with $value.
* @param mixed $value
*/
public function promiseFulfilled($value): Promise;

Expand Down
6 changes: 3 additions & 3 deletions tests/Adapter/Amp/EventLoopTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ protected function createEventLoop(): EventLoop
return new Amp\EventLoop();
}

public function testStreamShouldReadFromWritable($expectedSequence = '')
public function testStreamShouldReadFromWritable(string $expectedSequence = ''): void
{
// Because Amp resolve promises in a slightly different order.
parent::testStreamShouldReadFromWritable('W0R0W12345R12R34W6R56R');
}

public function testStreamShouldNotBeWritableIfClosed()
public function testStreamShouldNotBeWritableIfClosed(): void
{
assert_options(ASSERT_EXCEPTION, 1);
$this->expectException(\Throwable::class);

parent::testStreamShouldNotBeWritableIfClosed();
}

public function testStreamShouldNotBeReadableIfClosed()
public function testStreamShouldNotBeReadableIfClosed(): void
{
assert_options(ASSERT_EXCEPTION, 1);
$this->expectException(\Throwable::class);
Expand Down
4 changes: 2 additions & 2 deletions tests/Adapter/Guzzle/HttpClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ protected function createHttpClient(EventLoop $eventLoop, array $responsesOrExce
/**
* @dataProvider eventLoopProvider
*/
public function testWrapperIsTicked(EventLoop $eventLoop)
public function testWrapperIsTicked(EventLoop $eventLoop): void
{
$httpClient = new \M6Web\Tornado\Adapter\Guzzle\HttpClient(
$eventLoop,
Expand All @@ -35,7 +35,7 @@ public function testWrapperIsTicked(EventLoop $eventLoop)
/**
* @dataProvider eventLoopProvider
*/
public function testRequestExceptionsAreSuccessful(EventLoop $eventLoop)
public function testRequestExceptionsAreSuccessful(EventLoop $eventLoop): void
{
$request = new Request('GET', 'http://www.example.com');
$expectedResponse = new Response(500, [], 'An error occurred');
Expand Down
14 changes: 7 additions & 7 deletions tests/Adapter/Tornado/SynchronousEventLoopTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,31 @@ protected function createEventLoop(): EventLoop
return new Tornado\SynchronousEventLoop();
}

public function testIdle($expectedSequence = '')
public function testIdle(string $expectedSequence = ''): void
{
//By definition, this is not an asynchronous EventLoop
parent::testIdle('AAABBC');
}

public function testPromiseRaceShouldResolvePromisesArray(int $expectedValue = 2)
public function testPromiseRaceShouldResolvePromisesArray(int $expectedValue = 2): void
{
// In the synchronous case, there is no race, first promise always win
parent::testPromiseRaceShouldResolvePromisesArray(1);
}

public function testPromiseRaceShouldRejectIfFirstSettledPromiseRejects(int $expectedValue = 2)
public function testPromiseRaceShouldRejectIfFirstSettledPromiseRejects(int $expectedValue = 2): void
{
// In the synchronous case, there is no race, first promise always win
parent::testPromiseRaceShouldRejectIfFirstSettledPromiseRejects(1);
}

public function testStreamShouldReadFromWritable($expectedSequence = '')
public function testStreamShouldReadFromWritable(string $expectedSequence = ''): void
{
// Never wait…
parent::testStreamShouldReadFromWritable('W0W12345W6R01R23R45R6R');
}

public function testDelay()
public function testDelay(): void
{
$expectedDelay = 42; /*ms*/
$eventLoop = $this->createEventLoop();
Expand All @@ -54,14 +54,14 @@ public function testDelay()
$this->assertLessThanOrEqual($expectedDelay + 10, $duration);
}

public function testWaitFunctionShouldReturnAsSoonAsPromiseIsResolved()
public function testWaitFunctionShouldReturnAsSoonAsPromiseIsResolved(): void
{
// By definition, synchronous event loop can only wait a promise if already resolved.
// So this use case is not relevant for this particular implementation.
$this->assertTrue(true);
}

public function testWaitFunctionShouldThrowIfPromiseCannotBeResolved()
public function testWaitFunctionShouldThrowIfPromiseCannotBeResolved(): void
{
$eventLoop = $this->createEventLoop();
$deferred = $eventLoop->deferred();
Expand Down
Loading

0 comments on commit aa078bb

Please sign in to comment.