bug #18039 Fixing autowiring collision failure (weaverryan)

This PR was merged into the 3.1-dev branch.

Discussion
----------

Fixing autowiring collision failure

| Q             | A
| ------------- | ---
| Branch        | master
| Bug fix?      | yes (bug introduced in master)
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | none
| License       | MIT
| Doc PR        | n/a

In #17877, I introduced a bug: https://github.com/symfony/symfony/pull/17877/files#diff-62df969ae028c559d33ffd256de1ac49L200.

Namely, if some class cannot be autowired because there is an *odd* number of matching services, then it *would* autowire the last service found, instead of throwing an exception. The tests only tested even numbers, which is how it was missed. This fixes that.

Thanks!

Commits
-------

2aea337 Fixing a bug where an odd number of type collisions would incorrectly autowire (instead of an error)
This commit is contained in:
Fabien Potencier 2016-03-10 16:36:01 +01:00
commit 681a3494d5
2 changed files with 21 additions and 7 deletions

View File

@ -181,6 +181,13 @@ class AutowirePass implements CompilerPassInterface
return;
}
// is this already a type/class that is known to match multiple services?
if (isset($this->ambiguousServiceTypes[$type])) {
$this->addServiceToAmbiguousType($id, $type);
return;
}
// check to make sure the type doesn't match multiple services
if (isset($this->types[$type])) {
if ($this->types[$type] === $id) {
@ -188,12 +195,7 @@ class AutowirePass implements CompilerPassInterface
}
// keep an array of all services matching this type
if (!isset($this->ambiguousServiceTypes[$type])) {
$this->ambiguousServiceTypes[$type] = array(
$this->types[$type],
);
}
$this->ambiguousServiceTypes[$type][] = $id;
$this->addServiceToAmbiguousType($id, $type);
unset($this->types[$type]);
@ -265,4 +267,15 @@ class AutowirePass implements CompilerPassInterface
// return null
}
}
private function addServiceToAmbiguousType($id, $type)
{
// keep an array of all services matching this type
if (!isset($this->ambiguousServiceTypes[$type])) {
$this->ambiguousServiceTypes[$type] = array(
$this->types[$type],
);
}
$this->ambiguousServiceTypes[$type][] = $id;
}
}

View File

@ -103,7 +103,7 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @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).
* @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).
*/
public function testTypeCollision()
{
@ -111,6 +111,7 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
$container->register('c1', __NAMESPACE__.'\CollisionA');
$container->register('c2', __NAMESPACE__.'\CollisionB');
$container->register('c3', __NAMESPACE__.'\CollisionB');
$aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired');
$aDefinition->setAutowired(true);