bug #35225 [DependencyInjection] Handle ServiceClosureArgument for callable in container linting (shieldo)

This PR was merged into the 4.4 branch.

Discussion
----------

[DependencyInjection] Handle ServiceClosureArgument for callable in container linting

| Q             | A
| ------------- | ---
| Branch?       | 4.4 (+)
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | (none)
| License       | MIT

Making use of `ServiceClosureArgument` instances in service definitions was not accounted for in container linting when a service type-hints for `callable` in an argument - adding this check ensures that `ServiceClosureArgument` instances are recognised correctly as callables (once they are resolved).

Commits
-------

e48829e9b6 [DependencyInjection] Handle ServiceClosureArgument for callable in container linting
This commit is contained in:
Nicolas Grekas 2020-01-07 11:57:32 +01:00
commit ffd5d12045
3 changed files with 34 additions and 0 deletions

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
@ -219,6 +220,10 @@ final class CheckTypeDeclarationsPass extends AbstractRecursivePass
return;
}
if (\in_array($type, ['callable', 'Closure'], true) && $value instanceof ServiceClosureArgument) {
return;
}
if ('iterable' === $type && (\is_array($value) || $value instanceof \Traversable || $value instanceof IteratorArgument)) {
return;
}

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass;
use Symfony\Component\DependencyInjection\Compiler\ResolveParameterPlaceHoldersPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@ -697,4 +698,28 @@ class CheckTypeDeclarationsPassTest extends TestCase
$this->addToAssertionCount(1);
}
public function testProcessSuccessWhenPassingServiceClosureArgumentToCallable()
{
$container = new ContainerBuilder();
$container->register('bar', BarMethodCall::class)
->addMethodCall('setCallable', [new ServiceClosureArgument(new Reference('foo'))]);
(new CheckTypeDeclarationsPass(true))->process($container);
$this->addToAssertionCount(1);
}
public function testProcessSuccessWhenPassingServiceClosureArgumentToClosure()
{
$container = new ContainerBuilder();
$container->register('bar', BarMethodCall::class)
->addMethodCall('setClosure', [new ServiceClosureArgument(new Reference('foo'))]);
(new CheckTypeDeclarationsPass(true))->process($container);
$this->addToAssertionCount(1);
}
}

View File

@ -40,4 +40,8 @@ class BarMethodCall
public function setCallable(callable $callable): void
{
}
public function setClosure(\Closure $closure): void
{
}
}