Skip to content

Commit 6eec691

Browse files
committed
feat: add option to report ignores without identifiers
1 parent d4107e4 commit 6eec691

File tree

7 files changed

+93
-5
lines changed

7 files changed

+93
-5
lines changed

conf/config.neon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ parameters:
9696
cache:
9797
nodesByStringCountMax: 256
9898
reportUnmatchedIgnoredErrors: true
99+
reportIgnoresWithoutIdentifiers: false
99100
typeAliases: []
100101
universalObjectCratesClasses:
101102
- stdClass
@@ -199,6 +200,7 @@ parameters:
199200
- [parameters, errorFormat]
200201
- [parameters, ignoreErrors]
201202
- [parameters, reportUnmatchedIgnoredErrors]
203+
- [parameters, reportIgnoresWithoutIdentifiers]
202204
- [parameters, tipsOfTheDay]
203205
- [parameters, parallel]
204206
- [parameters, internalErrorsCountLimit]
@@ -463,6 +465,7 @@ services:
463465
class: PHPStan\Analyser\AnalyserResultFinalizer
464466
arguments:
465467
reportUnmatchedIgnoredErrors: %reportUnmatchedIgnoredErrors%
468+
reportIgnoresWithoutIdentifiers: %reportIgnoresWithoutIdentifiers%
466469

467470
-
468471
class: PHPStan\Analyser\FileAnalyser

conf/parametersSchema.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ parametersSchema:
144144
nodesByStringCountMax: int()
145145
])
146146
reportUnmatchedIgnoredErrors: bool()
147+
reportIgnoresWithoutIdentifiers: bool()
147148
typeAliases: arrayOf(string())
148149
universalObjectCratesClasses: listOf(string())
149150
stubFiles: listOf(string())

src/Analyser/AnalyserResultFinalizer.php

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,20 @@ public function __construct(
2424
private ScopeFactory $scopeFactory,
2525
private LocalIgnoresProcessor $localIgnoresProcessor,
2626
private bool $reportUnmatchedIgnoredErrors,
27+
private bool $reportIgnoresWithoutIdentifiers,
2728
)
2829
{
2930
}
3031

3132
public function finalize(AnalyserResult $analyserResult, bool $onlyFiles, bool $debug): FinalizerResult
3233
{
3334
if (count($analyserResult->getCollectedData()) === 0) {
34-
return $this->addUnmatchedIgnoredErrors($this->mergeFilteredPhpErrors($analyserResult), [], []);
35+
return $this->addUnmatchedIgnoredErrors($this->addIgnoresWithoutIdentifiersErrors($this->mergeFilteredPhpErrors($analyserResult)), [], []);
3536
}
3637

3738
$hasInternalErrors = count($analyserResult->getInternalErrors()) > 0 || $analyserResult->hasReachedInternalErrorsCountLimit();
3839
if ($hasInternalErrors) {
39-
return $this->addUnmatchedIgnoredErrors($this->mergeFilteredPhpErrors($analyserResult), [], []);
40+
return $this->addUnmatchedIgnoredErrors($this->addIgnoresWithoutIdentifiersErrors($this->mergeFilteredPhpErrors($analyserResult)), [], []);
4041
}
4142

4243
$nodeType = CollectedDataNode::class;
@@ -130,7 +131,7 @@ public function finalize(AnalyserResult $analyserResult, bool $onlyFiles, bool $
130131
$allUnmatchedLineIgnores[$file] = $localIgnoresProcessorResult->getUnmatchedLineIgnores();
131132
}
132133

133-
return $this->addUnmatchedIgnoredErrors(new AnalyserResult(
134+
return $this->addUnmatchedIgnoredErrors($this->addIgnoresWithoutIdentifiersErrors(new AnalyserResult(
134135
array_merge($errors, $analyserResult->getFilteredPhpErrors()),
135136
[],
136137
$analyserResult->getAllPhpErrors(),
@@ -144,7 +145,7 @@ public function finalize(AnalyserResult $analyserResult, bool $onlyFiles, bool $
144145
$analyserResult->getExportedNodes(),
145146
$analyserResult->hasReachedInternalErrorsCountLimit(),
146147
$analyserResult->getPeakMemoryUsageBytes(),
147-
), $collectorErrors, $locallyIgnoredCollectorErrors);
148+
)), $collectorErrors, $locallyIgnoredCollectorErrors);
148149
}
149150

150151
private function mergeFilteredPhpErrors(AnalyserResult $analyserResult): AnalyserResult
@@ -233,4 +234,49 @@ private function addUnmatchedIgnoredErrors(
233234
);
234235
}
235236

237+
private function addIgnoresWithoutIdentifiersErrors(AnalyserResult $analyserResult): AnalyserResult
238+
{
239+
if (!$this->reportIgnoresWithoutIdentifiers) {
240+
return $analyserResult;
241+
}
242+
243+
$errors = $analyserResult->getUnorderedErrors();
244+
foreach ($analyserResult->getLinesToIgnore() as $file => $data) {
245+
foreach ($data as $ignoredFile => $lines) {
246+
if ($ignoredFile !== $file) {
247+
continue;
248+
}
249+
250+
foreach ($lines as $line => $identifiers) {
251+
if ($identifiers !== null) {
252+
continue;
253+
}
254+
255+
$errors[] = (new Error(
256+
sprintf('Error is ignored with no identifiers on line %d.', $line),
257+
$file,
258+
$line,
259+
false,
260+
$file,
261+
))->withIdentifier('ignore.noIdentifier');
262+
}
263+
}
264+
}
265+
266+
return new AnalyserResult(
267+
$errors,
268+
$analyserResult->getFilteredPhpErrors(),
269+
$analyserResult->getAllPhpErrors(),
270+
$analyserResult->getLocallyIgnoredErrors(),
271+
$analyserResult->getLinesToIgnore(),
272+
$analyserResult->getUnmatchedLineIgnores(),
273+
$analyserResult->getInternalErrors(),
274+
$analyserResult->getCollectedData(),
275+
$analyserResult->getDependencies(),
276+
$analyserResult->getExportedNodes(),
277+
$analyserResult->hasReachedInternalErrorsCountLimit(),
278+
$analyserResult->getPeakMemoryUsageBytes(),
279+
);
280+
}
281+
236282
}

src/Command/FixerWorkerCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ function (array $errors, array $locallyIgnoredErrors, array $analysedFiles) use
310310
if ($error->getIdentifier() === null) {
311311
continue;
312312
}
313-
if (!in_array($error->getIdentifier(), ['ignore.count', 'ignore.unmatched', 'ignore.unmatchedLine', 'ignore.unmatchedIdentifier'], true)) {
313+
if (!in_array($error->getIdentifier(), ['ignore.count', 'ignore.unmatched', 'ignore.unmatchedLine', 'ignore.unmatchedIdentifier', 'ignore.noIdentifier'], true)) {
314314
continue;
315315
}
316316
$ignoreFileErrors[] = $error;

src/Testing/RuleTestCase.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ private function gatherAnalyserErrorsWithDelayedErrors(array $files): array
241241
$this->createScopeFactory($reflectionProvider, $this->getTypeSpecifier()),
242242
new LocalIgnoresProcessor(),
243243
true,
244+
false,
244245
);
245246

246247
return [

tests/PHPStan/Analyser/AnalyserTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,20 @@ public function testIgnoreNextLineUnmatched(): void
559559
}
560560
}
561561

562+
public function testIgnoresWithoutIdentifiersReported(): void
563+
{
564+
$result = $this->runAnalyser([], false, [
565+
__DIR__ . '/data/ignore-no-identifiers.php',
566+
], true, true);
567+
$this->assertCount(4, $result);
568+
foreach ([10, 12, 15, 18] as $i => $line) {
569+
$this->assertArrayHasKey($i, $result);
570+
$this->assertInstanceOf(Error::class, $result[$i]);
571+
$this->assertStringContainsString('Error is ignored with no identifiers on line', $result[$i]->getMessage());
572+
$this->assertSame($line, $result[$i]->getLine());
573+
}
574+
}
575+
562576
/**
563577
* @dataProvider dataTrueAndFalse
564578
*/
@@ -645,6 +659,7 @@ private function runAnalyser(
645659
bool $reportUnmatchedIgnoredErrors,
646660
$filePaths,
647661
bool $onlyFiles,
662+
bool $reportIgnoresWithoutIdentifiers = false,
648663
): array
649664
{
650665
$analyser = $this->createAnalyser();
@@ -677,6 +692,7 @@ private function runAnalyser(
677692
),
678693
new LocalIgnoresProcessor(),
679694
$reportUnmatchedIgnoredErrors,
695+
$reportIgnoresWithoutIdentifiers,
680696
);
681697
$analyserResult = $finalizer->finalize($analyserResult, $onlyFiles, false)->getAnalyserResult();
682698

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace IgnoreNoIdentifiers;
4+
5+
class Foo
6+
{
7+
8+
public function doFoo(): void
9+
{
10+
fail(); // @phpstan-ignore-line
11+
12+
succ(); /** @phpstan-ignore-line reported as unmatched */
13+
14+
// @phpstan-ignore-next-line
15+
fail();
16+
17+
/** @phpstan-ignore-next-line reported as unmatched */
18+
succ();
19+
}
20+
21+
}

0 commit comments

Comments
 (0)