8000 [DependencyInjection] Improving autowiring error messages to say *why… · symfony/symfony@6fe97f9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6fe97f9

Browse files
committed
[DependencyInjection] Improving autowiring error messages to say *why* something cannot be autowired
1 parent 0813705 commit 6fe97f9

File tree

2 files changed

+40
-9
lines changed

2 files changed

+40
-9
lines changed

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

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class AutowirePass implements CompilerPassInterface
2727
private $reflectionClasses = array();
2828
private $definedTypes = array();
2929
private $types;
30-
private $notGuessableTypes = array();
30+
private $ambiguousServiceTypes = array();
3131

3232
/**
3333
* {@inheritdoc}
@@ -46,7 +46,7 @@ public function process(ContainerBuilder $container)
4646
$this->reflectionClasses = array();
4747
$this->definedTypes = array();
4848
$this->types = null;
49-
$this->notGuessableTypes = array();
49+
$this->ambiguousServiceTypes = array();
5050
}
5151

5252
/**
@@ -197,17 +197,25 @@ private function extractAncestors($id, \ReflectionClass $reflectionClass)
197197
*/
198198
private function set($type, $id)
199199
{
200-
if (isset($this->definedTypes[$type]) || isset($this->notGuessableTypes[$type])) {
200+
if (isset($this->definedTypes[$type])) {
201201
return;
202202
}
203203

204+
// check to make sure the type doesn't match multiple services
204205
if (isset($this->types[$type])) {
205206
if ($this->types[$type] === $id) {
206207
return;
207208
}
208209

210+
// keep an array of all services matching this type
211+
if (!isset($this->ambiguousServiceTypes[$type])) {
212+
$this->ambiguousServiceTypes[$type] = array(
213+
$this->types[$type],
214+
);
215+
}
216+
$this->ambiguousServiceTypes[$type][] = $id;
217+
209218
unset($this->types[$type]);
210-
$this->notGuessableTypes[$type] = true;
211219

212220
return;
213221
}
@@ -227,8 +235,16 @@ private function set($type, $id)
227235
*/
228236
private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
229237
{
230-
if (isset($this->notGuessableTypes[$typeHint->name]) || !$typeHint->isInstantiable()) {
231-
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s".', $typeHint->name, $id));
238+
if (isset($this->ambiguousServiceTypes[$typeHint->name])) {
239+
$classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
240+
$matchingServices = implode(', ', $this->ambiguousServiceTypes[$typeHint->name]);
241+
242+
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));
243+
}
244+
245+
if (!$typeHint->isInstantiable()) {
246+
$classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
247+
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s.', $typeHint->name, $id, $classOrInterface));
232248
}
233249

234250
$argumentId = sprintf('autowired.%s', $typeHint->name);

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public function testCompleteExistingDefinitionWithNotDefinedArguments()
102102

103103
/**
104104
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
105-
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a".
105+
* @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).
106106
*/
107107
public function testTypeCollision()
108108
{
@@ -119,7 +119,7 @@ public function testTypeCollision()
119119

120120
/**
121121
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
122-
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" for the service "a".
122+
* @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).
123123
*/
124124
public function testTypeNotGuessable()
125125
{
@@ -136,7 +136,7 @@ public function testTypeNotGuessable()
136136

137137
/**
138138
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
139-
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\A" for the service "a".
139+
* @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).
140140
*/
141141
public function testTypeNotGuessableWithSubclass()
142142
{
@@ -151,6 +151,21 @@ public function testTypeNotGuessableWithSubclass()
151151
$pass->process($container);
152152
}
153153

154+
/**
155+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
156+
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". No services were found matching this interface.
157+
*/
158+
public function testTypeNotGuessableNoServicesFound()
159+
{
160+
$container = new ContainerBuilder();
161+
162+
$aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired');
163+
$aDefinition->setAutowired(true);
164+
165+
$pass = new AutowirePass();
166+
$pass->process($container);
167+
}
168+
154169
public function testTypeNotGuessableWithTypeSet()
155170
{
156171
$container = new ContainerBuilder();

0 commit comments

Comments
 (0)
0