From 60437984ebd34df70eb9e54b703d288fdc131f9d Mon Sep 17 00:00:00 2001 From: David Grudl Date: Wed, 29 Sep 2021 15:40:02 +0200 Subject: [PATCH] Resolver::autowireArguments() throws an exception when combining a named and positional parameter --- src/DI/Resolver.php | 8 +++++++- tests/DI/Compiler.services.factory.phpt | 4 ++-- tests/DI/Resolver.autowireArguments.errors.phpt | 10 ++++++++++ tests/DI/Resolver.autowireArguments.phpt | 12 ++++++++++++ tests/DI/files/compiler.services.factory.neon | 2 +- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/DI/Resolver.php b/src/DI/Resolver.php index 023dea40c..95d55fe51 100644 --- a/src/DI/Resolver.php +++ b/src/DI/Resolver.php @@ -520,7 +520,13 @@ public static function autowireArguments( $paramName = $param->name; if (!$param->isVariadic() && array_key_exists($paramName, $arguments)) { $res[$num] = $arguments[$paramName]; - unset($arguments[$paramName], $arguments[$num]); + if (array_key_exists($num, $arguments)) { + throw new ServiceCreationException(sprintf( + 'Named parameter $%s used at the same time as a positional in %s.', + $paramName, + Reflection::toString($method) + )); + } } elseif (array_key_exists($num, $arguments)) { $res[$num] = $arguments[$num]; diff --git a/tests/DI/Compiler.services.factory.phpt b/tests/DI/Compiler.services.factory.phpt index 2ee628df9..315081d4b 100644 --- a/tests/DI/Compiler.services.factory.phpt +++ b/tests/DI/Compiler.services.factory.phpt @@ -58,7 +58,7 @@ Assert::type(Ipsum::class, $container->getService('two')); Assert::same(1, $container->getService('two')->arg); Assert::type(Lorem::class, $container->getService('three')); -Assert::same('Factory::createLorem 5 2', $container->getService('three')->arg); +Assert::same('Factory::createLorem 1 2', $container->getService('three')->arg); Assert::type(Lorem::class, $container->getService('four')); Assert::same('Factory::createLorem 1', $container->getService('four')->arg); @@ -74,7 +74,7 @@ Assert::type(Lorem::class, $container->getService('seven')); Assert::type(Lorem::class, $container->getService('eight')); Assert::type(Lorem::class, $container->getService('nine')); -Assert::same('Factory::createLorem 5 2', $container->getService('nine')->arg); +Assert::same('Factory::createLorem 1 2', $container->getService('nine')->arg); Assert::same([], $container->getService('nine')->foo); Assert::type(Ipsum::class, $container->getService('referencedService')); diff --git a/tests/DI/Resolver.autowireArguments.errors.phpt b/tests/DI/Resolver.autowireArguments.errors.phpt index 6f36aa8d6..9ff3aea79 100644 --- a/tests/DI/Resolver.autowireArguments.errors.phpt +++ b/tests/DI/Resolver.autowireArguments.errors.phpt @@ -31,3 +31,13 @@ Assert::exception(function () { Assert::exception(function () { Resolver::autowireArguments(new ReflectionFunction(function (int $x) {}), [], function () {}); }, Nette\DI\ServiceCreationException::class, 'Parameter $x in {closure}() has no class type or default value, so its value must be specified.'); + + +Assert::exception(function () { + Resolver::autowireArguments(new ReflectionFunction(function (int $x) {}), [10, 'x' => 10], function () {}); +}, Nette\DI\ServiceCreationException::class, 'Named parameter $x used at the same time as a positional in {closure}%a?%.'); + + +Assert::exception(function () { + Resolver::autowireArguments(new ReflectionFunction(function (...$args) {}), ['args' => []], function () {}); +}, Nette\DI\ServiceCreationException::class, 'Unable to pass specified arguments to {closure}%a?%.'); diff --git a/tests/DI/Resolver.autowireArguments.phpt b/tests/DI/Resolver.autowireArguments.phpt index aa548e81b..4caf96bf5 100644 --- a/tests/DI/Resolver.autowireArguments.phpt +++ b/tests/DI/Resolver.autowireArguments.phpt @@ -38,3 +38,15 @@ Assert::equal( return $type === Test::class ? new Test : null; }) ); + + +// variadics +Assert::equal( + [], + Resolver::autowireArguments(new ReflectionFunction(function (...$args) {}), [], function () {}) +); + +Assert::equal( + [1, 2, 3], + Resolver::autowireArguments(new ReflectionFunction(function (...$args) {}), [1, 2, 3], function () {}) +); diff --git a/tests/DI/files/compiler.services.factory.neon b/tests/DI/files/compiler.services.factory.neon index 4df98cdfa..dc393fdfb 100644 --- a/tests/DI/files/compiler.services.factory.neon +++ b/tests/DI/files/compiler.services.factory.neon @@ -25,7 +25,7 @@ services: three: type: Lorem factory: Factory::createLorem - arguments: [arg: 5, 1, 2] + arguments: [1, 2] four: factory: Factory::createLorem(1)