Skip to content

Commit 702d577

Browse files
committed
RuleErrorFilterExtension
This allows for more flexibility in filtering errors. Some use cases: * Ignore `missingType.iterableValue` on controller actions: Rule: when the method is public and it has `#[Route]` attribute or the class has `#[AsController]` attribute. * Ignore `should return int but returns int|null` on `getId` for entities. Rule: class needs to have `#[Entity]` attribute. * Ignore `never returns null so it can be removed from the return type` Rule: method needs to have `#[GraphQL\Field]` attribute.
1 parent 46b9819 commit 702d577

File tree

4 files changed

+90
-0
lines changed

4 files changed

+90
-0
lines changed

src/Analyser/AnalyserResultFinalizer.php

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ final class AnalyserResultFinalizer
1919

2020
public function __construct(
2121
private RuleRegistry $ruleRegistry,
22+
private RuleErrorFilter $ruleErrorFilter,
2223
private RuleErrorTransformer $ruleErrorTransformer,
2324
private ScopeFactory $scopeFactory,
2425
private LocalIgnoresProcessor $localIgnoresProcessor,
@@ -87,6 +88,8 @@ public function finalize(AnalyserResult $analyserResult, bool $onlyFiles, bool $
8788
continue;
8889
}
8990

91+
$ruleErrors = $this->ruleErrorFilter->filter($ruleErrors, $node, $scope);
92+
9093
foreach ($ruleErrors as $ruleError) {
9194
$tempCollectorErrors[] = $this->ruleErrorTransformer->transform($ruleError, $scope, $nodeType, $node->getStartLine());
9295
}

src/Analyser/FileAnalyser.php

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public function __construct(
5151
private NodeScopeResolver $nodeScopeResolver,
5252
private Parser $parser,
5353
private DependencyResolver $dependencyResolver,
54+
private RuleErrorFilter $ruleErrorFilter,
5455
private RuleErrorTransformer $ruleErrorTransformer,
5556
private LocalIgnoresProcessor $localIgnoresProcessor,
5657
)
@@ -141,6 +142,8 @@ public function analyseFile(
141142
continue;
142143
}
143144

145+
$ruleErrors = $this->ruleErrorFilter->filter($ruleErrors, $node, $scope);
146+
144147
foreach ($ruleErrors as $ruleError) {
145148
$temporaryFileErrors[] = $this->ruleErrorTransformer->transform($ruleError, $scope, $nodeType, $node->getStartLine());
146149
}

src/Analyser/RuleErrorFilter.php

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser;
4+
5+
use PhpParser\Node;
6+
use PHPStan\DependencyInjection\Container;
7+
use PHPStan\Rules\RuleError;
8+
use PHPStan\Rules\RuleErrorFilterExtension;
9+
10+
final class RuleErrorFilter
11+
{
12+
13+
public function __construct(private Container $container)
14+
{
15+
}
16+
17+
/**
18+
* @param RuleError[] $ruleErrors
19+
* @return RuleError[]
20+
*/
21+
public function filter(
22+
array $ruleErrors,
23+
Node $node,
24+
Scope $scope,
25+
): array
26+
{
27+
if ($ruleErrors === []) {
28+
return [];
29+
}
30+
31+
$extensions = $this->container->getServicesByTag(RuleErrorFilterExtension::EXTENSION_TAG);
32+
33+
foreach ($extensions as $extension) {
34+
if (!$extension instanceof RuleErrorFilterExtension) {
35+
continue;
36+
}
37+
38+
$ruleErrors = array_filter(
39+
$ruleErrors,
40+
static fn (RuleError $ruleError): bool => !$extension->filter($ruleError, $node, $scope)
41+
);
42+
43+
if ($ruleErrors === []) {
44+
break;
45+
}
46+
}
47+
48+
return $ruleErrors;
49+
}
50+
51+
}
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules;
4+
5+
use PHPStan\Analyser\Scope;
6+
use PhpParser\Node;
7+
8+
/**
9+
* This is the extension interface to implement if you want to filter out rule
10+
* errors based on the node and scope.
11+
*
12+
* To register it in the configuration file use the `phpstan.ruleErrorFilterExtension` service tag:
13+
*
14+
* ```
15+
* services:
16+
* -
17+
* class: App\PHPStan\MyExtension
18+
* tags:
19+
* - phpstan.ruleErrorFilterExtension
20+
* ```
21+
*
22+
* Learn more: https://phpstan.org
23+
*
24+
* @api
25+
*/
26+
interface RuleErrorFilterExtension
27+
{
28+
29+
public const EXTENSION_TAG = 'phpstan.ruleErrorFilterExtension';
30+
31+
public function filter(RuleError $ruleError, Node $node, Scope $scope): bool;
32+
33+
}

0 commit comments

Comments
 (0)