Skip to content

Commit d1a2026

Browse files
authored
Merge branch refs/heads/2.1.x into 2.2.x
2 parents 842777b + 5ed2f90 commit d1a2026

File tree

15 files changed

+119
-50
lines changed

15 files changed

+119
-50
lines changed

.github/workflows/e2e-tests.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,12 @@ jobs:
296296
- script: |
297297
cd e2e/nested-trait-use
298298
../../bin/phpstan analyze
299+
- script: |
300+
cd e2e/report-ignores-without-comments
301+
OUTPUT=$(../bashunit -a exit_code "1" "../../bin/phpstan --error-format=raw")
302+
echo "$OUTPUT"
303+
../bashunit -a contains 'test.php:4:Ignore with identifier variable.undefined has no comment' "$OUTPUT"
304+
../bashunit -a not_contains 'test.php:7' "$OUTPUT"
299305
300306
steps:
301307
- name: "Checkout"

conf/config.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ parameters:
118118
resolvedPhpDocBlockCacheCountMax: 2048
119119
nameScopeMapMemoryCacheCountMax: 2048
120120
reportUnmatchedIgnoredErrors: true
121+
reportIgnoresWithoutComments: false
121122
typeAliases: []
122123
universalObjectCratesClasses:
123124
- stdClass

conf/parametersSchema.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ parametersSchema:
143143
nameScopeMapMemoryCacheCountMax: int()
144144
])
145145
reportUnmatchedIgnoredErrors: bool()
146+
reportIgnoresWithoutComments: bool()
146147
typeAliases: arrayOf(string())
147148
universalObjectCratesClasses: listOf(string())
148149
stubFiles: listOf(string())
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
parameters:
2+
level: 5
3+
paths:
4+
- test.php
5+
reportIgnoresWithoutComments: true
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
// @phpstan-ignore variable.undefined
4+
echo $undefined;
5+
6+
// @phpstan-ignore variable.undefined (this one has a comment so no error)
7+
echo $anotherUndefined;

src/Analyser/AnalyserResultFinalizer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ private function addUnmatchedIgnoredErrors(
205205

206206
foreach ($identifiers as $identifier) {
207207
$errors[] = (new Error(
208-
sprintf('No error with identifier %s is reported on line %d.', $identifier, $line),
208+
sprintf('No error with identifier %s is reported on line %d.', $identifier['name'], $line),
209209
$file,
210210
$line,
211211
false,

src/Analyser/FileAnalyser.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public function __construct(
6060
private IgnoreErrorExtensionProvider $ignoreErrorExtensionProvider,
6161
private RuleErrorTransformer $ruleErrorTransformer,
6262
private LocalIgnoresProcessor $localIgnoresProcessor,
63+
#[AutowiredParameter]
64+
private bool $reportIgnoresWithoutComments,
6365
)
6466
{
6567
}
@@ -129,6 +131,32 @@ public function analyseFile(
129131
$temporaryFileErrors = $nodeCallback->getTemporaryFileErrors();
130132
$processedFiles = $nodeCallback->getProcessedFiles();
131133

134+
if ($this->reportIgnoresWithoutComments) {
135+
foreach ($linesToIgnore as $ignoredFile => $lines) {
136+
foreach ($lines as $line => $identifiers) {
137+
if ($identifiers === null) {
138+
continue;
139+
}
140+
141+
foreach ($identifiers as $identifier) {
142+
if ($identifier['comment'] !== null) {
143+
continue;
144+
}
145+
146+
$fileErrors[] = (new Error(
147+
sprintf('Ignore with identifier %s has no comment.', $identifier['name']),
148+
$ignoredFile,
149+
$line,
150+
false,
151+
$ignoredFile,
152+
null,
153+
'Explain why this ignore is necessary in parentheses after the identifier.',
154+
))->withIdentifier('ignore.noComment');
155+
}
156+
}
157+
}
158+
}
159+
132160
$localIgnoresProcessorResult = $this->localIgnoresProcessor->process(
133161
$temporaryFileErrors,
134162
$linesToIgnore,

src/Analyser/FileAnalyserCallback.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
/**
2323
* @phpstan-import-type CollectorData from CollectedData
24+
* @phpstan-import-type Identifier from FileAnalyserResult
2425
* @phpstan-import-type LinesToIgnore from FileAnalyserResult
2526
*/
2627
final class FileAnalyserCallback
@@ -231,15 +232,15 @@ public function __invoke(Node $node, Scope $scope): void
231232

232233
/**
233234
* @param Node[] $nodes
234-
* @return array<int, non-empty-list<string>|null>
235+
* @return array<int, non-empty-list<Identifier>|null>
235236
*/
236237
private function getLinesToIgnoreFromTokens(array $nodes): array
237238
{
238239
if (!isset($nodes[0])) {
239240
return [];
240241
}
241242

242-
/** @var array<int, non-empty-list<string>|null> */
243+
/** @var array<int, non-empty-list<Identifier>|null> */
243244
return $nodes[0]->getAttribute('linesToIgnore', []);
244245
}
245246

src/Analyser/FileAnalyserResult.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
use PHPStan\Dependency\RootExportedNode;
77

88
/**
9-
* @phpstan-type LinesToIgnore = array<string, array<int, non-empty-list<string>|null>>
9+
* @phpstan-type Identifier = array{name: string, comment: string|null}
10+
* @phpstan-type LinesToIgnore = array<string, array<int, non-empty-list<Identifier>|null>>
1011
* @phpstan-import-type CollectorData from CollectedData
1112
*/
1213
final class FileAnalyserResult

src/Analyser/LocalIgnoresProcessor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public function process(
4949
}
5050

5151
foreach ($identifiers as $i => $ignoredIdentifier) {
52-
if ($ignoredIdentifier !== $tmpFileError->getIdentifier()) {
52+
if ($ignoredIdentifier['name'] !== $tmpFileError->getIdentifier()) {
5353
continue;
5454
}
5555

@@ -68,7 +68,7 @@ public function process(
6868
$unmatchedIgnoredIdentifiers = $unmatchedLineIgnores[$tmpFileError->getFile()][$line];
6969
if (is_array($unmatchedIgnoredIdentifiers)) {
7070
foreach ($unmatchedIgnoredIdentifiers as $j => $unmatchedIgnoredIdentifier) {
71-
if ($ignoredIdentifier !== $unmatchedIgnoredIdentifier) {
71+
if ($ignoredIdentifier['name'] !== $unmatchedIgnoredIdentifier['name']) {
7272
continue;
7373
}
7474

0 commit comments

Comments
 (0)