diff --git a/rules-tests/CodingStyle/Rector/ClassMethod/FuncGetArgsToVariadicParamRector/Fixture/in_method_or_static_call.php.inc b/rules-tests/CodingStyle/Rector/ClassMethod/FuncGetArgsToVariadicParamRector/Fixture/in_method_or_static_call.php.inc new file mode 100644 index 000000000000..e6481797b55c --- /dev/null +++ b/rules-tests/CodingStyle/Rector/ClassMethod/FuncGetArgsToVariadicParamRector/Fixture/in_method_or_static_call.php.inc @@ -0,0 +1,43 @@ +count($args = func_get_args(), 1); + Assert::count($args = func_get_args(), 1); + } + + private function count($args, $value) + { + Assert::count($args, $value); + } +} + +?> +----- +count($args, 1); + Assert::count($args, 1); + } + + private function count($args, $value) + { + Assert::count($args, $value); + } +} + +?> diff --git a/rules-tests/CodingStyle/Rector/ClassMethod/FuncGetArgsToVariadicParamRector/Fixture/in_method_or_static_call2.php.inc b/rules-tests/CodingStyle/Rector/ClassMethod/FuncGetArgsToVariadicParamRector/Fixture/in_method_or_static_call2.php.inc new file mode 100644 index 000000000000..6104b3f050f0 --- /dev/null +++ b/rules-tests/CodingStyle/Rector/ClassMethod/FuncGetArgsToVariadicParamRector/Fixture/in_method_or_static_call2.php.inc @@ -0,0 +1,61 @@ +count($args = func_get_args(), 1); + Assert::count($args = func_get_args(), 1); + }; + } + + public function run2(): void + { + function innerFunc() { + Assert::count($args = func_get_args(), 1); + }; + } + + private function count($args, $value) + { + Assert::count($args, $value); + } +} + +?> +----- +count($args, 1); + Assert::count($args, 1); + }; + } + + public function run2(): void + { + function innerFunc(...$args) { + Assert::count($args, 1); + }; + } + + private function count($args, $value) + { + Assert::count($args, $value); + } +} + +?> diff --git a/rules/CodingStyle/Rector/ClassMethod/FuncGetArgsToVariadicParamRector.php b/rules/CodingStyle/Rector/ClassMethod/FuncGetArgsToVariadicParamRector.php index 09f136edc5eb..5668a0a51bb4 100644 --- a/rules/CodingStyle/Rector/ClassMethod/FuncGetArgsToVariadicParamRector.php +++ b/rules/CodingStyle/Rector/ClassMethod/FuncGetArgsToVariadicParamRector.php @@ -5,15 +5,20 @@ namespace Rector\CodingStyle\Rector\ClassMethod; use PhpParser\Node; +use PhpParser\Node\Expr; use PhpParser\Node\Expr\Assign; use PhpParser\Node\Expr\Closure; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\Variable; +use PhpParser\Node\FunctionLike; use PhpParser\Node\Param; +use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\ClassMethod; +use PhpParser\Node\Stmt\Expression; use PhpParser\Node\Stmt\Function_; use Rector\Core\Rector\AbstractRector; use Rector\Core\ValueObject\PhpVersionFeature; +use Rector\NodeTypeResolver\Node\AttributeKey; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -77,12 +82,16 @@ public function refactor(Node $node): ?Node return null; } - $this->removeNode($assign); - } else { - $variableName = 'args'; - $assign->expr = new Variable('args'); + return $this->removeOrChangeAssignToVariable($node, $assign, $variableName); } + $variableName = 'args'; + $assign->expr = new Variable('args'); + return $this->applyVariadicParams($node, $assign, $variableName); + } + + private function applyVariadicParams(ClassMethod|Function_|Closure $node, Assign $assign, string $variableName): ?Node + { $param = $this->createVariadicParam($variableName); $variableParam = $param->var; if ($variableParam instanceof Variable && $this->hasFunctionOrClosureInside($node, $variableParam)) { @@ -93,6 +102,31 @@ public function refactor(Node $node): ?Node return $node; } + private function removeOrChangeAssignToVariable(ClassMethod|Function_|Closure $node, Assign $assign, string $variableName): ?Node + { + $parent = $assign->getAttribute(AttributeKey::PARENT_NODE); + if ($parent instanceof Expression) { + $this->removeNode($assign); + return $this->applyVariadicParams($node, $assign, $variableName); + } + + $variable = $assign->var; + /** @var ClassMethod|Function_|Closure $functionLike */ + $functionLike = $this->betterNodeFinder->findParentType($parent, FunctionLike::class); + /** @var Stmt[] $stmts */ + $stmts = $functionLike->getStmts(); + $this->traverseNodesWithCallable($stmts, function (Node $node) use ($assign, $variable): ?Expr { + if (! $this->nodeComparator->areNodesEqual($node, $assign)) { + return null; + } + + return $variable; + }); + + $this->applyVariadicParams($functionLike, $assign, $variableName); + return $node; + } + private function hasFunctionOrClosureInside( ClassMethod | Function_ | Closure $functionLike, Variable $variable