Make failed autowiring error messages more explicit
This commit is contained in:
parent
39ddd2383f
commit
2ac81f954b
@ -105,7 +105,7 @@ class AutowirePass implements CompilerPassInterface
|
|||||||
$this->populateAvailableTypes();
|
$this->populateAvailableTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->types[$typeHint->name])) {
|
if (isset($this->types[$typeHint->name]) && !isset($this->notGuessableTypes[$typeHint->name])) {
|
||||||
$value = new Reference($this->types[$typeHint->name]);
|
$value = new Reference($this->types[$typeHint->name]);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@ -190,22 +190,26 @@ class AutowirePass implements CompilerPassInterface
|
|||||||
*/
|
*/
|
||||||
private function set($type, $id)
|
private function set($type, $id)
|
||||||
{
|
{
|
||||||
if (isset($this->definedTypes[$type]) || isset($this->notGuessableTypes[$type])) {
|
if (isset($this->definedTypes[$type])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->types[$type])) {
|
||||||
|
$this->types[$type] = $id;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($this->types[$type])) {
|
|
||||||
if ($this->types[$type] === $id) {
|
if ($this->types[$type] === $id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($this->types[$type]);
|
if (!isset($this->notGuessableTypes[$type])) {
|
||||||
$this->notGuessableTypes[$type] = true;
|
$this->notGuessableTypes[$type] = true;
|
||||||
|
$this->types[$type] = (array) $this->types[$type];
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->types[$type] = $id;
|
$this->types[$type][] = $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -220,8 +224,14 @@ class AutowirePass implements CompilerPassInterface
|
|||||||
*/
|
*/
|
||||||
private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
|
private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
|
||||||
{
|
{
|
||||||
if (isset($this->notGuessableTypes[$typeHint->name]) || !$typeHint->isInstantiable()) {
|
if (isset($this->notGuessableTypes[$typeHint->name])) {
|
||||||
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s".', $typeHint->name, $id));
|
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])));
|
||||||
|
}
|
||||||
|
|
||||||
|
$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);
|
||||||
|
|
||||||
|
if (!$typeHint->isInstantiable()) {
|
||||||
|
throw new RuntimeException($noAvailableDefinitionMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
$argumentId = sprintf('autowired.%s', $typeHint->name);
|
$argumentId = sprintf('autowired.%s', $typeHint->name);
|
||||||
@ -230,7 +240,12 @@ class AutowirePass implements CompilerPassInterface
|
|||||||
$argumentDefinition->setPublic(false);
|
$argumentDefinition->setPublic(false);
|
||||||
|
|
||||||
$this->populateAvailableType($argumentId, $argumentDefinition);
|
$this->populateAvailableType($argumentId, $argumentDefinition);
|
||||||
|
|
||||||
|
try {
|
||||||
$this->completeDefinition($argumentId, $argumentDefinition);
|
$this->completeDefinition($argumentId, $argumentDefinition);
|
||||||
|
} catch (RuntimeException $e) {
|
||||||
|
throw new RuntimeException($noAvailableDefinitionMessage, 0, $e);
|
||||||
|
}
|
||||||
|
|
||||||
return new Reference($argumentId);
|
return new Reference($argumentId);
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||||
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a".
|
* @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".
|
||||||
*/
|
*/
|
||||||
public function testTypeCollision()
|
public function testTypeCollision()
|
||||||
{
|
{
|
||||||
@ -120,7 +120,7 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||||
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" for the service "a".
|
* @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".
|
||||||
*/
|
*/
|
||||||
public function testTypeNotGuessable()
|
public function testTypeNotGuessable()
|
||||||
{
|
{
|
||||||
@ -137,7 +137,7 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||||
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\A" for the service "a".
|
* @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".
|
||||||
*/
|
*/
|
||||||
public function testTypeNotGuessableWithSubclass()
|
public function testTypeNotGuessableWithSubclass()
|
||||||
{
|
{
|
||||||
@ -207,6 +207,21 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(__NAMESPACE__.'\Lille', $lilleDefinition->getClass());
|
$this->assertEquals(__NAMESPACE__.'\Lille', $lilleDefinition->getClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
public function testCreateNonInstanciable()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
|
$aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired');
|
||||||
|
$aDefinition->setAutowired(true);
|
||||||
|
|
||||||
|
$pass = new AutowirePass();
|
||||||
|
$pass->process($container);
|
||||||
|
}
|
||||||
|
|
||||||
public function testResolveParameter()
|
public function testResolveParameter()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
Reference in New Issue
Block a user