Skip to content

Commit

Permalink
Resolver::autowireArguments() fixed support for variadics
Browse files Browse the repository at this point in the history
The variadics argument cannot be used if a previous argument has been omitted.
  • Loading branch information
dg committed Feb 27, 2023
1 parent dad71aa commit 8e6357f
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 55 deletions.
32 changes: 10 additions & 22 deletions src/DI/Resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Nette\DI\Definitions\Reference;
use Nette\DI\Definitions\Statement;
use Nette\PhpGenerator\Helpers as PhpHelpers;
use Nette\Utils\Arrays;
use Nette\Utils\Callback;
use Nette\Utils\Reflection;
use Nette\Utils\Strings;
Expand Down Expand Up @@ -254,7 +255,7 @@ public function completeStatement(Statement $statement, bool $currentServiceAllo

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

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

if ($param->isVariadic()) {
if (array_key_exists($paramName, $arguments)) {
if (!is_array($arguments[$paramName])) {
throw new ServiceCreationException(sprintf(
'Parameter %s must be array, %s given.',
Reflection::toString($param),
gettype($arguments[$paramName])
));
}

$variadics = $arguments[$paramName];
unset($arguments[$paramName]);
} else {
$variadics = array_merge($arguments);
$arguments = [];
}

if ($useName) {
$res[$paramName] = $variadics;
} else {
$res = array_merge($res, $variadics);
if ($useName && Arrays::some($arguments, function ($val, $key) { return is_int($key); })) {
throw new ServiceCreationException(sprintf(
'Cannot use positional argument after named or omitted argument in %s.',
Reflection::toString($param)
));
}

$res = array_merge($res, $arguments);
$arguments = [];
$optCount = 0;
break;

Expand Down
26 changes: 9 additions & 17 deletions tests/DI/Resolver.autowireArguments.errors.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,13 @@ Assert::exception(function () {
}, Nette\DI\ServiceCreationException::class, 'Parameter $x in {closure}%a?% has no class type or default value, so its value must be specified.');


// bad variadics (this is actually what PHP allows)
Assert::exception(function () {
Resolver::autowireArguments(
new ReflectionFunction(function (...$args) {}),
[1, 'args' => []],
function () {}
);
}, Nette\DI\ServiceCreationException::class, 'Unable to pass specified arguments to {closure}%a?%.');


// bad variadics
Assert::exception(function () {
Resolver::autowireArguments(
new ReflectionFunction(function (...$args) {}),
['args' => [], 1],
function () {}
);
}, Nette\DI\ServiceCreationException::class, 'Unable to pass specified arguments to {closure}%a?%.');
if (PHP_VERSION_ID >= 80000) {
Assert::exception(function () {
Resolver::autowireArguments(
new ReflectionFunction(function ($a = 1, ...$args) {}),
[1 => 'new1', 2 => 'new2'],
function () {}
);
}, Nette\DI\ServiceCreationException::class, 'Cannot use positional argument after named or omitted argument in $args in {closure}%a?%.');
}
22 changes: 6 additions & 16 deletions tests/DI/Resolver.autowireArguments.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -98,27 +98,17 @@ Assert::equal(
)
);

// optional arguments + variadics
// optional arguments + named variadics
Assert::equal(
PHP_VERSION_ID < 80000 ? [1, 'new1', 'new2'] : ['args' => ['new1', 'new2']],
PHP_VERSION_ID < 80000 ? [1, 'k1' => 'new1', 'k2' => 'new2'] : ['k1' => 'new1', 'k2' => 'new2'],
Resolver::autowireArguments(
new ReflectionFunction(function ($a = 1, ...$args) {}),
[1 => 'new1', 2 => 'new2'],
['k1' => 'new1', 'k2' => 'new2'],
function () {}
)
);

// optional arguments + variadics
Assert::equal(
['new', 'new1', 'new2'],
Resolver::autowireArguments(
new ReflectionFunction(function ($a = 1, ...$args) {}),
['a' => 'new', 1 => 'new1', 2 => 'new2'],
function () {}
)
);

// variadics as items
// variadics
Assert::equal(
[1, 2, 3],
Resolver::autowireArguments(
Expand All @@ -128,9 +118,9 @@ Assert::equal(
)
);

// variadics as array
// name of variadics is ignored
Assert::equal(
[1, 2, 3],
['args' => [1, 2, 3]],
Resolver::autowireArguments(
new ReflectionFunction(function (...$args) {}),
['args' => [1, 2, 3]],
Expand Down

0 comments on commit 8e6357f

Please sign in to comment.