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 6c80873c27..792fe3fc20 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 9fb064b08f..1375d6ffab 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 a9a382c906..aaec5b90ba 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 acbc3a4ccf..39d0cdac07 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -291,6 +291,12 @@ class AutowirePass extends AbstractRecursivePass 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 b006504444..9ed9698e40 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -58,8 +58,10 @@ class AutowirePassTest extends TestCase } /** - * @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 @@ class AutowirePassTest extends TestCase } /** - * @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 @@ class AutowirePassTest extends TestCase } /** - * @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 @@ class AutowirePassTest extends TestCase } /** - * @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 @@ class AutowirePassTest extends TestCase } /** - * @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() {