diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index eb417742c3..269dc27c83 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -126,6 +126,7 @@ parametersSchema: ?message: string() ?messages: listOf(string()) ?rawMessage: string() + ?rawMessages: listOf(string()) ?identifier: string() ?identifiers: listOf(string()) ?path: string() diff --git a/src/Analyser/Ignore/IgnoredErrorHelper.php b/src/Analyser/Ignore/IgnoredErrorHelper.php index 19e9428f26..f67a3e207a 100644 --- a/src/Analyser/Ignore/IgnoredErrorHelper.php +++ b/src/Analyser/Ignore/IgnoredErrorHelper.php @@ -40,7 +40,7 @@ public function initialize(): IgnoredErrorHelperResult $expandedIgnoreErrors = []; foreach ($this->ignoreErrors as $ignoreError) { if (is_array($ignoreError)) { - if (!isset($ignoreError['message']) && !isset($ignoreError['messages']) && !isset($ignoreError['rawMessage']) && !isset($ignoreError['identifier']) && !isset($ignoreError['identifiers'])) { + if (!isset($ignoreError['message']) && !isset($ignoreError['messages']) && !isset($ignoreError['rawMessage']) && !isset($ignoreError['rawMessages']) && !isset($ignoreError['identifier']) && !isset($ignoreError['identifiers'])) { $errors[] = sprintf( 'Ignored error %s is missing a message or an identifier.', Json::encode($ignoreError), @@ -54,6 +54,13 @@ public function initialize(): IgnoredErrorHelperResult $expandedIgnoreError['message'] = $message; $expandedIgnoreErrors[] = $expandedIgnoreError; } + } elseif (isset($ignoreError['rawMessages'])) { + foreach ($ignoreError['rawMessages'] as $rawMessage) { + $expandedIgnoreError = $ignoreError; + unset($expandedIgnoreError['rawMessages']); + $expandedIgnoreError['rawMessage'] = $rawMessage; + $expandedIgnoreErrors[] = $expandedIgnoreError; + } } elseif (isset($ignoreError['identifiers'])) { foreach ($ignoreError['identifiers'] as $identifier) { $expandedIgnoreError = $ignoreError; diff --git a/src/DependencyInjection/ContainerFactory.php b/src/DependencyInjection/ContainerFactory.php index 7f056c2c40..d2e163b837 100644 --- a/src/DependencyInjection/ContainerFactory.php +++ b/src/DependencyInjection/ContainerFactory.php @@ -37,6 +37,7 @@ use function array_keys; use function array_map; use function array_merge; +use function array_slice; use function array_unique; use function count; use function dirname; @@ -337,20 +338,23 @@ private function validateParameters(array $parameters, array $parametersSchema): continue; } - $atLeastOneOf = ['message', 'messages', 'rawMessage', 'identifier', 'identifiers', 'path', 'paths']; + $atLeastOneOf = ['message', 'messages', 'rawMessage', 'rawMessages', 'identifier', 'identifiers', 'path', 'paths']; if (array_intersect($atLeastOneOf, array_keys($ignoreError)) === []) { throw new InvalidIgnoredErrorException('An ignoreErrors entry must contain at least one of the following fields: ' . implode(', ', $atLeastOneOf) . '.'); } foreach ([ - ['message', 'messages'], - ['rawMessage', 'message'], - ['rawMessage', 'messages'], + ['rawMessage', 'rawMessages', 'message', 'messages'], ['identifier', 'identifiers'], ['path', 'paths'], - ] as [$field1, $field2]) { - if (array_key_exists($field1, $ignoreError) && array_key_exists($field2, $ignoreError)) { - throw new InvalidIgnoredErrorException(sprintf('An ignoreErrors entry cannot contain both %s and %s fields.', $field1, $field2)); + ] as $incompatibleFields) { + foreach ($incompatibleFields as $index => $field1) { + $fieldsToCheck = array_slice($incompatibleFields, $index + 1); + foreach ($fieldsToCheck as $field2) { + if (array_key_exists($field1, $ignoreError) && array_key_exists($field2, $ignoreError)) { + throw new InvalidIgnoredErrorException(sprintf('An ignoreErrors entry cannot contain both %s and %s fields.', $field1, $field2)); + } + } } } diff --git a/tests/PHPStan/Analyser/AnalyserTest.php b/tests/PHPStan/Analyser/AnalyserTest.php index caa1cfa1eb..0519966b1e 100644 --- a/tests/PHPStan/Analyser/AnalyserTest.php +++ b/tests/PHPStan/Analyser/AnalyserTest.php @@ -136,6 +136,12 @@ public function testFileWithAnIgnoredErrorMessages(): void $this->assertEquals([], $result); } + public function testFileWithAnIgnoredErrorRawMessages(): void + { + $result = $this->runAnalyser([['rawMessages' => ['Fail.']]], true, __DIR__ . '/data/bootstrap-error.php', false); + $this->assertEquals([], $result); + } + public function testFileWithAnIgnoredErrorIdentifiers(): void { $result = $this->runAnalyser([['identifiers' => ['tests.alwaysFail']]], true, __DIR__ . '/data/bootstrap-error.php', false); diff --git a/tests/PHPStan/DependencyInjection/InvalidIgnoredErrorExceptionTest.php b/tests/PHPStan/DependencyInjection/InvalidIgnoredErrorExceptionTest.php index 6d8ac35b8c..a4d6dc2a72 100644 --- a/tests/PHPStan/DependencyInjection/InvalidIgnoredErrorExceptionTest.php +++ b/tests/PHPStan/DependencyInjection/InvalidIgnoredErrorExceptionTest.php @@ -27,6 +27,18 @@ public static function dataValidateIgnoreErrors(): iterable __DIR__ . '/invalidIgnoreErrors/rawMessage-and-messages.neon', 'An ignoreErrors entry cannot contain both rawMessage and messages fields.', ]; + yield [ + __DIR__ . '/invalidIgnoreErrors/rawMessage-and-rawMessages.neon', + 'An ignoreErrors entry cannot contain both rawMessage and rawMessages fields.', + ]; + yield [ + __DIR__ . '/invalidIgnoreErrors/rawMessages-and-message.neon', + 'An ignoreErrors entry cannot contain both rawMessages and message fields.', + ]; + yield [ + __DIR__ . '/invalidIgnoreErrors/rawMessages-and-messages.neon', + 'An ignoreErrors entry cannot contain both rawMessages and messages fields.', + ]; yield [ __DIR__ . '/invalidIgnoreErrors/identifier-and-identifiers.neon', 'An ignoreErrors entry cannot contain both identifier and identifiers fields.', @@ -37,7 +49,7 @@ public static function dataValidateIgnoreErrors(): iterable ]; yield [ __DIR__ . '/invalidIgnoreErrors/missing-main-key.neon', - 'An ignoreErrors entry must contain at least one of the following fields: message, messages, rawMessage, identifier, identifiers, path, paths.', + 'An ignoreErrors entry must contain at least one of the following fields: message, messages, rawMessage, rawMessages, identifier, identifiers, path, paths.', ]; yield [ __DIR__ . '/invalidIgnoreErrors/count-without-path.neon', diff --git a/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/rawMessage-and-rawMessages.neon b/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/rawMessage-and-rawMessages.neon new file mode 100644 index 0000000000..971595c028 --- /dev/null +++ b/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/rawMessage-and-rawMessages.neon @@ -0,0 +1,5 @@ +parameters: + ignoreErrors: + - + rawMessage: 'One' + rawMessages: ['Two'] diff --git a/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/rawMessages-and-message.neon b/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/rawMessages-and-message.neon new file mode 100644 index 0000000000..391b5f9083 --- /dev/null +++ b/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/rawMessages-and-message.neon @@ -0,0 +1,5 @@ +parameters: + ignoreErrors: + - + message: '#One#' + rawMessages: ['Two'] diff --git a/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/rawMessages-and-messages.neon b/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/rawMessages-and-messages.neon new file mode 100644 index 0000000000..c8b7849b38 --- /dev/null +++ b/tests/PHPStan/DependencyInjection/invalidIgnoreErrors/rawMessages-and-messages.neon @@ -0,0 +1,5 @@ +parameters: + ignoreErrors: + - + messages: ['#One#'] + rawMessages: ['Two']