Skip to content

Commit 7d11012

Browse files
authored
Bleeding edge - UnusedFunctionParametersCheck: report precise line
1 parent f6c556f commit 7d11012

8 files changed

+55
-27
lines changed

conf/bleedingEdge.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ parameters:
44
checkParameterCastableToNumberFunctions: true
55
skipCheckGenericClasses!: []
66
stricterFunctionMap: true
7+
reportPreciseLineForUnusedFunctionParameter: true

conf/config.neon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ parameters:
2525
checkParameterCastableToNumberFunctions: false
2626
skipCheckGenericClasses: []
2727
stricterFunctionMap: false
28+
reportPreciseLineForUnusedFunctionParameter: false
2829
fileExtensions:
2930
- php
3031
checkAdvancedIsset: false
@@ -1043,6 +1044,8 @@ services:
10431044

10441045
-
10451046
class: PHPStan\Rules\UnusedFunctionParametersCheck
1047+
arguments:
1048+
reportExactLine: %featureToggles.reportPreciseLineForUnusedFunctionParameter%
10461049

10471050
-
10481051
class: PHPStan\Rules\TooWideTypehints\TooWideParameterOutTypeCheck

conf/parametersSchema.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ parametersSchema:
3131
checkParameterCastableToNumberFunctions: bool(),
3232
skipCheckGenericClasses: listOf(string()),
3333
stricterFunctionMap: bool()
34+
reportPreciseLineForUnusedFunctionParameter: bool()
3435
])
3536
fileExtensions: listOf(string())
3637
checkAdvancedIsset: bool()

src/Rules/Classes/UnusedConstructorParametersRule.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use function array_map;
1616
use function array_values;
1717
use function count;
18-
use function is_string;
1918
use function sprintf;
2019
use function strtolower;
2120

@@ -56,11 +55,11 @@ public function processNode(Node $node, Scope $scope): array
5655

5756
return $this->check->getUnusedParameters(
5857
$scope,
59-
array_map(static function (Param $parameter): string {
60-
if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) {
58+
array_map(static function (Param $parameter): Variable {
59+
if (!$parameter->var instanceof Variable) {
6160
throw new ShouldNotHappenException();
6261
}
63-
return $parameter->var->name;
62+
return $parameter->var;
6463
}, array_values(array_filter($originalNode->params, static fn (Param $parameter): bool => $parameter->flags === 0))),
6564
$originalNode->stmts,
6665
$message,

src/Rules/Functions/UnusedClosureUsesRule.php

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66
use PHPStan\Analyser\Scope;
77
use PHPStan\Rules\Rule;
88
use PHPStan\Rules\UnusedFunctionParametersCheck;
9-
use PHPStan\ShouldNotHappenException;
109
use function array_map;
1110
use function count;
12-
use function is_string;
1311

1412
/**
1513
* @implements Rule<Node\Expr\Closure>
@@ -34,12 +32,7 @@ public function processNode(Node $node, Scope $scope): array
3432

3533
return $this->check->getUnusedParameters(
3634
$scope,
37-
array_map(static function (Node\ClosureUse $use): string {
38-
if (!is_string($use->var->name)) {
39-
throw new ShouldNotHappenException();
40-
}
41-
return $use->var->name;
42-
}, $node->uses),
35+
array_map(static fn (Node\ClosureUse $use): Node\Expr\Variable => $use->var, $node->uses),
4336
$node->stmts,
4437
'Anonymous function has an unused use $%s.',
4538
'closure.unusedUse',

src/Rules/UnusedFunctionParametersCheck.php

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
namespace PHPStan\Rules;
44

55
use PhpParser\Node;
6+
use PhpParser\Node\Expr\Variable;
67
use PHPStan\Analyser\Scope;
78
use PHPStan\Reflection\ReflectionProvider;
9+
use PHPStan\ShouldNotHappenException;
810
use PHPStan\Type\Constant\ConstantStringType;
9-
use function array_fill_keys;
10-
use function array_keys;
11+
use function array_combine;
12+
use function array_map;
1113
use function array_merge;
1214
use function is_array;
1315
use function is_string;
@@ -16,25 +18,34 @@
1618
final class UnusedFunctionParametersCheck
1719
{
1820

19-
public function __construct(private ReflectionProvider $reflectionProvider)
21+
public function __construct(
22+
private ReflectionProvider $reflectionProvider,
23+
private bool $reportExactLine,
24+
)
2025
{
2126
}
2227

2328
/**
24-
* @param string[] $parameterNames
29+
* @param Variable[] $parameterVars
2530
* @param Node[] $statements
2631
* @param 'constructor.unusedParameter'|'closure.unusedUse' $identifier
2732
* @return list<IdentifierRuleError>
2833
*/
2934
public function getUnusedParameters(
3035
Scope $scope,
31-
array $parameterNames,
36+
array $parameterVars,
3237
array $statements,
3338
string $unusedParameterMessage,
3439
string $identifier,
3540
): array
3641
{
37-
$unusedParameters = array_fill_keys($parameterNames, true);
42+
$parameterNames = array_map(static function (Variable $variable): string {
43+
if (!is_string($variable->name)) {
44+
throw new ShouldNotHappenException();
45+
}
46+
return $variable->name;
47+
}, $parameterVars);
48+
$unusedParameters = array_combine($parameterNames, $parameterVars);
3849
foreach ($this->getUsedVariables($scope, $statements) as $variableName) {
3950
if (!isset($unusedParameters[$variableName])) {
4051
continue;
@@ -43,10 +54,12 @@ public function getUnusedParameters(
4354
unset($unusedParameters[$variableName]);
4455
}
4556
$errors = [];
46-
foreach (array_keys($unusedParameters) as $name) {
47-
$errors[] = RuleErrorBuilder::message(
48-
sprintf($unusedParameterMessage, $name),
49-
)->identifier($identifier)->build();
57+
foreach ($unusedParameters as $name => $variable) {
58+
$errorBuilder = RuleErrorBuilder::message(sprintf($unusedParameterMessage, $name))->identifier($identifier);
59+
if ($this->reportExactLine) {
60+
$errorBuilder->line($variable->getStartLine());
61+
}
62+
$errors[] = $errorBuilder->build();
5063
}
5164

5265
return $errors;
@@ -66,7 +79,7 @@ private function getUsedVariables(Scope $scope, $node): array
6679
return $scope->getDefinedVariables();
6780
}
6881
}
69-
if ($node instanceof Node\Expr\Variable && is_string($node->name) && $node->name !== 'this') {
82+
if ($node instanceof Variable && is_string($node->name) && $node->name !== 'this') {
7083
return [$node->name];
7184
}
7285
if ($node instanceof Node\ClosureUse && is_string($node->var->name)) {

tests/PHPStan/Rules/Classes/UnusedConstructorParametersRuleTest.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,19 @@
1212
class UnusedConstructorParametersRuleTest extends RuleTestCase
1313
{
1414

15+
private bool $reportExactLine = true;
16+
1517
protected function getRule(): Rule
1618
{
1719
return new UnusedConstructorParametersRule(new UnusedFunctionParametersCheck(
1820
$this->createReflectionProvider(),
21+
$this->reportExactLine,
1922
));
2023
}
2124

22-
public function testUnusedConstructorParameters(): void
25+
public function testUnusedConstructorParametersNoExactLine(): void
2326
{
27+
$this->reportExactLine = false;
2428
$this->analyse([__DIR__ . '/data/unused-constructor-parameters.php'], [
2529
[
2630
'Constructor of class UnusedConstructorParameters\Foo has an unused parameter $unusedParameter.',
@@ -33,6 +37,20 @@ public function testUnusedConstructorParameters(): void
3337
]);
3438
}
3539

40+
public function testUnusedConstructorParameters(): void
41+
{
42+
$this->analyse([__DIR__ . '/data/unused-constructor-parameters.php'], [
43+
[
44+
'Constructor of class UnusedConstructorParameters\Foo has an unused parameter $unusedParameter.',
45+
19,
46+
],
47+
[
48+
'Constructor of class UnusedConstructorParameters\Foo has an unused parameter $anotherUnusedParameter.',
49+
20,
50+
],
51+
]);
52+
}
53+
3654
public function testPromotedProperties(): void
3755
{
3856
$this->analyse([__DIR__ . '/data/unused-constructor-parameters-promoted-properties.php'], []);

tests/PHPStan/Rules/Functions/UnusedClosureUsesRuleTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,19 @@ class UnusedClosureUsesRuleTest extends RuleTestCase
1414

1515
protected function getRule(): Rule
1616
{
17-
return new UnusedClosureUsesRule(new UnusedFunctionParametersCheck($this->createReflectionProvider()));
17+
return new UnusedClosureUsesRule(new UnusedFunctionParametersCheck($this->createReflectionProvider(), true));
1818
}
1919

2020
public function testUnusedClosureUses(): void
2121
{
2222
$this->analyse([__DIR__ . '/data/unused-closure-uses.php'], [
2323
[
2424
'Anonymous function has an unused use $unused.',
25-
3,
25+
6,
2626
],
2727
[
2828
'Anonymous function has an unused use $anotherUnused.',
29-
3,
29+
7,
3030
],
3131
[
3232
'Anonymous function has an unused use $usedInClosureUse.',

0 commit comments

Comments
 (0)