diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php index 161cd5960ca91..d4f8e69fe5d8c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php @@ -17,9 +17,11 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\InvalidParameterTypeException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\ExpressionLanguage; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\ExpressionLanguage\Expression; /** * Checks whether injected parameters are compatible with type declarations. @@ -39,6 +41,8 @@ final class CheckTypeDeclarationsPass extends AbstractRecursivePass private $autoload; + private $expressionLanguage; + /** * @param bool $autoload Whether services who's class in not loaded should be checked or not. * Defaults to false to save loading code during compilation. @@ -172,6 +176,8 @@ private function checkType(Definition $checkedDefinition, $value, \ReflectionPar if ($value instanceof Parameter) { $value = $this->container->getParameter($value); + } elseif ($value instanceof Expression) { + $value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this->container]); } elseif (\is_string($value) && '%' === ($value[0] ?? '') && preg_match('/^%([^%]+)%$/', $value, $match)) { $value = $this->container->getParameter($match[1]); } @@ -202,4 +208,13 @@ private function checkType(Definition $checkedDefinition, $value, \ReflectionPar throw new InvalidParameterTypeException($this->currentId, \is_object($value) ? \get_class($value) : \gettype($value), $parameter); } } + + private function getExpressionLanguage(): ExpressionLanguage + { + if (null === $this->expressionLanguage) { + $this->expressionLanguage = new ExpressionLanguage(null, $this->container->getExpressionLanguageProviders()); + } + + return $this->expressionLanguage; + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php index b012a65625610..a2f66bf71c64d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php @@ -23,6 +23,7 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\BarOptionalArgumentNotNull; use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\Foo; use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\FooObject; +use Symfony\Component\ExpressionLanguage\Expression; /** * @author Nicolas Grekas @@ -569,4 +570,18 @@ public function testProcessThrowsOnIterableTypeWhenScalarPassed() $this->assertInstanceOf(\stdClass::class, $container->get('bar')->foo); } + + public function testProcessResolveExpressions() + { + $container = new ContainerBuilder(); + $container->setParameter('ccc', ['array']); + + $container + ->register('foobar', BarMethodCall::class) + ->addMethodCall('setArray', [new Expression("parameter('ccc')")]); + + (new CheckTypeDeclarationsPass(true))->process($container); + + $this->addToAssertionCount(1); + } }