Skip to content

Commit 8d34918

Browse files
committed
Check mixed return types and update to PHPStan level max
1 parent 61b4988 commit 8d34918

10 files changed

Lines changed: 67 additions & 28 deletions

examples/index.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
return htmlspecialchars_decode(htmlspecialchars($str, ENT_SUBSTITUTE | ENT_DISALLOWED, 'utf-8'));
2222
};
2323

24+
$name = $request->getAttribute('name');
25+
assert(is_string($name));
26+
2427
return React\Http\Message\Response::plaintext(
25-
"Hello " . $escape($request->getAttribute('name')) . "!\n"
28+
"Hello " . $escape($name) . "!\n"
2629
);
2730
});
2831

@@ -202,9 +205,10 @@
202205
});
203206

204207
$app->get('/location/{status:\d+}', function (Psr\Http\Message\ServerRequestInterface $request) {
205-
$statusCode = (int) $request->getAttribute('status');
208+
$statusCode = $request->getAttribute('status');
209+
assert(is_string($statusCode) && is_numeric($statusCode));
206210

207-
return new React\Http\Message\Response($statusCode, ['Location' => '/foobar']);
211+
return new React\Http\Message\Response((int) $statusCode, ['Location' => '/foobar']);
208212
});
209213

210214
$app->run();

phpstan.neon.dist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
parameters:
2-
level: 8
2+
level: max
33

44
paths:
55
- examples/

src/App.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,14 @@ private function runOnce(): void
319319
private function handleRequest(ServerRequestInterface $request)
320320
{
321321
$response = ($this->handler)($request);
322+
assert($response instanceof ResponseInterface || $response instanceof PromiseInterface || $response instanceof \Generator);
323+
322324
if ($response instanceof \Generator) {
323325
if ($response->valid()) {
324326
$response = $this->coroutine($response);
325327
} else {
326328
$response = $response->getReturn();
329+
assert($response instanceof ResponseInterface);
327330
}
328331
}
329332

@@ -341,6 +344,8 @@ private function coroutine(\Generator $generator): PromiseInterface
341344
}
342345

343346
$promise = $generator->current();
347+
assert($promise instanceof PromiseInterface);
348+
344349
$promise->then(function ($value) use ($generator, $next) {
345350
$generator->send($value);
346351
$next();

src/Container.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ public function getAccessLogHandler(): AccessLogHandler
118118
{
119119
if ($this->container instanceof ContainerInterface) {
120120
if ($this->container->has(AccessLogHandler::class)) {
121+
// @phpstan-ignore-next-line method return type will ensure correct type or throw `TypeError`
121122
return $this->container->get(AccessLogHandler::class);
122123
} else {
123124
return new AccessLogHandler();
@@ -131,6 +132,7 @@ public function getErrorHandler(): ErrorHandler
131132
{
132133
if ($this->container instanceof ContainerInterface) {
133134
if ($this->container->has(ErrorHandler::class)) {
135+
// @phpstan-ignore-next-line method return type will ensure correct type or throw `TypeError`
134136
return $this->container->get(ErrorHandler::class);
135137
} else {
136138
return new ErrorHandler();
@@ -140,7 +142,7 @@ public function getErrorHandler(): ErrorHandler
140142
}
141143

142144
/**
143-
* @template T
145+
* @template T of object
144146
* @param class-string<T> $name
145147
* @return T
146148
* @throws \BadMethodCallException if object of type $name can not be loaded
@@ -158,7 +160,7 @@ private function loadObject(string $name, int $depth = 64) /*: object (PHP 7.2+)
158160
// @phpstan-ignore-next-line because type of container value is explicitly checked after getting here
159161
$value = $this->loadObject($this->container[$name], $depth - 1);
160162
if (!$value instanceof $name) {
161-
throw new \BadMethodCallException('Factory for ' . $name . ' returned unexpected ' . (is_object($value) ? get_class($value) : gettype($value)));
163+
throw new \BadMethodCallException('Factory for ' . $name . ' returned unexpected ' . \get_class($value));
162164
}
163165

164166
$this->container[$name] = $value;

src/FilesystemHandler.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public function __construct(string $root)
6464
public function __invoke(ServerRequestInterface $request): ResponseInterface
6565
{
6666
$local = $request->getAttribute('path', '');
67+
assert(\is_string($local));
6768
$path = \rtrim($this->root . '/' . $local, '/');
6869

6970
// local path should not contain "./", "../", "//" or null bytes or start with slash

src/Io/FiberHandler.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public function __invoke(ServerRequestInterface $request, callable $next): mixed
5656
$fiber->start();
5757
if ($fiber->isTerminated()) {
5858
/** @throws void because fiber is known to have terminated successfully */
59+
/** @var ResponseInterface|PromiseInterface|\Generator */
5960
return $fiber->getReturn();
6061
}
6162

tests/AppMiddlewareTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use FrameworkX\AccessLogHandler;
66
use FrameworkX\App;
77
use FrameworkX\Io\FiberHandler;
8+
use FrameworkX\Io\MiddlewareHandler;
89
use FrameworkX\Io\RouteHandler;
910
use PHPUnit\Framework\TestCase;
1011
use Psr\Http\Message\ResponseInterface;
@@ -217,7 +218,7 @@ public function testMiddlewareCallsNextWithModifiedRequestReturnsResponseFromRou
217218
[
218219
'Content-Type' => 'text/html'
219220
],
220-
$request->getAttribute('name')
221+
$request->getAttribute('name') // @phpstan-ignore-line known to return string
221222
);
222223
};
223224

@@ -786,10 +787,12 @@ private function createAppWithoutLogger(...$middleware): App
786787
$ref = new \ReflectionProperty($app, 'handler');
787788
$ref->setAccessible(true);
788789
$middleware = $ref->getValue($app);
790+
assert($middleware instanceof MiddlewareHandler);
789791

790792
$ref = new \ReflectionProperty($middleware, 'handlers');
791793
$ref->setAccessible(true);
792794
$handlers = $ref->getValue($middleware);
795+
assert(is_array($handlers));
793796

794797
if (PHP_VERSION_ID >= 80100) {
795798
$first = array_shift($handlers);

tests/AppTest.php

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,12 @@ public function testConstructWithMiddlewareAssignsGivenMiddleware(): void
4646
$ref = new ReflectionProperty($app, 'handler');
4747
$ref->setAccessible(true);
4848
$handler = $ref->getValue($app);
49+
assert($handler instanceof MiddlewareHandler);
4950

50-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
5151
$ref = new ReflectionProperty($handler, 'handlers');
5252
$ref->setAccessible(true);
5353
$handlers = $ref->getValue($handler);
54+
assert(is_array($handlers));
5455

5556
if (PHP_VERSION_ID >= 80100) {
5657
$first = array_shift($handlers);
@@ -78,11 +79,12 @@ public function testConstructWithContainerAssignsDefaultHandlersAndContainerForR
7879
$ref = new ReflectionProperty($app, 'handler');
7980
$ref->setAccessible(true);
8081
$handler = $ref->getValue($app);
82+
assert($handler instanceof MiddlewareHandler);
8183

82-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
8384
$ref = new ReflectionProperty($handler, 'handlers');
8485
$ref->setAccessible(true);
8586
$handlers = $ref->getValue($handler);
87+
assert(is_array($handlers));
8688

8789
if (PHP_VERSION_ID >= 80100) {
8890
$first = array_shift($handlers);
@@ -112,11 +114,12 @@ public function testConstructWithContainerAndMiddlewareClassNameAssignsCallableF
112114
$ref = new ReflectionProperty($app, 'handler');
113115
$ref->setAccessible(true);
114116
$handler = $ref->getValue($app);
117+
assert($handler instanceof MiddlewareHandler);
115118

116-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
117119
$ref = new ReflectionProperty($handler, 'handlers');
118120
$ref->setAccessible(true);
119121
$handlers = $ref->getValue($handler);
122+
assert(is_array($handlers));
120123

121124
if (PHP_VERSION_ID >= 80100) {
122125
$first = array_shift($handlers);
@@ -144,11 +147,12 @@ public function testConstructWithErrorHandlerOnlyAssignsErrorHandlerAfterDefault
144147
$ref = new ReflectionProperty($app, 'handler');
145148
$ref->setAccessible(true);
146149
$handler = $ref->getValue($app);
150+
assert($handler instanceof MiddlewareHandler);
147151

148-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
149152
$ref = new ReflectionProperty($handler, 'handlers');
150153
$ref->setAccessible(true);
151154
$handlers = $ref->getValue($handler);
155+
assert(is_array($handlers));
152156

153157
if (PHP_VERSION_ID >= 80100) {
154158
$first = array_shift($handlers);
@@ -168,11 +172,12 @@ public function testConstructWithErrorHandlerClassOnlyAssignsErrorHandlerAfterDe
168172
$ref = new ReflectionProperty($app, 'handler');
169173
$ref->setAccessible(true);
170174
$handler = $ref->getValue($app);
175+
assert($handler instanceof MiddlewareHandler);
171176

172-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
173177
$ref = new ReflectionProperty($handler, 'handlers');
174178
$ref->setAccessible(true);
175179
$handlers = $ref->getValue($handler);
180+
assert(is_array($handlers));
176181

177182
if (PHP_VERSION_ID >= 80100) {
178183
$first = array_shift($handlers);
@@ -194,11 +199,12 @@ public function testConstructWithContainerAndErrorHandlerAssignsErrorHandlerAfte
194199
$ref = new ReflectionProperty($app, 'handler');
195200
$ref->setAccessible(true);
196201
$handler = $ref->getValue($app);
202+
assert($handler instanceof MiddlewareHandler);
197203

198-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
199204
$ref = new ReflectionProperty($handler, 'handlers');
200205
$ref->setAccessible(true);
201206
$handlers = $ref->getValue($handler);
207+
assert(is_array($handlers));
202208

203209
if (PHP_VERSION_ID >= 80100) {
204210
$first = array_shift($handlers);
@@ -223,11 +229,12 @@ public function testConstructWithContainerAndErrorHandlerClassAssignsErrorHandle
223229
$ref = new ReflectionProperty($app, 'handler');
224230
$ref->setAccessible(true);
225231
$handler = $ref->getValue($app);
232+
assert($handler instanceof MiddlewareHandler);
226233

227-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
228234
$ref = new ReflectionProperty($handler, 'handlers');
229235
$ref->setAccessible(true);
230236
$handlers = $ref->getValue($handler);
237+
assert(is_array($handlers));
231238

232239
if (PHP_VERSION_ID >= 80100) {
233240
$first = array_shift($handlers);
@@ -255,11 +262,12 @@ public function testConstructWithMultipleContainersAndErrorHandlerClassAssignsEr
255262
$ref = new ReflectionProperty($app, 'handler');
256263
$ref->setAccessible(true);
257264
$handler = $ref->getValue($app);
265+
assert($handler instanceof MiddlewareHandler);
258266

259-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
260267
$ref = new ReflectionProperty($handler, 'handlers');
261268
$ref->setAccessible(true);
262269
$handlers = $ref->getValue($handler);
270+
assert(is_array($handlers));
263271

264272
if (PHP_VERSION_ID >= 80100) {
265273
$first = array_shift($handlers);
@@ -288,11 +296,12 @@ public function testConstructWithMultipleContainersAndMiddlewareAssignsErrorHand
288296
$ref = new ReflectionProperty($app, 'handler');
289297
$ref->setAccessible(true);
290298
$handler = $ref->getValue($app);
299+
assert($handler instanceof MiddlewareHandler);
291300

292-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
293301
$ref = new ReflectionProperty($handler, 'handlers');
294302
$ref->setAccessible(true);
295303
$handlers = $ref->getValue($handler);
304+
assert(is_array($handlers));
296305

297306
if (PHP_VERSION_ID >= 80100) {
298307
$first = array_shift($handlers);
@@ -316,11 +325,12 @@ public function testConstructWithMiddlewareAndErrorHandlerAssignsGivenErrorHandl
316325
$ref = new ReflectionProperty($app, 'handler');
317326
$ref->setAccessible(true);
318327
$handler = $ref->getValue($app);
328+
assert($handler instanceof MiddlewareHandler);
319329

320-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
321330
$ref = new ReflectionProperty($handler, 'handlers');
322331
$ref->setAccessible(true);
323332
$handlers = $ref->getValue($handler);
333+
assert(is_array($handlers));
324334

325335
if (PHP_VERSION_ID >= 80100) {
326336
$first = array_shift($handlers);
@@ -356,11 +366,12 @@ public function testConstructWithMultipleContainersAndMiddlewareAndErrorHandlerC
356366
$ref = new ReflectionProperty($app, 'handler');
357367
$ref->setAccessible(true);
358368
$handler = $ref->getValue($app);
369+
assert($handler instanceof MiddlewareHandler);
359370

360-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
361371
$ref = new ReflectionProperty($handler, 'handlers');
362372
$ref->setAccessible(true);
363373
$handlers = $ref->getValue($handler);
374+
assert(is_array($handlers));
364375

365376
if (PHP_VERSION_ID >= 80100) {
366377
$first = array_shift($handlers);
@@ -385,11 +396,12 @@ public function testConstructWithAccessLogHandlerAndErrorHandlerAssignsHandlersA
385396
$ref = new ReflectionProperty($app, 'handler');
386397
$ref->setAccessible(true);
387398
$handler = $ref->getValue($app);
399+
assert($handler instanceof MiddlewareHandler);
388400

389-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
390401
$ref = new ReflectionProperty($handler, 'handlers');
391402
$ref->setAccessible(true);
392403
$handlers = $ref->getValue($handler);
404+
assert(is_array($handlers));
393405

394406
if (PHP_VERSION_ID >= 80100) {
395407
$first = array_shift($handlers);
@@ -409,11 +421,12 @@ public function testConstructWithAccessLogHandlerClassAndErrorHandlerClassAssign
409421
$ref = new ReflectionProperty($app, 'handler');
410422
$ref->setAccessible(true);
411423
$handler = $ref->getValue($app);
424+
assert($handler instanceof MiddlewareHandler);
412425

413-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
414426
$ref = new ReflectionProperty($handler, 'handlers');
415427
$ref->setAccessible(true);
416428
$handlers = $ref->getValue($handler);
429+
assert(is_array($handlers));
417430

418431
if (PHP_VERSION_ID >= 80100) {
419432
$first = array_shift($handlers);
@@ -440,11 +453,12 @@ public function testConstructWithContainerAndAccessLogHandlerClassAndErrorHandle
440453
$ref = new ReflectionProperty($app, 'handler');
441454
$ref->setAccessible(true);
442455
$handler = $ref->getValue($app);
456+
assert($handler instanceof MiddlewareHandler);
443457

444-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
445458
$ref = new ReflectionProperty($handler, 'handlers');
446459
$ref->setAccessible(true);
447460
$handlers = $ref->getValue($handler);
461+
assert(is_array($handlers));
448462

449463
if (PHP_VERSION_ID >= 80100) {
450464
$first = array_shift($handlers);
@@ -468,11 +482,12 @@ public function testConstructWithMiddlewareBeforeAccessLogHandlerAndErrorHandler
468482
$ref = new ReflectionProperty($app, 'handler');
469483
$ref->setAccessible(true);
470484
$handler = $ref->getValue($app);
485+
assert($handler instanceof MiddlewareHandler);
471486

472-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
473487
$ref = new ReflectionProperty($handler, 'handlers');
474488
$ref->setAccessible(true);
475489
$handlers = $ref->getValue($handler);
490+
assert(is_array($handlers));
476491

477492
if (PHP_VERSION_ID >= 80100) {
478493
$first = array_shift($handlers);
@@ -505,11 +520,12 @@ public function testConstructWithMultipleContainersAndAccessLogHandlerClassAndEr
505520
$ref = new ReflectionProperty($app, 'handler');
506521
$ref->setAccessible(true);
507522
$handler = $ref->getValue($app);
523+
assert($handler instanceof MiddlewareHandler);
508524

509-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
510525
$ref = new ReflectionProperty($handler, 'handlers');
511526
$ref->setAccessible(true);
512527
$handlers = $ref->getValue($handler);
528+
assert(is_array($handlers));
513529

514530
if (PHP_VERSION_ID >= 80100) {
515531
$first = array_shift($handlers);
@@ -543,11 +559,12 @@ public function testConstructWithMultipleContainersAndMiddlewareAssignsDefaultHa
543559
$ref = new ReflectionProperty($app, 'handler');
544560
$ref->setAccessible(true);
545561
$handler = $ref->getValue($app);
562+
assert($handler instanceof MiddlewareHandler);
546563

547-
$this->assertInstanceOf(MiddlewareHandler::class, $handler);
548564
$ref = new ReflectionProperty($handler, 'handlers');
549565
$ref->setAccessible(true);
550566
$handlers = $ref->getValue($handler);
567+
assert(is_array($handlers));
551568

552569
if (PHP_VERSION_ID >= 80100) {
553570
$first = array_shift($handlers);
@@ -1458,6 +1475,7 @@ public function testHandleRequestWithMatchingRouteAndRouteVariablesReturnsRespon
14581475

14591476
$app->get('/users/{name}', function (ServerRequestInterface $request) {
14601477
$name = $request->getAttribute('name');
1478+
assert(is_string($name));
14611479

14621480
return new Response(
14631481
200,
@@ -2091,10 +2109,12 @@ private function createAppWithoutLogger(): App
20912109
$ref = new \ReflectionProperty($app, 'handler');
20922110
$ref->setAccessible(true);
20932111
$middleware = $ref->getValue($app);
2112+
assert($middleware instanceof MiddlewareHandler);
20942113

20952114
$ref = new \ReflectionProperty($middleware, 'handlers');
20962115
$ref->setAccessible(true);
20972116
$handlers = $ref->getValue($middleware);
2117+
assert(is_array($handlers));
20982118

20992119
if (PHP_VERSION_ID >= 80100) {
21002120
$first = array_shift($handlers);

0 commit comments

Comments
 (0)