diff --git a/README.md b/README.md index f172f4a..f47633e 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ return static function (RectorConfig $rectorConfig): void { }; ``` -`ALLOW_NAMED_VARIADIC_ARGUMENTS` is enabled by default. If you set it to `false`, calls that include variadic arguments are skipped. +`ALLOW_NAMED_VARIADIC_ARGUMENTS` is enabled by default. For user-defined callables, the rule may still synthesize names for variadic entries (for example `values1`, `values2`), because PHP accepts unknown named arguments there and forwards them into the variadic parameter. Internal/native variadic callables such as `sprintf()` are skipped when a variadic tail is actually passed, because PHP rejects unknown named parameters there and named arguments also cannot be followed by positional ones. If you set it to `false`, calls that include variadic arguments are skipped entirely. #### Implementing Your Own Strategy diff --git a/src/AddNamedArgumentsRector.php b/src/AddNamedArgumentsRector.php index 8cedcda..553eae8 100644 --- a/src/AddNamedArgumentsRector.php +++ b/src/AddNamedArgumentsRector.php @@ -103,11 +103,20 @@ public function refactor(Node $node): ?Node return null; } - if (! $this->allowNamedVariadicArguments && $this->hasVariadicArguments($node, $parameters)) { + $hasVariadicArguments = $this->hasVariadicArguments($node, $parameters); + if (! $this->allowNamedVariadicArguments && $hasVariadicArguments) { return null; } - $hasChanges = $this->addNamesToArgs(node: $node, parameters: $parameters); + $functionReflection = Reflection::getFunctionReflection(node: $node, classReflection: $classReflection); + if ($hasVariadicArguments && ($functionReflection?->isInternal() ?? false)) { + return null; + } + + $hasChanges = $this->addNamesToArgs( + node: $node, + parameters: $parameters, + ); if (! $hasChanges) { return null; @@ -152,9 +161,13 @@ private function addNamesToArgs( $variadicArgCounters[$variadicParameterName] = $variadicIndex; $arg->name = new Identifier(name: $variadicParameterName . $variadicIndex); - } else { - $arg->name = new Identifier(name: $parameter->getName()); + $namedArgs[] = $arg; + $hasChanges = true; + + continue; } + + $arg->name = new Identifier(name: $parameter->getName()); $namedArgs[] = $arg; $hasChanges = true; } diff --git a/tests/DefaultStrategy/Fixture/internal_variadic.php.inc b/tests/DefaultStrategy/Fixture/internal_variadic.php.inc new file mode 100644 index 0000000..cb79daf --- /dev/null +++ b/tests/DefaultStrategy/Fixture/internal_variadic.php.inc @@ -0,0 +1,11 @@ + 1], ['b' => 2], ['c' => 3]); + +?> +----- + 1], ['b' => 2], ['c' => 3]); + +?> diff --git a/tests/DefaultStrategy/Fixture/userland_variadic_function.php.inc b/tests/DefaultStrategy/Fixture/userland_variadic_function.php.inc new file mode 100644 index 0000000..af98583 --- /dev/null +++ b/tests/DefaultStrategy/Fixture/userland_variadic_function.php.inc @@ -0,0 +1,11 @@ + +----- + diff --git a/tests/DefaultStrategy/Fixture/variadic.php.inc b/tests/DefaultStrategy/Fixture/variadic.php.inc index eaf24e1..ef468d2 100644 --- a/tests/DefaultStrategy/Fixture/variadic.php.inc +++ b/tests/DefaultStrategy/Fixture/variadic.php.inc @@ -6,6 +6,6 @@ sprintf('%s/%s', 'foo', 'bar'); ----- diff --git a/tests/DefaultStrategy/FixtureFunctions.php b/tests/DefaultStrategy/FixtureFunctions.php new file mode 100644 index 0000000..efaccbb --- /dev/null +++ b/tests/DefaultStrategy/FixtureFunctions.php @@ -0,0 +1,5 @@ +withRules(rules: [ AddNamedArgumentsRector::class,