Skip to content

Commit

Permalink
[WIP][3.x] Introduce PHPStan
Browse files Browse the repository at this point in the history
Full commit message will follow
  • Loading branch information
WyriHaximus committed Feb 12, 2024
1 parent 862cdc4 commit eb61e23
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 16 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,31 @@ jobs:
uses: docker://hhvm/hhvm:3.30-lts-latest
with:
args: hhvm vendor/bin/phpunit

PHPStan:
name: PHPStan (PHP ${{ matrix.php }})
runs-on: ubuntu-22.04
strategy:
matrix:
php:
- 8.3
- 8.2
- 8.1
- 8.0
- 7.4
- 7.3
- 7.2
- 7.1
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
ini-file: development
ini-values: disable_functions='' # do not disable PCNTL functions on PHP < 8.1
extensions: sockets, pcntl ${{ matrix.php >= 5.6 && ', event' || '' }} ${{ matrix.php >= 5.4 && ', ev' || '' }}
env:
fail-fast: true # fail step if any extension can not be installed
- run: composer install
- run: vendor/bin/phpstan
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"php": ">=5.3.0"
},
"require-dev": {
"phpstan/phpstan": "^1",
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36"
},
"suggest": {
Expand Down
6 changes: 6 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
parameters:
level: 5

paths:
- src/
- tests/
14 changes: 12 additions & 2 deletions src/ExtEvLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,21 @@ public function run()
$this->futureTickQueue->tick();

$hasPendingCallbacks = !$this->futureTickQueue->isEmpty();
/**
* @link https://github.com/phpstan/phpstan/issues/10566
* @phpstan-ignore-next-line
*/
$wasJustStopped = !$this->running;
$nothingLeftToDo = !$this->readStreams
&& !$this->writeStreams
&& !$this->timers->count()
&& $this->signals->isEmpty();

$flags = Ev::RUN_ONCE;
/**
* @link https://github.com/phpstan/phpstan/issues/10566
* @phpstan-ignore-next-line
*/
if ($wasJustStopped || $hasPendingCallbacks) {
$flags |= Ev::RUN_NOWAIT;
} elseif ($nothingLeftToDo) {
Expand All @@ -222,11 +230,13 @@ public function __destruct()
}

foreach ($this->readStreams as $key => $stream) {
$this->removeReadStream($key);
$this->readStreams[$key]->stop();
unset($this->readStreams[$key]);
}

foreach ($this->writeStreams as $key => $stream) {
$this->removeWriteStream($key);
$this->readStreams[$key]->stop();
unset($this->readStreams[$key]);
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/ExtEventLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ public function run()
$this->futureTickQueue->tick();

$flags = EventBase::LOOP_ONCE;
/**
* @link https://github.com/phpstan/phpstan/issues/10566
* @phpstan-ignore-next-line
*/
if (!$this->running || !$this->futureTickQueue->isEmpty()) {
$flags |= EventBase::LOOP_NONBLOCK;
} elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count() && $this->signals->isEmpty()) {
Expand Down
16 changes: 16 additions & 0 deletions src/ExtUvLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ public function run()
$this->futureTickQueue->tick();

$hasPendingCallbacks = !$this->futureTickQueue->isEmpty();
/**
* @link https://github.com/phpstan/phpstan/issues/10566
* @phpstan-ignore-next-line
*/
$wasJustStopped = !$this->running;
$nothingLeftToDo = !$this->readStreams
&& !$this->writeStreams
Expand All @@ -223,12 +227,20 @@ public function run()
// otherwise use UV::RUN_NOWAIT.
// @link http://docs.libuv.org/en/v1.x/loop.html#c.uv_run
$flags = \UV::RUN_ONCE;
/**
* @link https://github.com/phpstan/phpstan/issues/10566
* @phpstan-ignore-next-line
*/
if ($wasJustStopped || $hasPendingCallbacks) {
$flags = \UV::RUN_NOWAIT;
} elseif ($nothingLeftToDo) {
break;
}

/**
* @link https://github.com/JetBrains/phpstorm-stubs/pull/1614
* @phpstan-ignore-next-line
*/
\uv_run($this->uv, $flags);
}
}
Expand Down Expand Up @@ -261,6 +273,10 @@ private function removeStream($stream)
if (!isset($this->readStreams[(int) $stream])
&& !isset($this->writeStreams[(int) $stream])) {
\uv_poll_stop($this->streamEvents[(int) $stream]);
/**
* @link https://github.com/JetBrains/phpstorm-stubs/pull/1615
* @phpstan-ignore-next-line
*/
\uv_close($this->streamEvents[(int) $stream]);
unset($this->streamEvents[(int) $stream]);
return;
Expand Down
6 changes: 6 additions & 0 deletions src/SignalsHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
*/
final class SignalsHandler
{
/**
* @var array<int, array<callable>>
*/
private $signals = array();

public function add($signal, $listener)
Expand Down Expand Up @@ -47,6 +50,9 @@ public function call($signal)
}
}

/**
* @return int
*/
public function count($signal)
{
if (!isset($this->signals[$signal])) {
Expand Down
13 changes: 11 additions & 2 deletions src/StreamSelectLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ final class StreamSelectLoop implements LoopInterface
private $running;
private $pcntl = false;
private $pcntlPoll = false;
/**
* @var SignalsHandler
*/
private $signals;

public function __construct()
Expand Down Expand Up @@ -183,7 +186,13 @@ public function run()

$this->timers->tick();

// Future-tick queue has pending callbacks ...
/**
* Future-tick queue has pending callbacks ...
*
*
* @link https://github.com/phpstan/phpstan/issues/10566
* @phpstan-ignore-next-line
*/
if (!$this->running || !$this->futureTickQueue->isEmpty()) {
$timeout = 0;

Expand Down Expand Up @@ -305,7 +314,7 @@ private function streamSelect(array &$read, array &$write, $timeout)
} catch (\Throwable $e) { // @codeCoverageIgnoreStart
\restore_error_handler();
throw $e;
} catch (\Exception $e) {
} catch (\Exception $e) { /** @phpstan-ignore-line */
\restore_error_handler();
throw $e;
} // @codeCoverageIgnoreEnd
Expand Down
9 changes: 0 additions & 9 deletions tests/ExtEventLoopTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,6 @@ public function createStream()
return $stream;
}

public function writeToStream($stream, $content)
{
if ('Linux' !== PHP_OS) {
return parent::writeToStream($stream, $content);
}

fwrite($stream, $content);
}

/**
* @group epoll-readable-error
*/
Expand Down
10 changes: 7 additions & 3 deletions tests/StreamSelectLoopTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public function testStreamSelectReportsWarningForStreamWithFilter()
$error = null;
$previous = set_error_handler(function ($_, $errstr) use (&$error) {
$error = $errstr;
return true;
});

try {
Expand All @@ -73,7 +74,9 @@ public function testStreamSelectReportsWarningForStreamWithFilter()

$this->assertNotNull($error);

$now = set_error_handler(function () { });
$now = set_error_handler(function () {
return true;
});
restore_error_handler();
$this->assertEquals($previous, $now);
}
Expand Down Expand Up @@ -114,7 +117,9 @@ public function testStreamSelectThrowsWhenCustomErrorHandlerThrowsForStreamWithF

$this->assertInstanceOf('RuntimeException', $e);

$now = set_error_handler(function () { });
$now = set_error_handler(function () {
return true;
});
restore_error_handler();
$this->assertEquals($previous, $now);
}
Expand Down Expand Up @@ -176,7 +181,6 @@ public function testSignalInterruptWithStream($signal)
$loop = $this->loop;
list($writeStream, $readStream) = $this->createSocketPair();
$loop->addReadStream($readStream, function ($stream) use ($loop) {
/** @var $loop LoopInterface */
$read = fgets($stream);
if ($read === "end loop\n") {
$loop->stop();
Expand Down
5 changes: 5 additions & 0 deletions tests/bin/12-undefined.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,9 @@
echo 'never';
});

/**
* We're ignore this line because the test using this file relies on the error caused by it.
*
* @phpstan-ignore-next-line
*/
$undefined->foo('bar');
5 changes: 5 additions & 0 deletions tests/bin/22-stop-uncaught.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
echo 'never';
});

/**
* Ignoring the next line until we raise the minimum PHP version to 7.1
*
* @phpstan-ignore-next-line
*/
set_exception_handler(function (Exception $e) {
echo 'Uncaught error occured' . PHP_EOL;
Loop::stop();
Expand Down

0 comments on commit eb61e23

Please sign in to comment.