Skip to content

Commit 20ae0fc

Browse files
authored
Merge pull request #36 from gsteel/feature/psalm-hack
Improve psalm type inference, add missing type annotations
2 parents c8aad67 + 3ad3449 commit 20ae0fc

20 files changed

+150
-205
lines changed

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
"laminas/laminas-coding-standard": "~2.5.0",
5252
"phpunit/phpunit": "^9.5.27",
5353
"psalm/plugin-phpunit": "^0.18.4",
54-
"vimeo/psalm": "^5.2"
54+
"vimeo/psalm": "^5.4"
5555
},
5656
"autoload": {
5757
"psr-4": {

composer.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

psalm-baseline.xml

+3-144
Original file line numberDiff line numberDiff line change
@@ -1,157 +1,16 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<files psalm-version="5.2.0@fb685a16df3050d4c18d8a4100fe83abe6458cba">
33
<file src="src/ProblemDetailsMiddleware.php">
4-
<MissingClosureParamType occurrences="1">
5-
<code>$listener</code>
6-
</MissingClosureParamType>
7-
<MixedArgumentTypeCoercion occurrences="1">
4+
<InvalidArgument occurrences="1">
85
<code>$this-&gt;createErrorHandler()</code>
9-
</MixedArgumentTypeCoercion>
10-
<MixedFunctionCall occurrences="1">
11-
<code>$listener($error, $request, $response)</code>
12-
</MixedFunctionCall>
13-
<MixedPropertyTypeCoercion occurrences="1">
14-
<code>$this-&gt;listeners</code>
15-
</MixedPropertyTypeCoercion>
16-
</file>
17-
<file src="src/ProblemDetailsMiddlewareFactory.php">
18-
<MixedArgument occurrences="1">
19-
<code>$container-&gt;get(ProblemDetailsResponseFactory::class)</code>
20-
</MixedArgument>
21-
</file>
22-
<file src="src/ProblemDetailsNotFoundHandlerFactory.php">
23-
<MixedArgument occurrences="1">
24-
<code>$container-&gt;get(ProblemDetailsResponseFactory::class)</code>
25-
</MixedArgument>
6+
</InvalidArgument>
267
</file>
278
<file src="src/ProblemDetailsResponseFactory.php">
28-
<MissingClosureParamType occurrences="1">
29-
<code>$value</code>
30-
</MissingClosureParamType>
31-
<MixedArgument occurrences="4">
32-
<code>$content</code>
9+
<MixedArgument occurrences="1">
3310
<code>$mediaType-&gt;getValue()</code>
34-
<code>$payload['status']</code>
35-
<code>$payload['status']</code>
3611
</MixedArgument>
37-
<MixedAssignment occurrences="3">
38-
<code>$content</code>
39-
<code>$return[$key]</code>
40-
<code>$value</code>
41-
</MixedAssignment>
42-
<MixedInferredReturnType occurrences="1">
43-
<code>ResponseInterface</code>
44-
</MixedInferredReturnType>
45-
<MixedReturnStatement occurrences="1">
46-
<code>$this-&gt;getResponseGenerator($request)($payload)</code>
47-
</MixedReturnStatement>
4812
<UndefinedInterfaceMethod occurrences="1">
4913
<code>getValue</code>
5014
</UndefinedInterfaceMethod>
5115
</file>
52-
<file src="src/ProblemDetailsResponseFactoryFactory.php">
53-
<MixedArgument occurrences="4">
54-
<code>$defaultTypesMap</code>
55-
<code>$includeThrowableDetail</code>
56-
<code>$includeThrowableDetail</code>
57-
<code>$jsonFlags</code>
58-
</MixedArgument>
59-
<MixedAssignment occurrences="3">
60-
<code>$defaultTypesMap</code>
61-
<code>$includeThrowableDetail</code>
62-
<code>$jsonFlags</code>
63-
</MixedAssignment>
64-
</file>
65-
<file src="test/ConfigProviderTest.php">
66-
<MixedArgument occurrences="4">
67-
<code>$dependencies</code>
68-
<code>$factories</code>
69-
<code>$factories</code>
70-
<code>$factories</code>
71-
</MixedArgument>
72-
<MixedArrayAccess occurrences="3">
73-
<code>$dependencies['factories']</code>
74-
<code>$factories[ProblemDetailsMiddleware::class]</code>
75-
<code>$factories[ProblemDetailsResponseFactory::class]</code>
76-
</MixedArrayAccess>
77-
<MixedAssignment occurrences="2">
78-
<code>$dependencies</code>
79-
<code>$factories</code>
80-
</MixedAssignment>
81-
</file>
82-
<file src="test/Exception/ProblemDetailsExceptionInterfaceTest.php">
83-
<MixedAssignment occurrences="1">
84-
<code>$problem</code>
85-
</MixedAssignment>
86-
</file>
87-
<file src="test/ProblemDetailsAssertionsTrait.php">
88-
<MissingClosureParamType occurrences="1">
89-
<code>$item</code>
90-
</MissingClosureParamType>
91-
<MixedArgument occurrences="1">
92-
<code>$payload</code>
93-
</MixedArgument>
94-
<MixedAssignment occurrences="3">
95-
<code>$data</code>
96-
<code>$payload</code>
97-
<code>$value</code>
98-
</MixedAssignment>
99-
</file>
100-
<file src="test/ProblemDetailsMiddlewareFactoryTest.php">
101-
<MissingReturnType occurrences="1">
102-
<code>testRaisesExceptionWhenProblemDetailsResponseFactoryServiceIsNotAvailable</code>
103-
</MissingReturnType>
104-
</file>
105-
<file src="test/ProblemDetailsMiddlewareTest.php">
106-
<MissingClosureParamType occurrences="3">
107-
<code>$error</code>
108-
<code>$request</code>
109-
<code>$response</code>
110-
</MissingClosureParamType>
111-
<MixedInferredReturnType occurrences="1">
112-
<code>array</code>
113-
</MixedInferredReturnType>
114-
</file>
115-
<file src="test/ProblemDetailsNotFoundHandlerFactoryTest.php">
116-
<MissingReturnType occurrences="1">
117-
<code>testRaisesExceptionWhenProblemDetailsResponseFactoryServiceIsNotAvailable</code>
118-
</MissingReturnType>
119-
</file>
120-
<file src="test/ProblemDetailsNotFoundHandlerTest.php">
121-
<MixedInferredReturnType occurrences="1">
122-
<code>array</code>
123-
</MixedInferredReturnType>
124-
</file>
125-
<file src="test/ProblemDetailsResponseFactoryFactoryTest.php">
126-
<MissingReturnType occurrences="3">
127-
<code>assertResponseFactoryReturns</code>
128-
<code>testLackOfResponseServiceResultsInException</code>
129-
<code>testNonCallableResponseServiceResultsInException</code>
130-
</MissingReturnType>
131-
<MixedOperand occurrences="1">
132-
<code>$jsonFlags-&gt;getValue($factory)</code>
133-
</MixedOperand>
134-
</file>
135-
<file src="test/ProblemDetailsResponseFactoryTest.php">
136-
<MixedArgument occurrences="2">
137-
<code>$payload['exception']</code>
138-
<code>$payload['foo']</code>
139-
</MixedArgument>
140-
<MixedArrayAccess occurrences="6">
141-
<code>$payload['exception']['code']</code>
142-
<code>$payload['exception']['message']</code>
143-
<code>$payload['exception']['stack']</code>
144-
<code>$payload['exception']['stack'][0]['code']</code>
145-
<code>$payload['exception']['stack'][0]['message']</code>
146-
<code>$payload['type']</code>
147-
</MixedArrayAccess>
148-
<MixedAssignment occurrences="1">
149-
<code>$payload</code>
150-
</MixedAssignment>
151-
</file>
152-
<file src="test/TestAsset/RuntimeException.php">
153-
<MixedAssignment occurrences="1">
154-
<code>$this-&gt;code</code>
155-
</MixedAssignment>
156-
</file>
15716
</files>

src/Exception/CommonProblemDetailsExceptionTrait.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ trait CommonProblemDetailsExceptionTrait
3434
/** @var string */
3535
private $type;
3636

37-
/** @var array */
37+
/** @var array<string, mixed> */
3838
private $additional = [];
3939

4040
public function getStatus(): int
@@ -57,6 +57,7 @@ public function getDetail(): string
5757
return $this->detail;
5858
}
5959

60+
/** @return array<string, mixed> */
6061
public function getAdditionalData(): array
6162
{
6263
return $this->additional;

src/Exception/ProblemDetailsExceptionInterface.php

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public function getTitle(): string;
2020

2121
public function getDetail(): string;
2222

23+
/** @return array<string, mixed> */
2324
public function getAdditionalData(): array;
2425

2526
/**

src/ProblemDetailsMiddleware.php

+8-5
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55
namespace Mezzio\ProblemDetails;
66

77
use ErrorException;
8-
use Mezzio\ProblemDetails\ProblemDetailsResponseFactory;
98
use Negotiation\Negotiator;
9+
use Psr\Http\Message\RequestInterface;
1010
use Psr\Http\Message\ResponseInterface;
1111
use Psr\Http\Message\ServerRequestInterface;
1212
use Psr\Http\Server\MiddlewareInterface;
1313
use Psr\Http\Server\RequestHandlerInterface;
1414
use Throwable;
1515

16-
use function array_walk;
1716
use function error_reporting;
1817
use function in_array;
1918
use function restore_error_handler;
@@ -25,7 +24,7 @@
2524
*/
2625
class ProblemDetailsMiddleware implements MiddlewareInterface
2726
{
28-
/** @var callable[] */
27+
/** @var list<callable(Throwable, RequestInterface, ResponseInterface): void> */
2928
private array $listeners = [];
3029

3130
public function __construct(private ProblemDetailsResponseFactory $responseFactory)
@@ -67,6 +66,8 @@ public function process(ServerRequestInterface $request, RequestHandlerInterface
6766
* These instances are all immutable, and the return values of
6867
* listeners are ignored; use listeners for reporting purposes
6968
* only.
69+
*
70+
* @param callable(Throwable, RequestInterface, ResponseInterface): void $listener
7071
*/
7172
public function attachListener(callable $listener): void
7273
{
@@ -94,6 +95,8 @@ private function canActAsErrorHandler(ServerRequestInterface $request): bool
9495
* Creates and returns a callable error handler that raises exceptions.
9596
*
9697
* Only raises exceptions for errors that are within the error_reporting mask.
98+
*
99+
* @return callable(int, string, string, int): void
97100
*/
98101
private function createErrorHandler(): callable
99102
{
@@ -122,8 +125,8 @@ private function triggerListeners(
122125
ServerRequestInterface $request,
123126
ResponseInterface $response
124127
): void {
125-
array_walk($this->listeners, static function ($listener) use ($error, $request, $response): void {
128+
foreach ($this->listeners as $listener) {
126129
$listener($error, $request, $response);
127-
});
130+
}
128131
}
129132
}

src/ProblemDetailsMiddlewareFactory.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@
66

77
use Psr\Container\ContainerInterface;
88

9+
use function assert;
10+
911
class ProblemDetailsMiddlewareFactory
1012
{
1113
public function __invoke(ContainerInterface $container): ProblemDetailsMiddleware
1214
{
13-
return new ProblemDetailsMiddleware($container->get(ProblemDetailsResponseFactory::class));
15+
$responseFactory = $container->get(ProblemDetailsResponseFactory::class);
16+
assert($responseFactory instanceof ProblemDetailsResponseFactory);
17+
18+
return new ProblemDetailsMiddleware($responseFactory);
1419
}
1520
}

src/ProblemDetailsNotFoundHandlerFactory.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,15 @@
66

77
use Psr\Container\ContainerInterface;
88

9+
use function assert;
10+
911
class ProblemDetailsNotFoundHandlerFactory
1012
{
1113
public function __invoke(ContainerInterface $container): ProblemDetailsNotFoundHandler
1214
{
13-
return new ProblemDetailsNotFoundHandler($container->get(ProblemDetailsResponseFactory::class));
15+
$responseFactory = $container->get(ProblemDetailsResponseFactory::class);
16+
assert($responseFactory instanceof ProblemDetailsResponseFactory);
17+
18+
return new ProblemDetailsNotFoundHandler($responseFactory);
1419
}
1520
}

0 commit comments

Comments
 (0)