Skip to content

Commit ae8efe4

Browse files
committed
[WIP][3.x] Introduce PHPStan
Full commit message will follow
1 parent 229fb29 commit ae8efe4

13 files changed

+125
-18
lines changed

.github/workflows/ci.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,36 @@ jobs:
120120
uses: docker://hhvm/hhvm:3.30-lts-latest
121121
with:
122122
args: hhvm vendor/bin/phpunit
123+
124+
PHPStan:
125+
name: PHPStan (PHP ${{ matrix.php }})
126+
runs-on: ubuntu-22.04
127+
strategy:
128+
matrix:
129+
php:
130+
- 8.3
131+
- 8.2
132+
- 8.1
133+
- 8.0
134+
- 7.4
135+
- 7.3
136+
- 7.2
137+
- 7.1
138+
steps:
139+
- uses: actions/checkout@v4
140+
- uses: shivammathur/setup-php@v2
141+
with:
142+
php-version: ${{ matrix.php }}
143+
coverage: none
144+
ini-file: development
145+
ini-values: disable_functions='' # do not disable PCNTL functions on PHP < 8.1
146+
extensions: sockets, pcntl ${{ matrix.php >= 5.6 && ', event' || '' }} ${{ matrix.php >= 5.4 && ', ev' || '' }}
147+
env:
148+
fail-fast: true # fail step if any extension can not be installed
149+
- name: Install ext-uv on PHP 7+
150+
run: |
151+
sudo apt-get update -q && sudo apt-get install libuv1-dev
152+
echo "yes" | sudo pecl install ${{ matrix.php >= 8.0 && 'uv-0.3.0' || 'uv-0.2.4' }}
153+
php -m | grep -q uv || echo "extension=uv.so" >> "$(php -r 'echo php_ini_loaded_file();')"
154+
- run: composer install
155+
- run: vendor/bin/phpstan

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"php": ">=5.3.0"
3030
},
3131
"require-dev": {
32+
"phpstan/phpstan": "^1",
3233
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36"
3334
},
3435
"suggest": {

phpstan.neon.dist

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
parameters:
2+
level: max
3+
4+
paths:
5+
- src/
6+
- tests/
7+
8+
# ignoreErrors:
9+
# - '#type specified#'
10+
# - '#expects resource, resource\|false given#'

src/ExtEvLoop.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class ExtEvLoop implements LoopInterface
3434
private $futureTickQueue;
3535

3636
/**
37-
* @var SplObjectStorage
37+
* @var SplObjectStorage<TimerInterface, \EvTimer>
3838
*/
3939
private $timers;
4040

@@ -192,13 +192,21 @@ public function run()
192192
$this->futureTickQueue->tick();
193193

194194
$hasPendingCallbacks = !$this->futureTickQueue->isEmpty();
195+
/**
196+
* @link https://github.com/phpstan/phpstan/issues/10566
197+
* @phpstan-ignore-next-line
198+
*/
195199
$wasJustStopped = !$this->running;
196200
$nothingLeftToDo = !$this->readStreams
197201
&& !$this->writeStreams
198202
&& !$this->timers->count()
199203
&& $this->signals->isEmpty();
200204

201205
$flags = Ev::RUN_ONCE;
206+
/**
207+
* @link https://github.com/phpstan/phpstan/issues/10566
208+
* @phpstan-ignore-next-line
209+
*/
202210
if ($wasJustStopped || $hasPendingCallbacks) {
203211
$flags |= Ev::RUN_NOWAIT;
204212
} elseif ($nothingLeftToDo) {
@@ -222,11 +230,13 @@ public function __destruct()
222230
}
223231

224232
foreach ($this->readStreams as $key => $stream) {
225-
$this->removeReadStream($key);
233+
$this->readStreams[$key]->stop();
234+
unset($this->readStreams[$key]);
226235
}
227236

228237
foreach ($this->writeStreams as $key => $stream) {
229-
$this->removeWriteStream($key);
238+
$this->readStreams[$key]->stop();
239+
unset($this->readStreams[$key]);
230240
}
231241
}
232242

src/ExtEventLoop.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,10 @@ public function run()
196196
$this->futureTickQueue->tick();
197197

198198
$flags = EventBase::LOOP_ONCE;
199+
/**
200+
* @link https://github.com/phpstan/phpstan/issues/10566
201+
* @phpstan-ignore-next-line
202+
*/
199203
if (!$this->running || !$this->futureTickQueue->isEmpty()) {
200204
$flags |= EventBase::LOOP_NONBLOCK;
201205
} elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count() && $this->signals->isEmpty()) {

src/ExtUvLoop.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ public function run()
213213
$this->futureTickQueue->tick();
214214

215215
$hasPendingCallbacks = !$this->futureTickQueue->isEmpty();
216+
/**
217+
* @link https://github.com/phpstan/phpstan/issues/10566
218+
* @phpstan-ignore-next-line
219+
*/
216220
$wasJustStopped = !$this->running;
217221
$nothingLeftToDo = !$this->readStreams
218222
&& !$this->writeStreams
@@ -223,12 +227,20 @@ public function run()
223227
// otherwise use UV::RUN_NOWAIT.
224228
// @link http://docs.libuv.org/en/v1.x/loop.html#c.uv_run
225229
$flags = \UV::RUN_ONCE;
230+
/**
231+
* @link https://github.com/phpstan/phpstan/issues/10566
232+
* @phpstan-ignore-next-line
233+
*/
226234
if ($wasJustStopped || $hasPendingCallbacks) {
227235
$flags = \UV::RUN_NOWAIT;
228236
} elseif ($nothingLeftToDo) {
229237
break;
230238
}
231239

240+
/**
241+
* @link https://github.com/JetBrains/phpstorm-stubs/pull/1614
242+
* @phpstan-ignore-next-line
243+
*/
232244
\uv_run($this->uv, $flags);
233245
}
234246
}
@@ -261,6 +273,10 @@ private function removeStream($stream)
261273
if (!isset($this->readStreams[(int) $stream])
262274
&& !isset($this->writeStreams[(int) $stream])) {
263275
\uv_poll_stop($this->streamEvents[(int) $stream]);
276+
/**
277+
* @link https://github.com/JetBrains/phpstorm-stubs/pull/1615
278+
* @phpstan-ignore-next-line
279+
*/
264280
\uv_close($this->streamEvents[(int) $stream]);
265281
unset($this->streamEvents[(int) $stream]);
266282
return;

src/Loop.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public static function addReadStream($stream, $listener)
8787
if (self::$instance === null) {
8888
self::get();
8989
}
90+
assert(self::$instance instanceof LoopInterface);
9091
self::$instance->addReadStream($stream, $listener);
9192
}
9293

@@ -105,6 +106,9 @@ public static function addWriteStream($stream, $listener)
105106
if (self::$instance === null) {
106107
self::get();
107108
}
109+
110+
assert(self::$instance instanceof LoopInterface);
111+
108112
self::$instance->addWriteStream($stream, $listener);
109113
}
110114

@@ -150,6 +154,9 @@ public static function addTimer($interval, $callback)
150154
if (self::$instance === null) {
151155
self::get();
152156
}
157+
158+
assert(self::$instance instanceof LoopInterface);
159+
153160
return self::$instance->addTimer($interval, $callback);
154161
}
155162

@@ -167,6 +174,9 @@ public static function addPeriodicTimer($interval, $callback)
167174
if (self::$instance === null) {
168175
self::get();
169176
}
177+
178+
assert(self::$instance instanceof LoopInterface);
179+
170180
return self::$instance->addPeriodicTimer($interval, $callback);
171181
}
172182

@@ -198,6 +208,8 @@ public static function futureTick($listener)
198208
self::get();
199209
}
200210

211+
assert(self::$instance instanceof LoopInterface);
212+
201213
self::$instance->futureTick($listener);
202214
}
203215

@@ -216,6 +228,8 @@ public static function addSignal($signal, $listener)
216228
self::get();
217229
}
218230

231+
assert(self::$instance instanceof LoopInterface);
232+
219233
self::$instance->addSignal($signal, $listener);
220234
}
221235

@@ -247,6 +261,8 @@ public static function run()
247261
self::get();
248262
}
249263

264+
assert(self::$instance instanceof LoopInterface);
265+
250266
self::$instance->run();
251267
}
252268

src/SignalsHandler.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ public function call($signal)
4747
}
4848
}
4949

50+
/**
51+
* @phpstan-impure
52+
*/
5053
public function count($signal)
5154
{
5255
if (!isset($this->signals[$signal])) {

src/StreamSelectLoop.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ final class StreamSelectLoop implements LoopInterface
6363
private $running;
6464
private $pcntl = false;
6565
private $pcntlPoll = false;
66+
/**
67+
* @var SignalsHandler
68+
*/
6669
private $signals;
6770

6871
public function __construct()
@@ -183,7 +186,13 @@ public function run()
183186

184187
$this->timers->tick();
185188

186-
// Future-tick queue has pending callbacks ...
189+
/**
190+
* Future-tick queue has pending callbacks ...
191+
*
192+
*
193+
* @link https://github.com/phpstan/phpstan/issues/10566
194+
* @phpstan-ignore-next-line
195+
*/
187196
if (!$this->running || !$this->futureTickQueue->isEmpty()) {
188197
$timeout = 0;
189198

@@ -286,7 +295,7 @@ private function streamSelect(array &$read, array &$write, $timeout)
286295
}
287296
}
288297

289-
/** @var ?callable $previous */
298+
/** @var ?(callable(int, string, string, int): bool) $previous */
290299
$previous = \set_error_handler(function ($errno, $errstr) use (&$previous) {
291300
// suppress warnings that occur when `stream_select()` is interrupted by a signal
292301
// PHP defines `EINTR` through `ext-sockets` or `ext-pcntl`, otherwise use common default (Linux & Mac)
@@ -305,7 +314,7 @@ private function streamSelect(array &$read, array &$write, $timeout)
305314
} catch (\Throwable $e) { // @codeCoverageIgnoreStart
306315
\restore_error_handler();
307316
throw $e;
308-
} catch (\Exception $e) {
317+
} catch (\Exception $e) { /** @phpstan-ignore-line */
309318
\restore_error_handler();
310319
throw $e;
311320
} // @codeCoverageIgnoreEnd

tests/ExtEventLoopTest.php

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,6 @@ public function createStream()
6262
return $stream;
6363
}
6464

65-
public function writeToStream($stream, $content)
66-
{
67-
if ('Linux' !== PHP_OS) {
68-
return parent::writeToStream($stream, $content);
69-
}
70-
71-
fwrite($stream, $content);
72-
}
73-
7465
/**
7566
* @group epoll-readable-error
7667
*/

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy