From 668532608bdc49e57f41d9cf6e36c0a04b54c488 Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Sun, 12 Dec 2021 20:11:43 +0100 Subject: [PATCH] Include `identifier` in generated baseline This makes it possible to analyse the baseline and manually group common errors by `identifier`. In the future, the logic can be used to remove the message patterns and only ignore on identifier. That can help reduce the file size in large legacy projects. References: https://github.com/phpstan/phpstan/issues/1686#issuecomment-532996159 https://github.com/phpstan/phpstan/issues/3065 --- .../BaselineNeonErrorFormatter.php | 37 +++++++++++-------- .../BaselineNeonErrorFormatterTest.php | 7 ++++ 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/Command/ErrorFormatter/BaselineNeonErrorFormatter.php b/src/Command/ErrorFormatter/BaselineNeonErrorFormatter.php index 9879b55924..0091e645ef 100644 --- a/src/Command/ErrorFormatter/BaselineNeonErrorFormatter.php +++ b/src/Command/ErrorFormatter/BaselineNeonErrorFormatter.php @@ -40,29 +40,34 @@ public function formatErrors( if (!$fileSpecificError->canBeIgnored()) { continue; } - $fileErrors[$this->relativePathHelper->getRelativePath($fileSpecificError->getFilePath())][] = $fileSpecificError->getMessage(); + + $relativePath = $this->relativePathHelper->getRelativePath($fileSpecificError->getFilePath()); + $key = $fileSpecificError->getIdentifier() . $fileSpecificError->getMessage(); + + $fileErrors[$relativePath][$key] ??= [ + 'message' => $fileSpecificError->getMessage(), + 'count' => 0, + 'identifier' => $fileSpecificError->getIdentifier() + ]; + $fileErrors[$relativePath][$key]['count']++; } ksort($fileErrors, SORT_STRING); $errorsToOutput = []; - foreach ($fileErrors as $file => $errorMessages) { - $fileErrorsCounts = []; - foreach ($errorMessages as $errorMessage) { - if (!isset($fileErrorsCounts[$errorMessage])) { - $fileErrorsCounts[$errorMessage] = 1; - continue; - } + foreach ($fileErrors as $file => $fileSpecificErrors) { + ksort($fileSpecificErrors, SORT_STRING); - $fileErrorsCounts[$errorMessage]++; - } - ksort($fileErrorsCounts, SORT_STRING); - - foreach ($fileErrorsCounts as $message => $count) { - $errorsToOutput[] = [ - 'message' => Helpers::escape('#^' . preg_quote($message, '#') . '$#'), - 'count' => $count, + foreach ($fileSpecificErrors as $data) { + $error = [ + 'message' => Helpers::escape('#^' . preg_quote($data['message'], '#') . '$#'), + 'count' => $data['count'], 'path' => Helpers::escape($file), ]; + if ($data['identifier'] !== null && $data['identifier'] !== '') { + $error['identifier'] = Helpers::escape($data['identifier']); + } + + $errorsToOutput[] = $error; } } diff --git a/tests/PHPStan/Command/ErrorFormatter/BaselineNeonErrorFormatterTest.php b/tests/PHPStan/Command/ErrorFormatter/BaselineNeonErrorFormatterTest.php index 98fa102cfb..cfa6a790ba 100644 --- a/tests/PHPStan/Command/ErrorFormatter/BaselineNeonErrorFormatterTest.php +++ b/tests/PHPStan/Command/ErrorFormatter/BaselineNeonErrorFormatterTest.php @@ -208,6 +208,7 @@ public function outputOrderingProvider(): Generator new Error('Error with Windows directory separators', 'TestFiles\\TestA', 1), new Error('Error with Unix directory separators', 'TestFiles/TestA', 1), new Error('Error without directory separators', 'TestFilesFoo', 1), + new Error('Error with identifier', 'TestFilesFoo', 1, true, null, null, null, null, null, 'my.identifier'), ]; yield [$errors]; mt_srand(0); @@ -257,6 +258,12 @@ public function testOutputOrdering(array $errors): void 'count' => 1, 'path' => 'TestFilesFoo', ], + [ + 'message' => '#^Error with identifier$#', + 'count' => 1, + 'path' => 'TestFilesFoo', + 'identifier' => 'my.identifier', + ], [ 'message' => '#^A different error \\#1$#', 'count' => 1,