From 0ed087d972beb0c7da7049a28b52867e55e54627 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 11 Apr 2017 23:05:55 +0200 Subject: [PATCH] [DI] Replace autowiring BC break by regular deprecation --- UPGRADE-3.3.md | 2 +- UPGRADE-4.0.md | 2 +- .../DependencyInjection/CHANGELOG.md | 4 +-- .../Compiler/AutowirePass.php | 6 ++++ .../Tests/Compiler/AutowirePassTest.php | 30 ++++++++++++------- 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/UPGRADE-3.3.md b/UPGRADE-3.3.md index 6c80873c27a37..792fe3fc20624 100644 --- a/UPGRADE-3.3.md +++ b/UPGRADE-3.3.md @@ -80,7 +80,7 @@ Debug DependencyInjection ------------------- - * [BC BREAK] autowiring now happens only when a type-hint matches its corresponding FQCN id or alias. Please follow the suggestions provided by the exceptions thrown at compilation to upgrade your service configuration. + * Autowiring services based on the types they implement is deprecated and won't be supported in version 4.0. Rename (or alias) your services to their FQCN id to make them autowirable. * [BC BREAK] `_defaults` and `_instanceof` are now reserved service names in Yaml configurations. Please rename any services with that names. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 9fb064b08f623..1375d6ffab867 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -73,7 +73,7 @@ Debug DependencyInjection ------------------- - * Autowiring now happens only when a type-hint matches its corresponding FQCN id or alias. + * Autowiring services based on the types they implement is not supported anymore. Rename (or alias) your services to their FQCN id to make them autowirable. * `_defaults` and `_instanceof` are now reserved service names in Yaml configurations. Please rename any services with that names. diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index a9a382c9060ba..aaec5b90ba149 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -4,8 +4,8 @@ CHANGELOG 3.3.0 ----- - * [BC BREAK] autowiring now happens only when a type-hint matches its corresponding FQCN id or alias. - Please follow the suggestions provided by the exceptions thrown at compilation to upgrade your service configuration. + * deprecated autowiring services based on the types they implement; + rename (or alias) your services to their FQCN id to make them autowirable * added "ServiceSubscriberInterface" - to allow for per-class explicit service-locator definitions * added "container.service_locator" tag for defining service-locator services * added anonymous services support in YAML configuration files using the `!service` tag. diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index acbc3a4ccf423..39d0cdac07595 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -291,6 +291,12 @@ private function getAutowiredReference(TypedReference $reference) return new TypedReference($this->types[$type], $type); } + if (isset($this->types[$type])) { + @trigger_error(sprintf('Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won\'t be supported in version 4.0. You should %s the "%s" service to "%s" instead.', isset($this->types[$this->types[$type]]) ? 'alias' : 'rename (or alias)', $this->types[$type], $type), E_USER_DEPRECATED); + + return new TypedReference($this->types[$type], $type); + } + if (!$reference->canBeAutoregistered() || isset($this->types[$type]) || isset($this->ambiguousServiceTypes[$type])) { return; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index b006504444293..9ed9698e40f58 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -58,8 +58,10 @@ public function testProcessVariadic() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - * @expectedExceptionMessage Cannot autowire service "c": argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\B" service. + * @group legacy + * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should alias the "Symfony\Component\DependencyInjection\Tests\Compiler\B" service to "Symfony\Component\DependencyInjection\Tests\Compiler\A" instead. + * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessageInSymfony4 Cannot autowire service "c": argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\B" service. */ public function testProcessAutowireParent() { @@ -77,8 +79,10 @@ public function testProcessAutowireParent() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - * @expectedExceptionMessage Cannot autowire service "g": argument "$d" of method "Symfony\Component\DependencyInjection\Tests\Compiler\G::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\DInterface" but no such service exists. You should maybe alias this interface to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\F" service. + * @group legacy + * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should alias the "Symfony\Component\DependencyInjection\Tests\Compiler\F" service to "Symfony\Component\DependencyInjection\Tests\Compiler\DInterface" instead. + * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessageInSymfony4 Cannot autowire service "g": argument "$d" of method "Symfony\Component\DependencyInjection\Tests\Compiler\G::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\DInterface" but no such service exists. You should maybe alias this interface to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\F" service. */ public function testProcessAutowireInterface() { @@ -333,8 +337,10 @@ public function testParentClassNotFoundThrowsException() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - * @expectedExceptionMessage Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but this service is abstract. You should maybe alias this class to the existing "foo" service. + * @group legacy + * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename (or alias) the "foo" service to "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" instead. + * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessageInSymfony4 Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but this service is abstract. You should maybe alias this class to the existing "foo" service. */ public function testDontUseAbstractServices() { @@ -603,8 +609,10 @@ public function testSetterInjectionCollisionThrowsException() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - * @expectedExceptionMessage Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to the existing "foo" service. + * @group legacy + * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename (or alias) the "foo" service to "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" instead. + * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessageInSymfony4 Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to the existing "foo" service. */ public function testProcessDoesNotTriggerDeprecations() { @@ -691,8 +699,10 @@ public function provideNotWireableCalls() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - * @expectedExceptionMessage Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. You should maybe alias this class to the existing "i" service; or type-hint against interface "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead. + * @group legacy + * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename (or alias) the "i" service to "Symfony\Component\DependencyInjection\Tests\Compiler\I" instead. + * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessageInSymfony4 Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. You should maybe alias this class to the existing "i" service; or type-hint against interface "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead. */ public function testByIdAlternative() {