Skip to content

Commit 7eaca75

Browse files
committed
Resolver::autowireArguments() fixed support for variadics
The variadics argument cannot be used if a previous argument has been omitted.
1 parent dad71aa commit 7eaca75

File tree

3 files changed

+25
-55
lines changed

3 files changed

+25
-55
lines changed

src/DI/Resolver.php

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Nette\DI\Definitions\Reference;
1515
use Nette\DI\Definitions\Statement;
1616
use Nette\PhpGenerator\Helpers as PhpHelpers;
17+
use Nette\Utils\Arrays;
1718
use Nette\Utils\Callback;
1819
use Nette\Utils\Reflection;
1920
use Nette\Utils\Strings;
@@ -254,7 +255,7 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo
254255

255256
switch (true) {
256257
case $entity[0] === '': // function call
257-
if (!Nette\Utils\Arrays::isList($arguments)) {
258+
if (!Arrays::isList($arguments)) {
258259
throw new ServiceCreationException(sprintf(
259260
'Unable to pass specified arguments to %s.',
260261
$entity[0]
@@ -294,7 +295,7 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo
294295
$arguments = self::autowireArguments($rm, $arguments, $getter);
295296
$this->addDependency($rm);
296297

297-
} elseif (!Nette\Utils\Arrays::isList($arguments)) {
298+
} elseif (!Arrays::isList($arguments)) {
298299
throw new ServiceCreationException(sprintf('Unable to pass specified arguments to %s::%s().', $type, $entity[1]));
299300
}
300301
}
@@ -542,28 +543,15 @@ public static function autowireArguments(
542543
$paramName = $param->name;
543544

544545
if ($param->isVariadic()) {
545-
if (array_key_exists($paramName, $arguments)) {
546-
if (!is_array($arguments[$paramName])) {
547-
throw new ServiceCreationException(sprintf(
548-
'Parameter %s must be array, %s given.',
549-
Reflection::toString($param),
550-
gettype($arguments[$paramName])
551-
));
552-
}
553-
554-
$variadics = $arguments[$paramName];
555-
unset($arguments[$paramName]);
556-
} else {
557-
$variadics = array_merge($arguments);
558-
$arguments = [];
559-
}
560-
561-
if ($useName) {
562-
$res[$paramName] = $variadics;
563-
} else {
564-
$res = array_merge($res, $variadics);
546+
if ($useName && Arrays::some($arguments, function ($val, $key) { return is_int($key); })) {
547+
throw new ServiceCreationException(sprintf(
548+
'Cannot use positional argument after named or omitted argument in %s.',
549+
Reflection::toString($param),
550+
));
565551
}
566552

553+
$res = array_merge($res, $arguments);
554+
$arguments = [];
567555
$optCount = 0;
568556
break;
569557

tests/DI/Resolver.autowireArguments.errors.phpt

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -53,21 +53,13 @@ Assert::exception(function () {
5353
}, Nette\DI\ServiceCreationException::class, 'Parameter $x in {closure}%a?% has no class type or default value, so its value must be specified.');
5454

5555

56-
// bad variadics (this is actually what PHP allows)
57-
Assert::exception(function () {
58-
Resolver::autowireArguments(
59-
new ReflectionFunction(function (...$args) {}),
60-
[1, 'args' => []],
61-
function () {}
62-
);
63-
}, Nette\DI\ServiceCreationException::class, 'Unable to pass specified arguments to {closure}%a?%.');
64-
65-
6656
// bad variadics
67-
Assert::exception(function () {
68-
Resolver::autowireArguments(
69-
new ReflectionFunction(function (...$args) {}),
70-
['args' => [], 1],
71-
function () {}
72-
);
73-
}, Nette\DI\ServiceCreationException::class, 'Unable to pass specified arguments to {closure}%a?%.');
57+
if (PHP_VERSION_ID >= 80000) {
58+
Assert::exception(function () {
59+
Resolver::autowireArguments(
60+
new ReflectionFunction(function ($a = 1, ...$args) {}),
61+
[1 => 'new1', 2 => 'new2'],
62+
function () {}
63+
);
64+
}, Nette\DI\ServiceCreationException::class, 'Cannot use positional argument after named or omitted argument in $args in {closure}%a?%.');
65+
}

tests/DI/Resolver.autowireArguments.phpt

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -98,27 +98,17 @@ Assert::equal(
9898
)
9999
);
100100

101-
// optional arguments + variadics
101+
// optional arguments + named variadics
102102
Assert::equal(
103-
PHP_VERSION_ID < 80000 ? [1, 'new1', 'new2'] : ['args' => ['new1', 'new2']],
103+
PHP_VERSION_ID < 80000 ? [1, 'k1' => 'new1', 'k2' => 'new2'] : ['k1' => 'new1', 'k2' => 'new2'],
104104
Resolver::autowireArguments(
105105
new ReflectionFunction(function ($a = 1, ...$args) {}),
106-
[1 => 'new1', 2 => 'new2'],
106+
['k1' => 'new1', 'k2' => 'new2'],
107107
function () {}
108108
)
109109
);
110110

111-
// optional arguments + variadics
112-
Assert::equal(
113-
['new', 'new1', 'new2'],
114-
Resolver::autowireArguments(
115-
new ReflectionFunction(function ($a = 1, ...$args) {}),
116-
['a' => 'new', 1 => 'new1', 2 => 'new2'],
117-
function () {}
118-
)
119-
);
120-
121-
// variadics as items
111+
// variadics
122112
Assert::equal(
123113
[1, 2, 3],
124114
Resolver::autowireArguments(
@@ -128,9 +118,9 @@ Assert::equal(
128118
)
129119
);
130120

131-
// variadics as array
121+
// name of variadics is ignored
132122
Assert::equal(
133-
[1, 2, 3],
123+
['args' => [1, 2, 3]],
134124
Resolver::autowireArguments(
135125
new ReflectionFunction(function (...$args) {}),
136126
['args' => [1, 2, 3]],

0 commit comments

Comments
 (0)