Skip to content

Commit 389b6d1

Browse files
committed
Add --ignore-new-errors analyse command option
1 parent 192fefa commit 389b6d1

10 files changed

+94
-61
lines changed

src/Analyser/Ignore/IgnoredErrorHelperResult.php

+38-15
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,15 @@ public function process(
5050
bool $onlyFiles,
5151
array $analysedFiles,
5252
bool $hasInternalErrors,
53+
bool $generateBaseline,
54+
bool $ignoreNewErrors,
5355
): IgnoredErrorHelperProcessedResult
5456
{
55-
$unmatchedIgnoredErrors = $this->ignoreErrors;
57+
// if we are generating the baseline, we dont want ignore Errors configuration to affect the errors we output
58+
$unmatchedIgnoredErrors = $generateBaseline ? [] : $this->ignoreErrors;
5659
$stringErrors = [];
5760

58-
$processIgnoreError = function (Error $error, int $i, $ignore) use (&$unmatchedIgnoredErrors, &$stringErrors): bool {
61+
$processIgnoreError = function (Error $error, int $i, $ignore) use ($generateBaseline, &$unmatchedIgnoredErrors, &$stringErrors): bool {
5962
$shouldBeIgnored = false;
6063
if (is_string($ignore)) {
6164
$shouldBeIgnored = IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore, null, null);
@@ -65,7 +68,8 @@ public function process(
6568
} else {
6669
if (isset($ignore['path'])) {
6770
$shouldBeIgnored = IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore['message'] ?? null, $ignore['identifier'] ?? null, $ignore['path']);
68-
if ($shouldBeIgnored) {
71+
// only ignore errors when not generating the baseline, because it need to contain all errors
72+
if ($shouldBeIgnored && !$generateBaseline) {
6973
if (isset($ignore['count'])) {
7074
$realCount = $unmatchedIgnoredErrors[$i]['realCount'] ?? 0;
7175
$realCount++;
@@ -115,12 +119,12 @@ public function process(
115119
'Error message "%s" cannot be ignored, use excludePaths instead.',
116120
$error->getMessage(),
117121
);
118-
return true;
122+
return false;
119123
}
120-
return false;
124+
return true;
121125
}
122126

123-
return true;
127+
return false;
124128
};
125129

126130
$ignoredErrors = [];
@@ -130,12 +134,16 @@ public function process(
130134
foreach ($this->ignoreErrorsByFile[$filePath] as $ignoreError) {
131135
$i = $ignoreError['index'];
132136
$ignore = $ignoreError['ignoreError'];
133-
$result = $processIgnoreError($error, $i, $ignore);
134-
if (!$result) {
137+
$isIgnoreMatch = $processIgnoreError($error, $i, $ignore);
138+
if (!$isIgnoreMatch) {
139+
continue;
140+
}
141+
142+
if (!$generateBaseline) {
135143
unset($errors[$errorIndex]);
136144
$ignoredErrors[] = [$error, $ignore];
137-
continue 2;
138145
}
146+
continue 2;
139147
}
140148
}
141149

@@ -146,12 +154,16 @@ public function process(
146154
foreach ($this->ignoreErrorsByFile[$normalizedTraitFilePath] as $ignoreError) {
147155
$i = $ignoreError['index'];
148156
$ignore = $ignoreError['ignoreError'];
149-
$result = $processIgnoreError($error, $i, $ignore);
150-
if (!$result) {
157+
$isIgnoreMatch = $processIgnoreError($error, $i, $ignore);
158+
if (!$isIgnoreMatch) {
159+
continue;
160+
}
161+
162+
if (!$generateBaseline) {
151163
unset($errors[$errorIndex]);
152164
$ignoredErrors[] = [$error, $ignore];
153-
continue 2;
154165
}
166+
continue 2;
155167
}
156168
}
157169
}
@@ -160,13 +172,24 @@ public function process(
160172
$i = $ignoreError['index'];
161173
$ignore = $ignoreError['ignoreError'];
162174

163-
$result = $processIgnoreError($error, $i, $ignore);
164-
if (!$result) {
175+
$isIgnoreMatch = $processIgnoreError($error, $i, $ignore);
176+
if (!$isIgnoreMatch) {
177+
continue;
178+
}
179+
180+
if (!$generateBaseline) {
165181
unset($errors[$errorIndex]);
166182
$ignoredErrors[] = [$error, $ignore];
167-
continue 2;
168183
}
184+
continue 2;
169185
}
186+
187+
if (!$ignoreNewErrors) {
188+
continue;
189+
}
190+
191+
// if the error was not ignored, it is a new error, don't return it when $ignoreNewErrors is set
192+
unset($errors[$errorIndex]);
170193
}
171194

172195
$errors = array_values($errors);

src/Command/AnalyseApplication.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ public function analyse(
4747
?string $projectConfigFile,
4848
?array $projectConfigArray,
4949
InputInterface $input,
50+
bool $generateBaseline,
51+
bool $ignoreNewErrors,
5052
): AnalysisResult
5153
{
5254
$isResultCacheUsed = false;
@@ -138,7 +140,7 @@ public function analyse(
138140
}
139141
}
140142

141-
$ignoredErrorHelperProcessedResult = $ignoredErrorHelperResult->process($errors, $onlyFiles, $files, $hasInternalErrors);
143+
$ignoredErrorHelperProcessedResult = $ignoredErrorHelperResult->process($errors, $onlyFiles, $files, $hasInternalErrors, $generateBaseline, $ignoreNewErrors);
142144
$fileSpecificErrors = $ignoredErrorHelperProcessedResult->getNotIgnoredErrors();
143145
$notFileSpecificErrors = $ignoredErrorHelperProcessedResult->getOtherIgnoreMessages();
144146
$collectedData = $analyserResult->getCollectedData();

src/Command/AnalyseCommand.php

+9
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ protected function configure(): void
102102
new InputOption('watch', null, InputOption::VALUE_NONE, 'Launch PHPStan Pro'),
103103
new InputOption('pro', null, InputOption::VALUE_NONE, 'Launch PHPStan Pro'),
104104
new InputOption('fail-without-result-cache', null, InputOption::VALUE_NONE, 'Return non-zero exit code when result cache is not used'),
105+
new InputOption('ignore-new-errors', null, InputOption::VALUE_NONE, 'Ignore new errors when generating the baseline.'),
105106
]);
106107
}
107108

@@ -136,6 +137,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
136137
$debugEnabled = (bool) $input->getOption('debug');
137138
$fix = (bool) $input->getOption('fix') || (bool) $input->getOption('watch') || (bool) $input->getOption('pro');
138139
$failWithoutResultCache = (bool) $input->getOption('fail-without-result-cache');
140+
$ignoreNewErrors = (bool) $input->getOption('ignore-new-errors');
139141

140142
/** @var string|false|null $generateBaselineFile */
141143
$generateBaselineFile = $input->getOption('generate-baseline');
@@ -182,6 +184,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
182184
return $inceptionResult->handleReturn(1, null, $this->analysisStartTime);
183185
}
184186

187+
if ($generateBaselineFile === null && $ignoreNewErrors) {
188+
$inceptionResult->getStdOutput()->getStyle()->error('You must pass the --generate-baseline option alongside --ignore-new-errors.');
189+
return $inceptionResult->handleReturn(1, null, $this->analysisStartTime);
190+
}
191+
185192
$errorOutput = $inceptionResult->getErrorOutput();
186193
$errorFormat = $input->getOption('error-format');
187194

@@ -290,6 +297,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
290297
$inceptionResult->getProjectConfigFile(),
291298
$inceptionResult->getProjectConfigArray(),
292299
$input,
300+
$generateBaselineFile !== null,
301+
$ignoreNewErrors,
293302
);
294303
} catch (Throwable $t) {
295304
if ($debug) {

src/Command/CommandHelper.php

-2
Original file line numberDiff line numberDiff line change
@@ -224,10 +224,8 @@ public static function begin(
224224
}
225225

226226
$loader = (new LoaderFactory(
227-
$currentWorkingDirectoryFileHelper,
228227
$containerFactory->getRootDirectory(),
229228
$containerFactory->getCurrentWorkingDirectory(),
230-
$generateBaselineFile,
231229
))->createLoader();
232230

233231
try {

src/Command/FixerWorkerCommand.php

+10-1
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,8 @@ function (array $errors, array $locallyIgnoredErrors, array $analysedFiles) use
302302
$isOnlyFiles,
303303
$inceptionFiles,
304304
$hasInternalErrors,
305+
false,
306+
false,
305307
);
306308
$ignoreFileErrors = [];
307309
foreach ($ignoredErrorHelperProcessedResult->getNotIgnoredErrors() as $error) {
@@ -355,7 +357,14 @@ private function transformErrorIntoInternalError(Error $error): InternalError
355357
*/
356358
private function filterErrors(array $errors, IgnoredErrorHelperResult $ignoredErrorHelperResult, bool $onlyFiles, array $inceptionFiles, bool $hasInternalErrors): array
357359
{
358-
$ignoredErrorHelperProcessedResult = $ignoredErrorHelperResult->process($errors, $onlyFiles, $inceptionFiles, $hasInternalErrors);
360+
$ignoredErrorHelperProcessedResult = $ignoredErrorHelperResult->process(
361+
$errors,
362+
$onlyFiles,
363+
$inceptionFiles,
364+
$hasInternalErrors,
365+
false,
366+
false,
367+
);
359368
$finalErrors = [];
360369
foreach ($ignoredErrorHelperProcessedResult->getNotIgnoredErrors() as $error) {
361370
if ($error->getIdentifier() === null) {

src/DependencyInjection/ContainerFactory.php

-2
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,8 @@ public function create(
114114
);
115115

116116
$configurator = new Configurator(new LoaderFactory(
117-
$this->fileHelper,
118117
$this->rootDirectory,
119118
$this->currentWorkingDirectory,
120-
$generateBaselineFile,
121119
), $this->journalContainer);
122120
$configurator->defaultExtensions = [
123121
'php' => PhpExtension::class,

src/DependencyInjection/LoaderFactory.php

+1-4
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,21 @@
33
namespace PHPStan\DependencyInjection;
44

55
use Nette\DI\Config\Loader;
6-
use PHPStan\File\FileHelper;
76
use function getenv;
87

98
final class LoaderFactory
109
{
1110

1211
public function __construct(
13-
private FileHelper $fileHelper,
1412
private string $rootDir,
1513
private string $currentWorkingDirectory,
16-
private ?string $generateBaselineFile,
1714
)
1815
{
1916
}
2017

2118
public function createLoader(): Loader
2219
{
23-
$loader = new NeonLoader($this->fileHelper, $this->generateBaselineFile);
20+
$loader = new Loader();
2421
$loader->addAdapter('dist', NeonAdapter::class);
2522
$loader->addAdapter('neon', NeonAdapter::class);
2623
$loader->setParameters([

src/DependencyInjection/NeonLoader.php

-35
This file was deleted.

tests/PHPStan/Analyser/AnalyserTest.php

+31-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,27 @@ public function testReturnErrorIfIgnoredMessagesDoesNotOccur(): void
5252
], $result);
5353
}
5454

55+
public function testDontReturnErrorIfIgnoredMessagesDoesNotOccurWhenGeneratingBaseline(): void
56+
{
57+
$result = $this->runAnalyser(['#Unknown error#'], false, __DIR__ . '/data/empty/empty.php', false, true);
58+
59+
$this->assertEmpty($result);
60+
}
61+
62+
public function testDontReturnErrorOnNewErrorWhenIgnoringNewErrors(): void
63+
{
64+
$result = $this->runAnalyser(['#Unknown error#'], false, __DIR__ . '/data/bootstrap-error.php', false, true, true);
65+
66+
$this->assertEmpty($result);
67+
}
68+
69+
public function testReturnErrorOnIgnoredErrorWhenIgnoringNewErrorsAndGeneratingBaseline(): void
70+
{
71+
$result = $this->runAnalyser(['#Fail\.#'], false, __DIR__ . '/data/bootstrap-error.php', false, true, true);
72+
73+
$this->assertNotEmpty($result);
74+
}
75+
5576
public function testDoNotReturnErrorIfIgnoredMessagesDoesNotOccurWithReportUnmatchedIgnoredErrorsOff(): void
5677
{
5778
$result = $this->runAnalyser(['#Unknown error#'], false, __DIR__ . '/data/empty/empty.php', false);
@@ -644,6 +665,8 @@ private function runAnalyser(
644665
bool $reportUnmatchedIgnoredErrors,
645666
$filePaths,
646667
bool $onlyFiles,
668+
bool $generateBaseline = false,
669+
bool $ignoreNewErrors = false,
647670
): array
648671
{
649672
$analyser = $this->createAnalyser();
@@ -679,7 +702,14 @@ private function runAnalyser(
679702
);
680703
$analyserResult = $finalizer->finalize($analyserResult, $onlyFiles, false)->getAnalyserResult();
681704

682-
$ignoredErrorHelperProcessedResult = $ignoredErrorHelperResult->process($analyserResult->getErrors(), $onlyFiles, $normalizedFilePaths, $analyserResult->hasReachedInternalErrorsCountLimit());
705+
$ignoredErrorHelperProcessedResult = $ignoredErrorHelperResult->process(
706+
$analyserResult->getErrors(),
707+
$onlyFiles,
708+
$normalizedFilePaths,
709+
$analyserResult->hasReachedInternalErrorsCountLimit(),
710+
$generateBaseline,
711+
$ignoreNewErrors,
712+
);
683713
$errors = $ignoredErrorHelperProcessedResult->getNotIgnoredErrors();
684714
$errors = array_merge($errors, $ignoredErrorHelperProcessedResult->getOtherIgnoreMessages());
685715
if ($analyserResult->hasReachedInternalErrorsCountLimit()) {

tests/PHPStan/Command/AnalyseApplicationIntegrationTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ private function runPath(string $path, int $expectedStatusCode): string
8585
null,
8686
null,
8787
$this->createMock(InputInterface::class),
88+
false,
89+
false,
8890
);
8991
$statusCode = $errorFormatter->formatErrors($analysisResult, $symfonyOutput);
9092

0 commit comments

Comments
 (0)