/
BaselineNeonErrorFormatter.php
98 lines (81 loc) · 2.53 KB
/
BaselineNeonErrorFormatter.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?php declare(strict_types = 1);
namespace PHPStan\Command\ErrorFormatter;
use Nette\DI\Helpers;
use Nette\Neon\Neon;
use Nette\Utils\Strings;
use PHPStan\Command\AnalysisResult;
use PHPStan\Command\Output;
use PHPStan\File\RelativePathHelper;
use PHPStan\ShouldNotHappenException;
use function ksort;
use function preg_quote;
use function substr;
use const SORT_STRING;
class BaselineNeonErrorFormatter
{
public function __construct(private RelativePathHelper $relativePathHelper)
{
}
public function formatErrors(
AnalysisResult $analysisResult,
Output $output,
string $existingBaselineContent,
): int
{
if (!$analysisResult->hasErrors()) {
$output->writeRaw($this->getNeon([], $existingBaselineContent));
return 0;
}
$fileErrors = [];
foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) {
if (!$fileSpecificError->canBeIgnored()) {
continue;
}
$fileErrors[$this->relativePathHelper->getRelativePath($fileSpecificError->getFilePath())][] = $fileSpecificError->getMessage();
}
ksort($fileErrors, SORT_STRING);
$errorsToOutput = [];
foreach ($fileErrors as $file => $errorMessages) {
$fileErrorsCounts = [];
foreach ($errorMessages as $errorMessage) {
if (!isset($fileErrorsCounts[$errorMessage])) {
$fileErrorsCounts[$errorMessage] = 1;
continue;
}
$fileErrorsCounts[$errorMessage]++;
}
ksort($fileErrorsCounts, SORT_STRING);
foreach ($fileErrorsCounts as $message => $count) {
$errorsToOutput[] = [
'message' => Helpers::escape('#^' . preg_quote($message, '#') . '$#'),
'count' => $count,
'path' => Helpers::escape($file),
];
}
}
$output->writeRaw($this->getNeon($errorsToOutput, $existingBaselineContent));
return 1;
}
/**
* @param array<int, array{message: string, count: int, path: string}> $ignoreErrors
*/
private function getNeon(array $ignoreErrors, string $existingBaselineContent): string
{
$neon = Neon::encode([
'parameters' => [
'ignoreErrors' => $ignoreErrors,
],
], Neon::BLOCK);
if (substr($neon, -2) !== "\n\n") {
throw new ShouldNotHappenException();
}
if ($existingBaselineContent === '') {
return substr($neon, 0, -1);
}
$existingBaselineContentEndOfFileNewlinesMatches = Strings::match($existingBaselineContent, "~(\n)+$~");
$existingBaselineContentEndOfFileNewlines = $existingBaselineContentEndOfFileNewlinesMatches !== null
? $existingBaselineContentEndOfFileNewlinesMatches[0]
: '';
return substr($neon, 0, -2) . $existingBaselineContentEndOfFileNewlines;
}
}