Skip to content

Commit 6f87293

Browse files
gharlanondrejmirtes
authored andcommitted
Introduce rawMessage key in ignoreErrors
1 parent 4a9474a commit 6f87293

File tree

9 files changed

+134
-12
lines changed

9 files changed

+134
-12
lines changed

conf/parametersSchema.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ parametersSchema:
114114
structure([
115115
?message: string()
116116
?messages: listOf(string())
117+
?rawMessage: string()
117118
?identifier: string()
118119
?identifiers: listOf(string())
119120
?path: string()

src/Analyser/Ignore/IgnoredError.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ public static function stringifyPattern($ignoredError): string
3030
$message = '';
3131
if (isset($ignoredError['message'])) {
3232
$message = $ignoredError['message'];
33+
} elseif (isset($ignoredError['rawMessage'])) {
34+
$message = '"' . $ignoredError['rawMessage'] . '"';
3335
}
3436
if (isset($ignoredError['identifier'])) {
3537
if ($message === '') {
@@ -71,6 +73,7 @@ public static function shouldIgnore(
7173
FileHelper $fileHelper,
7274
Error $error,
7375
?string $ignoredErrorPattern,
76+
?string $ignoredErrorMessage,
7477
?string $identifier,
7578
?string $path,
7679
): bool
@@ -91,6 +94,12 @@ public static function shouldIgnore(
9194
}
9295
}
9396

97+
if ($ignoredErrorMessage !== null) {
98+
if ($error->getMessage() !== $ignoredErrorMessage) {
99+
return false;
100+
}
101+
}
102+
94103
if ($path !== null) {
95104
$fileExcluder = new FileExcluder($fileHelper, [$path]);
96105
$isExcluded = $fileExcluder->isExcludedFromAnalysing($error->getFilePath());

src/Analyser/Ignore/IgnoredErrorHelper.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function initialize(): IgnoredErrorHelperResult
4040
$expandedIgnoreErrors = [];
4141
foreach ($this->ignoreErrors as $ignoreError) {
4242
if (is_array($ignoreError)) {
43-
if (!isset($ignoreError['message']) && !isset($ignoreError['messages']) && !isset($ignoreError['identifier']) && !isset($ignoreError['identifiers'])) {
43+
if (!isset($ignoreError['message']) && !isset($ignoreError['messages']) && !isset($ignoreError['rawMessage']) && !isset($ignoreError['identifier']) && !isset($ignoreError['identifiers'])) {
4444
$errors[] = sprintf(
4545
'Ignored error %s is missing a message or an identifier.',
4646
Json::encode($ignoreError),
@@ -71,7 +71,7 @@ public function initialize(): IgnoredErrorHelperResult
7171

7272
$uniquedExpandedIgnoreErrors = [];
7373
foreach ($expandedIgnoreErrors as $ignoreError) {
74-
if (!isset($ignoreError['message']) && !isset($ignoreError['identifier'])) {
74+
if (!isset($ignoreError['message']) && !isset($ignoreError['rawMessage']) && !isset($ignoreError['identifier'])) {
7575
$uniquedExpandedIgnoreErrors[] = $ignoreError;
7676
continue;
7777
}
@@ -84,6 +84,9 @@ public function initialize(): IgnoredErrorHelperResult
8484
if (isset($ignoreError['message'])) {
8585
$key = sprintf("%s\n%s", $key, $ignoreError['message']);
8686
}
87+
if (isset($ignoreError['rawMessage'])) {
88+
$key = sprintf("%s\n%s", $key, $ignoreError['rawMessage']);
89+
}
8790
if (isset($ignoreError['identifier'])) {
8891
$key = sprintf("%s\n%s", $key, $ignoreError['identifier']);
8992
}
@@ -98,6 +101,7 @@ public function initialize(): IgnoredErrorHelperResult
98101

99102
$uniquedExpandedIgnoreErrors[$key] = [
100103
'message' => $ignoreError['message'] ?? null,
104+
'rawMessage' => $ignoreError['rawMessage'] ?? null,
101105
'path' => $ignoreError['path'],
102106
'identifier' => $ignoreError['identifier'] ?? null,
103107
'count' => ($uniquedExpandedIgnoreErrors[$key]['count'] ?? 1) + ($ignoreError['count'] ?? 1),
@@ -114,7 +118,7 @@ public function initialize(): IgnoredErrorHelperResult
114118
];
115119
try {
116120
if (is_array($ignoreError)) {
117-
if (!isset($ignoreError['message']) && !isset($ignoreError['identifier'])) {
121+
if (!isset($ignoreError['message']) && !isset($ignoreError['rawMessage']) && !isset($ignoreError['identifier'])) {
118122
$errors[] = sprintf(
119123
'Ignored error %s is missing a message or an identifier.',
120124
Json::encode($ignoreError),

src/Analyser/Ignore/IgnoredErrorHelperResult.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,13 @@ public function process(
5858
$processIgnoreError = function (Error $error, int $i, $ignore) use (&$unmatchedIgnoredErrors, &$stringErrors): bool {
5959
$shouldBeIgnored = false;
6060
if (is_string($ignore)) {
61-
$shouldBeIgnored = IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore, null, null);
61+
$shouldBeIgnored = IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore, null, null, null);
6262
if ($shouldBeIgnored) {
6363
unset($unmatchedIgnoredErrors[$i]);
6464
}
6565
} else {
6666
if (isset($ignore['path'])) {
67-
$shouldBeIgnored = IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore['message'] ?? null, $ignore['identifier'] ?? null, $ignore['path']);
67+
$shouldBeIgnored = IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore['message'] ?? null, $ignore['rawMessage'] ?? null, $ignore['identifier'] ?? null, $ignore['path']);
6868
if ($shouldBeIgnored) {
6969
if (isset($ignore['count'])) {
7070
$realCount = $unmatchedIgnoredErrors[$i]['realCount'] ?? 0;
@@ -85,7 +85,7 @@ public function process(
8585
}
8686
} elseif (isset($ignore['paths'])) {
8787
foreach ($ignore['paths'] as $j => $ignorePath) {
88-
$shouldBeIgnored = IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore['message'] ?? null, $ignore['identifier'] ?? null, $ignorePath);
88+
$shouldBeIgnored = IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore['message'] ?? null, $ignore['rawMessage'] ?? null, $ignore['identifier'] ?? null, $ignorePath);
8989
if (!$shouldBeIgnored) {
9090
continue;
9191
}
@@ -102,7 +102,7 @@ public function process(
102102
break;
103103
}
104104
} else {
105-
$shouldBeIgnored = IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore['message'] ?? null, $ignore['identifier'] ?? null, null);
105+
$shouldBeIgnored = IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore['message'] ?? null, $ignore['rawMessage'] ?? null, $ignore['identifier'] ?? null, null);
106106
if ($shouldBeIgnored) {
107107
unset($unmatchedIgnoredErrors[$i]);
108108
}

src/DependencyInjection/ContainerFactory.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,14 +337,20 @@ private function validateParameters(array $parameters, array $parametersSchema):
337337
continue;
338338
}
339339

340-
$atLeastOneOf = ['message', 'messages', 'identifier', 'identifiers', 'path', 'paths'];
340+
$atLeastOneOf = ['message', 'messages', 'rawMessage', 'identifier', 'identifiers', 'path', 'paths'];
341341
if (array_intersect($atLeastOneOf, array_keys($ignoreError)) === []) {
342342
throw new InvalidIgnoredErrorException('An ignoreErrors entry must contain at least one of the following fields: ' . implode(', ', $atLeastOneOf) . '.');
343343
}
344344

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'));
345+
foreach ([
346+
['message', 'messages'],
347+
['rawMessage', 'message'],
348+
['rawMessage', 'messages'],
349+
['identifier', 'identifiers'],
350+
['path', 'paths'],
351+
] as [$field1, $field2]) {
352+
if (array_key_exists($field1, $ignoreError) && array_key_exists($field2, $ignoreError)) {
353+
throw new InvalidIgnoredErrorException(sprintf('An ignoreErrors entry cannot contain both %s and %s fields.', $field1, $field2));
348354
}
349355
}
350356

tests/PHPStan/Analyser/AnalyserTest.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ public function testFileWithAnIgnoredErrorMessage(): void
7979
$this->assertEmpty($result);
8080
}
8181

82+
public function testFileWithAnIgnoredErrorRawMessage(): void
83+
{
84+
$result = $this->runAnalyser([['rawMessage' => 'Fail.']], true, __DIR__ . '/data/bootstrap-error.php', false);
85+
$this->assertEmpty($result);
86+
}
87+
8288
public function testFileWithAnIgnoredErrorMessageAndWrongIdentifier(): void
8389
{
8490
$result = $this->runAnalyser([['message' => '#Fail\.#', 'identifier' => 'wrong.identifier']], true, __DIR__ . '/data/bootstrap-error.php', false);
@@ -89,6 +95,16 @@ public function testFileWithAnIgnoredErrorMessageAndWrongIdentifier(): void
8995
$this->assertSame('Ignored error pattern #Fail\.# (wrong.identifier) was not matched in reported errors.', $result[1]);
9096
}
9197

98+
public function testFileWithAnIgnoredErrorRawMessageAndWrongIdentifier(): void
99+
{
100+
$result = $this->runAnalyser([['rawMessage' => 'Fail.', 'identifier' => 'wrong.identifier']], true, __DIR__ . '/data/bootstrap-error.php', false);
101+
$this->assertCount(2, $result);
102+
assert($result[0] instanceof Error);
103+
$this->assertSame('Fail.', $result[0]->getMessage());
104+
assert(is_string($result[1]));
105+
$this->assertSame('Ignored error pattern "Fail." (wrong.identifier) was not matched in reported errors.', $result[1]);
106+
}
107+
92108
public function testFileWithAnIgnoredWrongIdentifier(): void
93109
{
94110
$result = $this->runAnalyser([['identifier' => 'wrong.identifier']], true, __DIR__ . '/data/bootstrap-error.php', false);
@@ -105,6 +121,12 @@ public function testFileWithAnIgnoredErrorMessageAndCorrectIdentifier(): void
105121
$this->assertEmpty($result);
106122
}
107123

124+
public function testFileWithAnIgnoredErrorRawMessageAndCorrectIdentifier(): void
125+
{
126+
$result = $this->runAnalyser([['rawMessage' => 'Fail.', 'identifier' => 'tests.alwaysFail']], true, __DIR__ . '/data/bootstrap-error.php', false);
127+
$this->assertEmpty($result);
128+
}
129+
108130
public function testFileWithAnIgnoredErrorIdentifier(): void
109131
{
110132
$result = $this->runAnalyser([['identifier' => 'tests.alwaysFail']], true, __DIR__ . '/data/bootstrap-error.php', false);
@@ -216,6 +238,31 @@ public static function dataIgnoreErrorByPathAndCount(): iterable
216238
],
217239
],
218240
];
241+
242+
yield [
243+
[
244+
[
245+
'rawMessage' => 'Fail.',
246+
'count' => 3,
247+
'path' => __DIR__ . '/data/two-fails.php',
248+
],
249+
],
250+
];
251+
252+
yield [
253+
[
254+
[
255+
'rawMessage' => 'Fail.',
256+
'count' => 2,
257+
'path' => __DIR__ . '/data/two-fails.php',
258+
],
259+
[
260+
'rawMessage' => 'Fail.',
261+
'count' => 1,
262+
'path' => __DIR__ . '/data/two-fails.php',
263+
],
264+
],
265+
];
219266
}
220267

221268
/**
@@ -352,6 +399,18 @@ public function testIgnoreErrorByPaths(): void
352399
$this->assertNoErrors($result);
353400
}
354401

402+
public function testIgnoreErrorRawByPaths(): void
403+
{
404+
$ignoreErrors = [
405+
[
406+
'rawMessage' => 'Fail.',
407+
'paths' => [__DIR__ . '/data/bootstrap-error.php'],
408+
],
409+
];
410+
$result = $this->runAnalyser($ignoreErrors, true, __DIR__ . '/data/bootstrap-error.php', false);
411+
$this->assertNoErrors($result);
412+
}
413+
355414
public function testIgnoreErrorMultiByPaths(): void
356415
{
357416
$ignoreErrors = [
@@ -622,6 +681,18 @@ public function testIgnoreErrorExplicitReportUnmatchedDisable(): void
622681
$this->assertNoErrors($result);
623682
}
624683

684+
public function testIgnoreErrorExplicitReportUnmatchedDisableRaw(): void
685+
{
686+
$ignoreErrors = [
687+
[
688+
'rawMessage' => 'Fail.',
689+
'reportUnmatched' => false,
690+
],
691+
];
692+
$result = $this->runAnalyser($ignoreErrors, true, __DIR__ . '/data/bootstrap.php', false);
693+
$this->assertNoErrors($result);
694+
}
695+
625696
public function testIgnoreErrorExplicitReportUnmatchedDisableMulti(): void
626697
{
627698
$ignoreErrors = [
@@ -647,6 +718,19 @@ public function testIgnoreErrorExplicitReportUnmatchedEnable(): void
647718
$this->assertSame('Ignored error pattern #Fail# was not matched in reported errors.', $result[0]);
648719
}
649720

721+
public function testIgnoreErrorExplicitReportUnmatchedEnableRaw(): void
722+
{
723+
$ignoreErrors = [
724+
[
725+
'rawMessage' => 'Fail.',
726+
'reportUnmatched' => true,
727+
],
728+
];
729+
$result = $this->runAnalyser($ignoreErrors, false, __DIR__ . '/data/bootstrap.php', false);
730+
$this->assertCount(1, $result);
731+
$this->assertSame('Ignored error pattern "Fail." was not matched in reported errors.', $result[0]);
732+
}
733+
650734
public function testIgnoreErrorExplicitReportUnmatchedEnableMulti(): void
651735
{
652736
$ignoreErrors = [

tests/PHPStan/DependencyInjection/InvalidIgnoredErrorExceptionTest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ public static function dataValidateIgnoreErrors(): iterable
1919
__DIR__ . '/invalidIgnoreErrors/message-and-messages.neon',
2020
'An ignoreErrors entry cannot contain both message and messages fields.',
2121
];
22+
yield [
23+
__DIR__ . '/invalidIgnoreErrors/rawMessage-and-message.neon',
24+
'An ignoreErrors entry cannot contain both rawMessage and message fields.',
25+
];
26+
yield [
27+
__DIR__ . '/invalidIgnoreErrors/rawMessage-and-messages.neon',
28+
'An ignoreErrors entry cannot contain both rawMessage and messages fields.',
29+
];
2230
yield [
2331
__DIR__ . '/invalidIgnoreErrors/identifier-and-identifiers.neon',
2432
'An ignoreErrors entry cannot contain both identifier and identifiers fields.',
@@ -29,7 +37,7 @@ public static function dataValidateIgnoreErrors(): iterable
2937
];
3038
yield [
3139
__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.',
40+
'An ignoreErrors entry must contain at least one of the following fields: message, messages, rawMessage, identifier, identifiers, path, paths.',
3341
];
3442
yield [
3543
__DIR__ . '/invalidIgnoreErrors/count-without-path.neon',
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
rawMessage: 'One'
5+
message: '#Two#'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
rawMessage: 'One'
5+
messages: ['#Two#']

0 commit comments

Comments
 (0)