Skip to content

Commit 911604c

Browse files
committed
Add VariableFunctionCallRule
1 parent 6b78d53 commit 911604c

File tree

4 files changed

+103
-0
lines changed

4 files changed

+103
-0
lines changed

rules.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ conditionalTags:
130130
phpstan.rules.rule: %strictRules.strictFunctionCalls%
131131
PHPStan\Rules\SwitchConditions\MatchingTypeInSwitchCaseConditionRule:
132132
phpstan.rules.rule: %strictRules.switchConditionsMatchingType%
133+
PHPStan\Rules\VariableVariables\VariableFunctionCallRule:
134+
phpstan.rules.rule: %strictRules.noVariableVariables%
133135
PHPStan\Rules\VariableVariables\VariableMethodCallRule:
134136
phpstan.rules.rule: %strictRules.noVariableVariables%
135137
PHPStan\Rules\VariableVariables\VariableMethodCallableRule:
@@ -282,6 +284,9 @@ services:
282284
-
283285
class: PHPStan\Rules\SwitchConditions\MatchingTypeInSwitchCaseConditionRule
284286

287+
-
288+
class: PHPStan\Rules\VariableVariables\VariableFunctionCallRule
289+
285290
-
286291
class: PHPStan\Rules\VariableVariables\VariableMethodCallRule
287292

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\VariableVariables;
4+
5+
use PhpParser\Node;
6+
use PhpParser\Node\Expr\FuncCall;
7+
use PHPStan\Analyser\Scope;
8+
use PHPStan\Rules\Rule;
9+
use PHPStan\Rules\RuleErrorBuilder;
10+
11+
/**
12+
* @implements Rule<FuncCall>
13+
*/
14+
class VariableFunctionCallRule implements Rule
15+
{
16+
17+
public function getNodeType(): string
18+
{
19+
return FuncCall::class;
20+
}
21+
22+
public function processNode(Node $node, Scope $scope): array
23+
{
24+
if (!$node->name instanceof Node\Expr) {
25+
return [];
26+
}
27+
28+
$type = $scope->getType($node->name);
29+
if (!$type->isString()->yes() && $type->isArray()->no()) {
30+
return [];
31+
}
32+
33+
return [
34+
RuleErrorBuilder::message('Variable function call.')->identifier('function.dynamicName')->build(),
35+
];
36+
}
37+
38+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\VariableVariables;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Testing\RuleTestCase;
7+
8+
/**
9+
* @extends RuleTestCase<VariableFunctionCallRule>
10+
*/
11+
class VariableFunctionCallRuleTest extends RuleTestCase
12+
{
13+
14+
protected function getRule(): Rule
15+
{
16+
return new VariableFunctionCallRule();
17+
}
18+
19+
public function testRule(): void
20+
{
21+
$this->analyse([__DIR__ . '/data/functions.php'], [
22+
[
23+
'Variable function call.',
24+
6,
25+
],
26+
[
27+
'Variable function call.',
28+
14,
29+
],
30+
[
31+
'Variable function call.',
32+
16,
33+
],
34+
[
35+
'Variable function call.',
36+
18,
37+
],
38+
]);
39+
}
40+
41+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php // lint >= 8.1
2+
3+
function (callable $a, string $b) {
4+
time();
5+
$a();
6+
$b();
7+
$c = function () {};
8+
$c();
9+
$d = fn ($a) => $a;
10+
$d();
11+
$e = time(...);
12+
$e();
13+
$f = 'time';
14+
$f();
15+
$g = ['PDO', 'connect'];
16+
$g();
17+
$h = ['PDO', $b];
18+
$h();
19+
};

0 commit comments

Comments
 (0)