8000 Make failed autowiring error messages more explicit · symfony/symfony@08cd5c7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 08cd5c7

Browse files
committed
Make failed autowiring error messages more explicit
1 parent 39ddd23 commit 08cd5c7

File tree

2 files changed

+45
-15
lines changed

2 files changed

+45
-15
lines changed

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

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ private function completeDefinition($id, Definition $definition)
105105
$this->populateAvailableTypes();
106106
}
107107

108-
if (isset($this->types[$typeHint->name])) {
108+
if (isset($this->types[$typeHint->name]) && !isset($this->notGuessableTypes[$typeHint->name])) {
109109
$value = new Reference($this->types[$typeHint->name]);
110110
} else {
111111
try {
@@ -190,22 +190,26 @@ private function populateAvailableType($id, Definition $definition)
190190
*/
191191
private function set($type, $id)
192192
{
193-
if (isset($this->definedTypes[$type]) || isset($this->notGuessableTypes[$type])) {
193+
if (isset($this->definedTypes[$type])) {
194194
return;
195195
}
196196

197-
if (isset($this->types[$type])) {
198-
if ($this->types[$type] === $id) {
199-
return;
200-
}
197+
if (!isset($this->types[$type])) {
198+
$this->types[$type] = $id;
201199

202-
unset($this->types[$type]);
203-
$this->notGuessableTypes[$type] = true;
200+
return;
201+
}
204202

203+
if ($this->types[$type] === $id) {
205204
return;
206205
}
207206

208-
$this->types[$type] = $id;
207+
if (!isset($this->notGuessableTypes[$type])) {
208+
$this->notGuessableTypes[$type] = true;
209+
$this->types[$type] = (array) $this->types[$type];
210+
}
211+
212+
$this->types[$type][] = $id;
209213
}
210214

211215
/**
@@ -220,8 +224,14 @@ private function set($type, $id)
220224
*/
221225
private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
222226
{
223-
if (isset($this->notGuessableTypes[$typeHint->name]) || !$typeHint->isInstantiable()) {
224-
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s".', $typeHint->name, $id));
227+
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+
}
230+
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);
232+
233+
if (!$typeHint->isInstantiable()) {
234+
throw new RuntimeException($NoAvailableDefinitionMessage);
225235
}
226236

227237
$argumentId = sprintf('autowired.%s', $typeHint->name);
@@ -230,7 +240,12 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
230240
$argumentDefinition->setPublic(false);
231241

232242
$this->populateAvailableType($argumentId, $argumentDefinition);
233-
$this->completeDefinition($argumentId, $argumentDefinition);
243+
244+
try {
245+
$this->completeDefinition($argumentId, $argumentDefinition);
246+
} catch (RuntimeException $e) {
247+
throw new RuntimeException($NoAvailableDefinitionMessage, 0, $e);
248+
}
234249

235250
return new Reference($argumentId);
236251
}

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

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ 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".
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".
107107
*/
108108
public function testTypeCollision()
109109
{
@@ -120,7 +120,7 @@ public function testTypeCollision()
120120

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

138138
/**
139139
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
140-
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\A" for the service "a".
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".
141141
*/
142142
public function testTypeNotGuessableWithSubclass()
143143
{
@@ -207,6 +207,21 @@ public function testCreateDefinition()
207207
$this->assertEquals(__NAMESPACE__.'\Lille', $lilleDefinition->getClass());
208208
}
209209

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+
210225
public function testResolveParameter()
211226
{
212227
$container = new ContainerBuilder();

0 commit comments

Comments
 (0)
0