Skip to content

Commit f86709c

Browse files
Ignored errors: simplify schema, validate in ContainerFactory
Co-authored-by: Ondrej Mirtes <[email protected]>
1 parent e9556fb commit f86709c

File tree

9 files changed

+123
-35
lines changed

9 files changed

+123
-35
lines changed

conf/parametersSchema.neon

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -111,42 +111,16 @@ parametersSchema:
111111
ignoreErrors: listOf(
112112
anyOf(
113113
string(),
114-
structure([
115-
?messages: listOf(string())
116-
?identifier: string()
117-
?identifiers: listOf(string())
118-
?path: string()
119-
?reportUnmatched: bool()
120-
]),
121114
structure([
122115
?message: string()
116+
?messages: listOf(string())
123117
?identifier: string()
124118
?identifiers: listOf(string())
125119
?path: string()
120+
?paths: listOf(string())
121+
?count: int()
126122
?reportUnmatched: bool()
127123
]),
128-
structure([
129-
?message: string()
130-
count: int()
131-
path: string()
132-
?identifier: string()
133-
?identifiers: listOf(string())
134-
?reportUnmatched: bool()
135-
]),
136-
structure([
137-
?message: string()
138-
paths: listOf(string())
139-
?identifier: string()
140-
?identifiers: listOf(string())
141-
?reportUnmatched: bool()
142-
]),
143-
structure([
144-
?messages: listOf(string())
145-
paths: listOf(string())
146-
?identifier: string()
147-
?identifiers: listOf(string())
148-
?reportUnmatched: bool()
149-
])
150124
)
151125
)
152126
internalErrorsCountLimit: int()

src/DependencyInjection/ContainerFactory.php

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,22 @@
3232
use PHPStan\ShouldNotHappenException;
3333
use PHPStan\Type\ObjectType;
3434
use function array_diff_key;
35+
use function array_intersect;
3536
use function array_key_exists;
37+
use function array_keys;
3638
use function array_map;
3739
use function array_merge;
3840
use function array_unique;
3941
use function count;
4042
use function dirname;
4143
use function extension_loaded;
4244
use function getenv;
45+
use function implode;
4346
use function ini_get;
4447
use function is_array;
4548
use function is_file;
4649
use function is_readable;
50+
use function is_string;
4751
use function spl_object_id;
4852
use function sprintf;
4953
use function str_ends_with;
@@ -318,15 +322,35 @@ private function validateParameters(array $parameters, array $parametersSchema):
318322
$processor->process($schema, $parameters);
319323

320324
if (
321-
!array_key_exists('phpVersion', $parameters)
322-
|| !is_array($parameters['phpVersion'])) {
323-
return;
325+
array_key_exists('phpVersion', $parameters)
326+
&& is_array($parameters['phpVersion'])
327+
) {
328+
$phpVersion = $parameters['phpVersion'];
329+
330+
if ($phpVersion['max'] < $phpVersion['min']) {
331+
throw new InvalidPhpVersionException('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min.');
332+
}
324333
}
325334

326-
$phpVersion = $parameters['phpVersion'];
335+
foreach ($parameters['ignoreErrors'] ?? [] as $ignoreError) {
336+
if (is_string($ignoreError)) {
337+
continue;
338+
}
339+
340+
$atLeastOneOf = ['message', 'messages', 'identifier', 'identifiers', 'path', 'paths'];
341+
if (array_intersect($atLeastOneOf, array_keys($ignoreError)) === []) {
342+
throw new InvalidIgnoredErrorException('An ignoreErrors entry must contain at least one of the following fields: ' . implode(', ', $atLeastOneOf) . '.');
343+
}
327344

328-
if ($phpVersion['max'] < $phpVersion['min']) {
329-
throw new InvalidPhpVersionException('Invalid PHP version range: phpVersion.max should be greater or equal to phpVersion.min.');
345+
foreach (['message', 'identifier', 'path'] as $field) {
346+
if (array_key_exists($field, $ignoreError) && array_key_exists($field . 's', $ignoreError)) {
347+
throw new InvalidIgnoredErrorException(sprintf('An ignoreErrors entry cannot contain both %s and %s fields.', $field, $field . 's'));
348+
}
349+
}
350+
351+
if (array_key_exists('count', $ignoreError) && !array_key_exists('path', $ignoreError)) {
352+
throw new InvalidIgnoredErrorException('An ignoreErrors entry with count field must also contain path field.');
353+
}
330354
}
331355
}
332356

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\DependencyInjection;
4+
5+
use Nette\DI\InvalidConfigurationException;
6+
7+
final class InvalidIgnoredErrorException extends InvalidConfigurationException
8+
{
9+
10+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\DependencyInjection;
4+
5+
use PHPStan\Testing\PHPStanTestCase;
6+
use PHPUnit\Framework\Attributes\DataProvider;
7+
8+
class InvalidIgnoredErrorExceptionTest extends PHPStanTestCase
9+
{
10+
11+
private static string $configFile;
12+
13+
/**
14+
* @return iterable<array{string, string}>
15+
*/
16+
public static function dataValidateIgnoreErrors(): iterable
17+
{
18+
yield [
19+
__DIR__ . '/invalidIgnoreErrors/message-and-messages.neon',
20+
'An ignoreErrors entry cannot contain both message and messages fields.',
21+
];
22+
yield [
23+
__DIR__ . '/invalidIgnoreErrors/identifier-and-identifiers.neon',
24+
'An ignoreErrors entry cannot contain both identifier and identifiers fields.',
25+
];
26+
yield [
27+
__DIR__ . '/invalidIgnoreErrors/path-and-paths.neon',
28+
'An ignoreErrors entry cannot contain both path and paths fields.',
29+
];
30+
yield [
31+
__DIR__ . '/invalidIgnoreErrors/missing-main-key.neon',
32+
'An ignoreErrors entry must contain at least one of the following fields: message, messages, identifier, identifiers, path, paths.',
33+
];
34+
yield [
35+
__DIR__ . '/invalidIgnoreErrors/count-without-path.neon',
36+
'An ignoreErrors entry with count field must also contain path field.',
37+
];
38+
}
39+
40+
#[DataProvider('dataValidateIgnoreErrors')]
41+
public function testValidateIgnoreErrors(string $file, string $expectedMessage): void
42+
{
43+
self::$configFile = $file;
44+
$this->expectExceptionMessage($expectedMessage);
45+
self::getContainer();
46+
}
47+
48+
public static function getAdditionalConfigFiles(): array
49+
{
50+
return [
51+
__DIR__ . '/../../../conf/bleedingEdge.neon',
52+
self::$configFile,
53+
];
54+
}
55+
56+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
message: '#One#'
5+
count: 3
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
identifier: argument.type
5+
identifiers: [argument.type]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
message: '#One#'
5+
messages: ['#Two#']
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
reportUnmatched: false
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
path: ../IgnoreErrorsTest.php
5+
paths: [../IgnoreErrorsTest.php]

0 commit comments

Comments
 (0)