Skip to content

Commit d728a1f

Browse files
committed
Extract new UselessFunctionReturnValueRule
1 parent f45fbbd commit d728a1f

File tree

6 files changed

+130
-60
lines changed

6 files changed

+130
-60
lines changed

conf/config.level0.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ rules:
7070
- PHPStan\Rules\Functions\DefineParametersRule
7171
- PHPStan\Rules\Functions\ExistingClassesInArrowFunctionTypehintsRule
7272
- PHPStan\Rules\Functions\CallToFunctionParametersRule
73+
- PHPStan\Rules\Functions\UselessFunctionReturnValueRule
7374
- PHPStan\Rules\Functions\ExistingClassesInClosureTypehintsRule
7475
- PHPStan\Rules\Functions\ExistingClassesInTypehintsRule
7576
- PHPStan\Rules\Functions\FunctionAttributesRule

src/Rules/FunctionCallParametersCheck.php

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
use PhpParser\Node;
66
use PhpParser\Node\Expr;
7-
use PHPStan\Analyser\ArgumentsNormalizer;
87
use PHPStan\Analyser\MutatingScope;
98
use PHPStan\Analyser\Scope;
109
use PHPStan\Php\PhpVersion;
@@ -30,7 +29,6 @@
3029
use function array_key_exists;
3130
use function count;
3231
use function implode;
33-
use function in_array;
3432
use function is_string;
3533
use function max;
3634
use function sprintf;
@@ -55,7 +53,7 @@ public function __construct(
5553

5654
/**
5755
* @param Node\Expr\FuncCall|Node\Expr\MethodCall|Node\Expr\StaticCall|Node\Expr\New_ $funcCall
58-
* @param array{0: string, 1: string, 2: string, 3: string, 4: string, 5: string, 6: string, 7: string, 8: string, 9: string, 10: string, 11: string, 12: string, 13?: string, 14?: string} $messages
56+
* @param array{0: string, 1: string, 2: string, 3: string, 4: string, 5: string, 6: string, 7: string, 8: string, 9: string, 10: string, 11: string, 12: string, 13?: string} $messages
5957
* @param 'attribute'|'callable'|'method'|'staticMethod'|'function'|'new' $nodeType
6058
* @return list<IdentifierRuleError>
6159
*/
@@ -246,30 +244,6 @@ public function check(
246244
->build();
247245
}
248246

249-
if (
250-
$funcCall instanceof Expr\FuncCall
251-
&& isset($messages[14])
252-
&& !$scope->isInFirstLevelStatement()
253-
&& $funcCall->name instanceof Node\Name
254-
&& in_array($funcCall->name->toString(), ['var_export', 'print_r', 'highlight_string', 'highlight_file'], true)
255-
) {
256-
$reorderedFuncCall = ArgumentsNormalizer::reorderFuncArguments(
257-
$parametersAcceptor,
258-
$funcCall,
259-
);
260-
261-
if ($reorderedFuncCall !== null) {
262-
$reorderedArgs = $reorderedFuncCall->getArgs();
263-
264-
if (count($reorderedArgs) === 1 || (count($reorderedArgs) >= 2 && $scope->getType($reorderedArgs[1]->value)->isFalse()->yes())) {
265-
$errors[] = RuleErrorBuilder::message($messages[14])
266-
->identifier(sprintf('%s.uselessReturn', $nodeType))
267-
->line($funcCall->getStartLine())
268-
->build();
269-
}
270-
}
271-
}
272-
273247
[$addedErrors, $argumentsWithParameters] = $this->processArguments($parametersAcceptor, $funcCall->getStartLine(), $isBuiltin, $arguments, $hasNamedArguments, $messages[10], $messages[11]);
274248
foreach ($addedErrors as $error) {
275249
$errors[] = $error;

src/Rules/Functions/CallToFunctionParametersRule.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ public function processNode(Node $node, Scope $scope): array
6464
'Unknown parameter $%s in call to function ' . $functionName . '.',
6565
'Return type of call to function ' . $functionName . ' contains unresolvable type.',
6666
'Parameter %s of function ' . $functionName . ' contains unresolvable type.',
67-
'Return value of call to function ' . $functionName . ' is useless.',
6867
],
6968
'function',
7069
);
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Functions;
4+
5+
use PhpParser\Node;
6+
use PhpParser\Node\Expr\FuncCall;
7+
use PHPStan\Analyser\ArgumentsNormalizer;
8+
use PHPStan\Analyser\Scope;
9+
use PHPStan\Reflection\ParametersAcceptorSelector;
10+
use PHPStan\Reflection\ReflectionProvider;
11+
use PHPStan\Rules\Rule;
12+
use PHPStan\Rules\RuleErrorBuilder;
13+
use function count;
14+
use function in_array;
15+
16+
/**
17+
* @implements Rule<Node\Expr\FuncCall>
18+
*/
19+
class UselessFunctionReturnValueRule implements Rule
20+
{
21+
22+
public function __construct(private ReflectionProvider $reflectionProvider)
23+
{
24+
}
25+
26+
public function getNodeType(): string
27+
{
28+
return FuncCall::class;
29+
}
30+
31+
public function processNode(Node $funcCall, Scope $scope): array
32+
{
33+
if (!($funcCall->name instanceof Node\Name) || $scope->isInFirstLevelStatement()) {
34+
return [];
35+
}
36+
37+
if (!$this->reflectionProvider->hasFunction($funcCall->name, $scope)) {
38+
return [];
39+
}
40+
41+
$functionReflection = $this->reflectionProvider->getFunction($funcCall->name, $scope);
42+
43+
if (!in_array($functionReflection->getName(), ['var_export', 'print_r', 'highlight_string', 'highlight_file'], true)) {
44+
return [];
45+
}
46+
$parametersAcceptor = ParametersAcceptorSelector::selectFromArgs(
47+
$scope,
48+
$funcCall->getArgs(),
49+
$functionReflection->getVariants(),
50+
$functionReflection->getNamedArgumentsVariants(),
51+
);
52+
53+
$reorderedFuncCall = ArgumentsNormalizer::reorderFuncArguments(
54+
$parametersAcceptor,
55+
$funcCall,
56+
);
57+
58+
if ($reorderedFuncCall === null) {
59+
return [];
60+
}
61+
$reorderedArgs = $reorderedFuncCall->getArgs();
62+
63+
if (count($reorderedArgs) === 1 || (count($reorderedArgs) >= 2 && $scope->getType($reorderedArgs[1]->value)->isFalse()->yes())) {
64+
return [RuleErrorBuilder::message('Return value of call to function ' . $functionReflection->getName() . ' is useless.')
65+
->identifier('functionReflection.uselessReturn')
66+
->line($funcCall->getStartLine())
67+
->build(),
68+
];
69+
}
70+
71+
return [];
72+
}
73+
74+
}

tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,36 +1716,4 @@ public function testCountArrayShift(): void
17161716
$this->analyse([__DIR__ . '/data/count-array-shift.php'], $errors);
17171717
}
17181718

1719-
public function testUselessReturnValue(): void
1720-
{
1721-
$this->analyse([__DIR__ . '/data/useless-fn-return.php'], [
1722-
[
1723-
'Return value of call to function print_r is useless.',
1724-
47,
1725-
],
1726-
[
1727-
'Return value of call to function var_export is useless.',
1728-
56,
1729-
],
1730-
[
1731-
'Return value of call to function print_r is useless.',
1732-
64,
1733-
],
1734-
]);
1735-
}
1736-
1737-
public function testUselessReturnValuePhp8(): void
1738-
{
1739-
if (PHP_VERSION_ID < 80000) {
1740-
return;
1741-
}
1742-
1743-
$this->analyse([__DIR__ . '/data/useless-fn-return-php8.php'], [
1744-
[
1745-
'Return value of call to function print_r is useless.',
1746-
18,
1747-
],
1748-
]);
1749-
}
1750-
17511719
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Functions;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Testing\RuleTestCase;
7+
use const PHP_VERSION_ID;
8+
9+
/**
10+
* @extends RuleTestCase<UselessFunctionReturnValueRule>
11+
*/
12+
class UselessFunctionReturnValueRuleTest extends RuleTestCase
13+
{
14+
15+
protected function getRule(): Rule
16+
{
17+
return new UselessFunctionReturnValueRule(
18+
$this->createReflectionProvider(),
19+
);
20+
}
21+
22+
public function testUselessReturnValue(): void
23+
{
24+
$this->analyse([__DIR__ . '/data/useless-fn-return.php'], [
25+
[
26+
'Return value of call to function print_r is useless.',
27+
47,
28+
],
29+
[
30+
'Return value of call to function var_export is useless.',
31+
56,
32+
],
33+
[
34+
'Return value of call to function print_r is useless.',
35+
64,
36+
],
37+
]);
38+
}
39+
40+
public function testUselessReturnValuePhp8(): void
41+
{
42+
if (PHP_VERSION_ID < 80000) {
43+
return;
44+
}
45+
46+
$this->analyse([__DIR__ . '/data/useless-fn-return-php8.php'], [
47+
[
48+
'Return value of call to function print_r is useless.',
49+
18,
50+
],
51+
]);
52+
}
53+
54+
}

0 commit comments

Comments
 (0)