diff --git a/rules.neon b/rules.neon index 7a63c4e..b68d905 100644 --- a/rules.neon +++ b/rules.neon @@ -130,6 +130,8 @@ conditionalTags: phpstan.rules.rule: %strictRules.strictFunctionCalls% PHPStan\Rules\SwitchConditions\MatchingTypeInSwitchCaseConditionRule: phpstan.rules.rule: %strictRules.switchConditionsMatchingType% + PHPStan\Rules\VariableVariables\VariableFunctionCallRule: + phpstan.rules.rule: %strictRules.noVariableVariables% PHPStan\Rules\VariableVariables\VariableMethodCallRule: phpstan.rules.rule: %strictRules.noVariableVariables% PHPStan\Rules\VariableVariables\VariableMethodCallableRule: @@ -282,6 +284,9 @@ services: - class: PHPStan\Rules\SwitchConditions\MatchingTypeInSwitchCaseConditionRule + - + class: PHPStan\Rules\VariableVariables\VariableFunctionCallRule + - class: PHPStan\Rules\VariableVariables\VariableMethodCallRule diff --git a/src/Rules/VariableVariables/VariableFunctionCallRule.php b/src/Rules/VariableVariables/VariableFunctionCallRule.php new file mode 100644 index 0000000..102a3c2 --- /dev/null +++ b/src/Rules/VariableVariables/VariableFunctionCallRule.php @@ -0,0 +1,38 @@ + + */ +class VariableFunctionCallRule implements Rule +{ + + public function getNodeType(): string + { + return FuncCall::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if (!$node->name instanceof Node\Expr) { + return []; + } + + $type = $scope->getType($node->name); + if (!$type->isString()->yes() && !$type->isArray()->yes()) { + return []; + } + + return [ + RuleErrorBuilder::message('Variable function call.')->identifier('function.dynamicName')->build(), + ]; + } + +} diff --git a/tests/Rules/VariableVariables/VariableFunctionCallRuleTest.php b/tests/Rules/VariableVariables/VariableFunctionCallRuleTest.php new file mode 100644 index 0000000..1a01479 --- /dev/null +++ b/tests/Rules/VariableVariables/VariableFunctionCallRuleTest.php @@ -0,0 +1,41 @@ + + */ +class VariableFunctionCallRuleTest extends RuleTestCase +{ + + protected function getRule(): Rule + { + return new VariableFunctionCallRule(); + } + + public function testRule(): void + { + $this->analyse([__DIR__ . '/data/functions.php'], [ + [ + 'Variable function call.', + 6, + ], + [ + 'Variable function call.', + 14, + ], + [ + 'Variable function call.', + 16, + ], + [ + 'Variable function call.', + 18, + ], + ]); + } + +} diff --git a/tests/Rules/VariableVariables/data/functions.php b/tests/Rules/VariableVariables/data/functions.php new file mode 100644 index 0000000..0197a81 --- /dev/null +++ b/tests/Rules/VariableVariables/data/functions.php @@ -0,0 +1,19 @@ += 8.1 + +function (callable $a, string $b) { + time(); + $a(); + $b(); + $c = function () {}; + $c(); + $d = fn ($a) => $a; + $d(); + $e = time(...); + $e(); + $f = 'time'; + $f(); + $g = ['PDO', 'connect']; + $g(); + $h = ['PDO', $b]; + $h(); +};