From f16230be5dd5b0e452f94295b2960d0f0ea60ee9 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 7 Jan 2021 03:10:33 +0100 Subject: [PATCH] [DependencyInjection] Support PHP 8 builtin types in CheckTypeDeclarationsPass --- .../Compiler/CheckTypeDeclarationsPass.php | 19 +++-- .../CheckTypeDeclarationsPassTest.php | 69 ++++++++++++++++++- .../UnionConstructor.php | 10 +++ 3 files changed, 92 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php index 752633ce17..41c4db8329 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php @@ -280,15 +280,26 @@ final class CheckTypeDeclarationsPass extends AbstractRecursivePass return; } + if ('mixed' === $type) { + return; + } + if (is_a($class, $type, true)) { return; } - $checkFunction = sprintf('is_%s', $type); - - if (!$reflectionType->isBuiltin() || !$checkFunction($value)) { - throw new InvalidParameterTypeException($this->currentId, \is_object($value) ? $class : \gettype($value), $parameter); + if ('false' === $type) { + if (false === $value) { + return; + } + } elseif ($reflectionType->isBuiltin()) { + $checkFunction = sprintf('is_%s', $type); + if ($checkFunction($value)) { + return; + } } + + throw new InvalidParameterTypeException($this->currentId, \is_object($value) ? $class : \gettype($value), $parameter); } private function getExpressionLanguage(): ExpressionLanguage diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php index bd69302d43..e5705dce08 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckTypeDeclarationsPassTest.php @@ -836,6 +836,22 @@ class CheckTypeDeclarationsPassTest extends TestCase $this->addToAssertionCount(1); } + /** + * @requires PHP 8 + */ + public function testUnionTypePassesWithFalse() + { + $container = new ContainerBuilder(); + + $container->register('union', UnionConstructor::class) + ->setFactory([UnionConstructor::class, 'create']) + ->setArguments([false]); + + (new CheckTypeDeclarationsPass(true))->process($container); + + $this->addToAssertionCount(1); + } + /** * @requires PHP 8 */ @@ -851,8 +867,6 @@ class CheckTypeDeclarationsPassTest extends TestCase $this->expectExceptionMessage('Invalid definition for service "union": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\UnionConstructor::__construct()" accepts "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\Foo|int", "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\Waldo" passed.'); (new CheckTypeDeclarationsPass(true))->process($container); - - $this->addToAssertionCount(1); } /** @@ -869,6 +883,57 @@ class CheckTypeDeclarationsPassTest extends TestCase $this->expectExceptionMessage('Invalid definition for service "union": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\UnionConstructor::__construct()" accepts "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\Foo|int", "array" passed.'); (new CheckTypeDeclarationsPass(true))->process($container); + } + + /** + * @requires PHP 8 + */ + public function testUnionTypeWithFalseFailsWithReference() + { + $container = new ContainerBuilder(); + + $container->register('waldo', Waldo::class); + $container->register('union', UnionConstructor::class) + ->setFactory([UnionConstructor::class, 'create']) + ->setArguments([new Reference('waldo')]); + + $this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid definition for service "union": argument 1 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\UnionConstructor::create()" accepts "array|false", "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\Waldo" passed.'); + + (new CheckTypeDeclarationsPass(true))->process($container); + } + + /** + * @requires PHP 8 + */ + public function testUnionTypeWithFalseFailsWithTrue() + { + $container = new ContainerBuilder(); + + $container->register('waldo', Waldo::class); + $container->register('union', UnionConstructor::class) + ->setFactory([UnionConstructor::class, 'create']) + ->setArguments([true]); + + $this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid definition for service "union": argument 1 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\UnionConstructor::create()" accepts "array|false", "boolean" passed.'); + + (new CheckTypeDeclarationsPass(true))->process($container); + } + + /** + * @requires PHP 8 + */ + public function testReferencePassesMixed() + { + $container = new ContainerBuilder(); + + $container->register('waldo', Waldo::class); + $container->register('union', UnionConstructor::class) + ->setFactory([UnionConstructor::class, 'make']) + ->setArguments([new Reference('waldo')]); + + (new CheckTypeDeclarationsPass(true))->process($container); $this->addToAssertionCount(1); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/UnionConstructor.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/UnionConstructor.php index 5ba5972863..144480a978 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/UnionConstructor.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/CheckTypeDeclarationsPass/UnionConstructor.php @@ -7,4 +7,14 @@ class UnionConstructor public function __construct(Foo|int $arg) { } + + public static function create(array|false $arg): static + { + return new static(0); + } + + public static function make(mixed $arg): static + { + return new static(0); + } }