diff --git a/conf/parametersSchema.neon b/conf/parametersSchema.neon index 6af9e2737e..24911351a5 100644 --- a/conf/parametersSchema.neon +++ b/conf/parametersSchema.neon @@ -109,12 +109,14 @@ parametersSchema: structure([ ?messages: listOf(string()) ?identifier: string() + ?identifiers: listOf(string()) ?path: string() ?reportUnmatched: bool() ]), structure([ ?message: string() ?identifier: string() + ?identifiers: listOf(string()) ?path: string() ?reportUnmatched: bool() ]), @@ -123,18 +125,21 @@ parametersSchema: count: int() path: string() ?identifier: string() + ?identifiers: listOf(string()) ?reportUnmatched: bool() ]), structure([ ?message: string() paths: listOf(string()) ?identifier: string() + ?identifiers: listOf(string()) ?reportUnmatched: bool() ]), structure([ ?messages: listOf(string()) paths: listOf(string()) ?identifier: string() + ?identifiers: listOf(string()) ?reportUnmatched: bool() ]) ) diff --git a/src/Analyser/Ignore/IgnoredError.php b/src/Analyser/Ignore/IgnoredError.php index b420ae29ce..8f44d3cb28 100644 --- a/src/Analyser/Ignore/IgnoredError.php +++ b/src/Analyser/Ignore/IgnoredError.php @@ -37,6 +37,13 @@ public static function stringifyPattern($ignoredError): string } else { $message = sprintf('%s (%s)', $message, $ignoredError['identifier']); } + } elseif (isset($ignoredError['identifiers'])) { + $identifierList = implode(', ', $ignoredError['identifiers']); + if ($message === '') { + $message = $identifierList; + } else { + $message = sprintf('%s (%s)', $message, $identifierList); + } } if ($message === '') { diff --git a/src/Analyser/Ignore/IgnoredErrorHelper.php b/src/Analyser/Ignore/IgnoredErrorHelper.php index a863d83adc..29fb13d818 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['identifier'])) { + if (!isset($ignoreError['message']) && !isset($ignoreError['messages']) && !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['identifiers'])) { + foreach ($ignoreError['identifiers'] as $identifier) { + $expandedIgnoreError = $ignoreError; + unset($expandedIgnoreError['identifiers']); + $expandedIgnoreError['identifier'] = $identifier; + $expandedIgnoreErrors[] = $expandedIgnoreError; + } } else { $expandedIgnoreErrors[] = $ignoreError; } diff --git a/tests/PHPStan/Analyser/AnalyserTest.php b/tests/PHPStan/Analyser/AnalyserTest.php index 51f95f9c47..f63fe3eb00 100644 --- a/tests/PHPStan/Analyser/AnalyserTest.php +++ b/tests/PHPStan/Analyser/AnalyserTest.php @@ -116,6 +116,28 @@ public function testFileWithAnIgnoredErrorMessages(): void $this->assertEquals([], $result); } + public function testFileWithAnIgnoredErrorIdentifiers(): void + { + $result = $this->runAnalyser([['identifiers' => ['tests.alwaysFail']]], true, __DIR__ . '/data/bootstrap-error.php', false); + $this->assertEmpty($result); + } + + public function testFileWithAnIgnoredErrorIdentifiersWithPath(): void + { + $result = $this->runAnalyser([['identifiers' => ['tests.alwaysFail'], 'path' => __DIR__ . '/data/bootstrap-error.php']], true, __DIR__ . '/data/bootstrap-error.php', false); + $this->assertEmpty($result); + } + + public function testFileWithAnIgnoredErrorIdentifiersWithWrongIdentifier(): void + { + $result = $this->runAnalyser([['identifiers' => ['wrong.identifier']]], true, __DIR__ . '/data/bootstrap-error.php', false); + $this->assertCount(2, $result); + assert($result[0] instanceof Error); + $this->assertSame('Fail.', $result[0]->getMessage()); + assert(is_string($result[1])); + $this->assertSame('Ignored error pattern wrong.identifier was not matched in reported errors.', $result[1]); + } + public function testIgnoringBrokenConfigurationDoesNotWork(): void { $this->markTestIncomplete(); diff --git a/tests/PHPStan/DependencyInjection/IgnoreErrorsTest.php b/tests/PHPStan/DependencyInjection/IgnoreErrorsTest.php index 112b256ed4..f24e65abc2 100644 --- a/tests/PHPStan/DependencyInjection/IgnoreErrorsTest.php +++ b/tests/PHPStan/DependencyInjection/IgnoreErrorsTest.php @@ -9,7 +9,7 @@ class IgnoreErrorsTest extends PHPStanTestCase public function testIgnoreErrors(): void { - $this->assertCount(12, self::getContainer()->getParameter('ignoreErrors')); + $this->assertCount(16, self::getContainer()->getParameter('ignoreErrors')); } /** diff --git a/tests/PHPStan/DependencyInjection/ignoreErrors.neon b/tests/PHPStan/DependencyInjection/ignoreErrors.neon index df1d471d75..c137667bb4 100644 --- a/tests/PHPStan/DependencyInjection/ignoreErrors.neon +++ b/tests/PHPStan/DependencyInjection/ignoreErrors.neon @@ -45,3 +45,21 @@ parameters: paths: - '/dir/*' reportUnmatched: false + - + identifiers: + - 'error.identifier' + - + identifiers: + - 'error.identifier' + path: '/dir/*' + - + identifiers: + - 'error.identifier' + paths: + - '/dir/*' + - + identifiers: + - 'error.identifier' + - 'another.identifier' + path: '/dir/*' + reportUnmatched: false