Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 83ff14c

Browse files
committed
Fixing a bug where an autowiring exception was thrown even when that service was removed
The specific report was for a service with a private constructor. This also clarifies that the AutowirePass throws AutowiringFailedException for all situations. And a bug was fixed in the constructor of AutowiringFailedException
1 parent 5473373 commit 83ff14c

File tree

3 files changed

+42
-17
lines changed

3 files changed

+42
-17
lines changed

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,13 @@ private function doProcessValue($value, $isRoot = false)
133133
$autowiredMethods = $this->getMethodsToAutowire($reflectionClass);
134134
$methodCalls = $value->getMethodCalls();
135135

136-
if ($constructor = $this->getConstructor($value, false)) {
136+
try {
137+
$constructor = $this->getConstructor($value, false);
138+
} catch (RuntimeException $e) {
139+
throw new AutowiringFailedException($this->currentId, $e->getMessage(), 0, $e);
140+
}
141+
142+
if ($constructor) {
137143
array_unshift($methodCalls, array($constructor, $value->getArguments()));
138144
}
139145

@@ -242,7 +248,7 @@ private function autowireCalls(\ReflectionClass $reflectionClass, array $methodC
242248
*
243249
* @return array The autowired arguments
244250
*
245-
* @throws RuntimeException
251+
* @throws AutowiringFailedException
246252
*/
247253
private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments)
248254
{

src/Symfony/Component/DependencyInjection/Exception/AutowiringFailedException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class AutowiringFailedException extends RuntimeException
1818
{
1919
private $serviceId;
2020

21-
public function __construct($serviceId, $message = '', $code = 0, Exception $previous = null)
21+
public function __construct($serviceId, $message = '', $code = 0, \Exception $previous = null)
2222
{
2323
$this->serviceId = $serviceId;
2424

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

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,21 @@ public function testExceptionsAreStored()
151151
}
152152

153153
/**
154-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
154+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
155+
* @expectedExceptionMessage Unable to resolve service "private_service": constructor of class "Symfony\Component\DependencyInjection\Tests\Compiler\PrivateConstructor" must be public.
156+
*/
157+
public function testPrivateConstructorThrowsAutowireException()
158+
{
159+
$container = new ContainerBuilder();
160+
161+
$container->autowire('private_service', __NAMESPACE__.'\PrivateConstructor');
162+
163+
$pass = new AutowirePass(true);
164+
$pass->process($container);
165+
}
166+
167+
/**
168+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
155169
* @expectedExceptionMessage Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\CannotBeAutowired::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "c1", "c2", "c3".
156170
*/
157171
public function testTypeCollision()
@@ -169,7 +183,7 @@ public function testTypeCollision()
169183
}
170184

171185
/**
172-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
186+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
173187
* @expectedExceptionMessage Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgument::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to one of these existing services: "a1", "a2".
174188
*/
175189
public function testTypeNotGuessable()
@@ -186,7 +200,7 @@ public function testTypeNotGuessable()
186200
}
187201

188202
/**
189-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
203+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
190204
* @expectedExceptionMessage Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgumentForSubclass::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to one of these existing services: "a1", "a2".
191205
*/
192206
public function testTypeNotGuessableWithSubclass()
@@ -203,7 +217,7 @@ public function testTypeNotGuessableWithSubclass()
203217
}
204218

205219
/**
206-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
220+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
207221
* @expectedExceptionMessage Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\CannotBeAutowired::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists.
208222
*/
209223
public function testTypeNotGuessableNoServicesFound()
@@ -322,7 +336,7 @@ public function testDontTriggerAutowiring()
322336
}
323337

324338
/**
325-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
339+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
326340
* @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class does not exist.
327341
*/
328342
public function testClassNotFoundThrowsException()
@@ -337,7 +351,7 @@ public function testClassNotFoundThrowsException()
337351
}
338352

339353
/**
340-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
354+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
341355
* @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadParentTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\OptionalServiceClass" but this class does not exist.
342356
*/
343357
public function testParentClassNotFoundThrowsException()
@@ -354,7 +368,7 @@ public function testParentClassNotFoundThrowsException()
354368
/**
355369
* @group legacy
356370
* @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.
357-
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException
371+
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
358372
* @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.
359373
*/
360374
public function testDontUseAbstractServices()
@@ -399,7 +413,7 @@ public function testSomeSpecificArgumentsAreSet()
399413
}
400414

401415
/**
402-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
416+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
403417
* @expectedExceptionMessage Cannot autowire service "arg_no_type_hint": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\MultipleArguments::__construct()" must have a type-hint or be given a value explicitly.
404418
*/
405419
public function testScalarArgsCannotBeAutowired()
@@ -607,7 +621,7 @@ public function testIgnoreServiceWithClassNotExisting()
607621
}
608622

609623
/**
610-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
624+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
611625
* @expectedExceptionMessage Cannot autowire service "setter_injection_collision": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\SetterInjectionCollision::setMultipleInstancesForOneArg()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "c1", "c2".
612626
*/
613627
public function testSetterInjectionCollisionThrowsException()
@@ -626,7 +640,7 @@ public function testSetterInjectionCollisionThrowsException()
626640
/**
627641
* @group legacy
628642
* @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.
629-
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException
643+
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
630644
* @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.
631645
*/
632646
public function testProcessDoesNotTriggerDeprecations()
@@ -677,7 +691,7 @@ public function testWithFactory()
677691

678692
/**
679693
* @dataProvider provideNotWireableCalls
680-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
694+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
681695
*/
682696
public function testNotWireableCalls($method, $expectedMsg)
683697
{
@@ -717,7 +731,7 @@ public function provideNotWireableCalls()
717731
/**
718732
* @group legacy
719733
* @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.
720-
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException
734+
* @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
721735
* @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. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead.
722736
*/
723737
public function testByIdAlternative()
@@ -734,7 +748,7 @@ public function testByIdAlternative()
734748
}
735749

736750
/**
737-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
751+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
738752
* @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. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead.
739753
*/
740754
public function testExceptionWhenAliasExists()
@@ -754,7 +768,7 @@ public function testExceptionWhenAliasExists()
754768
}
755769

756770
/**
757-
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
771+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
758772
* @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 one of these existing services: "i", "i2".
759773
*/
760774
public function testExceptionWhenAliasDoesNotExist()
@@ -1091,3 +1105,8 @@ protected function setProtectedMethod(A $a)
10911105
{
10921106
}
10931107
}
1108+
1109+
class PrivateConstructor
1110+
{
1111+
private function __construct(){}
1112+
}

0 commit comments

Comments
 (0)