8000 [DX][DI] Make Autowiring exceptions more future friendly · symfony/symfony@834f550 · GitHub
[go: up one dir, main page]

Skip to content

Commit 834f550

Browse files
committed
[DX][DI] Make Autowiring exceptions more future friendly
1 parent bcdf568 commit 834f550

File tree

2 files changed

+29
-23
lines changed

2 files changed

+29
-23
lines changed

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,13 +225,16 @@ private function set($type, $id)
225225
private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
226226
{
227227
if (isset($this->notGuessableTypes[$typeHint->name])) {
228-
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Several services implementing this type have been declared: "%s".', $typeHint->name, $id, implode('", "', $this->types[$typeHint->name])));
229-
}
228+
$classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
229+
$matchingServices = implode(', ', $this->types[$typeHint->name]);
230+
231+
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $typeHint->name, $id, $classOrInterface, $matchingServices));
230232

231-
$noAvailableDefinitionMessage = sprintf('Unable to autowire argument of type "%s" for the service "%s". This type cannot be instantiated automatically and no service implementing this type is declared.', $typeHint->name, $id);
233+
}
232234

233235
if (!$typeHint->isInstantiable()) {
234-
throw new RuntimeException($noAvailableDefinitionMessage);
236+
$classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
237+
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s and it cannot be auto-registered.', $typeHint->name, $id, $classOrInterface));
235238
}
236239

237240
$argumentId = sprintf('autowired.%s', $typeHint->name);
@@ -244,7 +247,9 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
244247
try {
245248
$this->completeDefinition($argumentId, $argumentDefinition);
246249
} catch (RuntimeException $e) {
247-
throw new RuntimeException($noAvailableDefinitionMessage, 0, $e);
250+
$classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
251+
$message = sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s and it cannot be auto-registered.', $typeHint->name, $id, $classOrInterface);
252+
throw new RuntimeException($message, 0, $e);
248253
}
249254

250255
return new Reference($argumentId);

src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,15 @@ public function testCompleteExistingDefinitionWithNotDefinedArguments()
103103

104104
/**
105105
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
106-
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". Several services implementing this type have been declared: "c1", "c2".
106+
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". Multiple services exist for this interface (c1, c2, c3).
107107
*/
108108
public function testTypeCollision()
109109
{
110110
$container = new ContainerBuilder();
111111

112112
$container->register('c1', __NAMESPACE__.'\CollisionA');
113113
$container->register('c2', __NAMESPACE__.'\CollisionB');
114+
$container->register('c3', __NAMESPACE__.'\CollisionB');
114115
$aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired');
115116
$aDefinition->setAutowired(true);
116117

@@ -120,7 +121,7 @@ public function testTypeCollision()
120121

121122
/**
122123
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
123-
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" for the service "a". Several services implementing this type have been declared: "a1", "a2".
124+
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" for the service "a". Multiple services exist for this class (a1, a2).
124125
*/
125126
public function testTypeNotGuessable()
126127
{
@@ -137,7 +138,7 @@ public function testTypeNotGuessable()
137138

138139
/**
139140
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
140-
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\A" for the service "a". Several services implementing this type have been declared: "a1", "a2".
141+
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\A" for the service "a". Multiple services exist for this class (a1, a2).
141142
*/
142143
public function testTypeNotGuessableWithSubclass()
143144
{
@@ -152,6 +153,21 @@ public function testTypeNotGuessableWithSubclass()
152153
$pass->process($container);
153154
}
154155

156+
/**
157+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
158+
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". No services were found matching this interface and it cannot be auto-registered.
159+
*/
160+
public function testTypeNotGuessableNoServicesFound()
161+
{
162+
$container = new ContainerBuilder();
163+
164+
$aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired');
165+
$aDefinition->setAutowired(true);
166+
167+
$pass = new AutowirePass();
168+
$pass->process($container);
169+
}
170+
155171
public function testTypeNotGuessableWithTypeSet()
156172
{
157173
$container = new ContainerBuilder();
@@ -207,21 +223,6 @@ public function testCreateDefinition()
207223
$this->assertEquals(__NAMESPACE__.'\Lille', $lilleDefinition->getClass());
208224
}
209225

210-
/**
211-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
212-
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". This type cannot be instantiated automatically and no service implementing this type is declared.
213-
*/
214-
public function testCreateNonInstanciable()
215-
{
216-
$container = new ContainerBuilder();
217-
218-
$aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired');
219-
$aDefinition->setAutowired(true);
220-
221-
$pass = new AutowirePass();
222-
$pass->process($container);
223-
}
224-
225226
public function testResolveParameter()
226227
{
227228
$container = new ContainerBuilder();

0 commit comments

Comments
 (0)
0