bug #27191 [DI] Display previous error messages when throwing unused bindings (nicolas-grekas)

This PR was merged into the 3.4 branch.

Discussion
----------

[DI] Display previous error messages when throwing unused bindings

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | n
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #27146
| License       | MIT
| Doc PR        | -

As reported by @jvasseur, confirmation + review welcome.

Commits
-------

f2231b584e [DI] Display previous error messages when throwing unused bindings
This commit is contained in:
Fabien Potencier 2018-05-12 11:34:41 +02:00
commit 98934e4c77
3 changed files with 33 additions and 3 deletions

View File

@ -118,8 +118,12 @@ abstract class AbstractRecursivePass implements CompilerPassInterface
$class = $definition->getClass();
if (!$r = $this->container->getReflectionClass($class)) {
throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
try {
if (!$r = $this->container->getReflectionClass($class)) {
throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
}
} catch (\ReflectionException $e) {
throw new RuntimeException(sprintf('Invalid service "%s": %s.', $this->currentId, lcfirst(rtrim($e->getMessage(), '.'))));
}
if (!$r = $r->getConstructor()) {
if ($required) {

View File

@ -27,6 +27,7 @@ class ResolveBindingsPass extends AbstractRecursivePass
{
private $usedBindings = array();
private $unusedBindings = array();
private $errorMessages = array();
/**
* {@inheritdoc}
@ -37,11 +38,19 @@ class ResolveBindingsPass extends AbstractRecursivePass
parent::process($container);
foreach ($this->unusedBindings as list($key, $serviceId)) {
throw new InvalidArgumentException(sprintf('Unused binding "%s" in service "%s".', $key, $serviceId));
$message = sprintf('Unused binding "%s" in service "%s".', $key, $serviceId);
if ($this->errorMessages) {
$message .= sprintf("\nCould be related to%s:", 1 < \count($this->errorMessages) ? ' one of' : '');
}
foreach ($this->errorMessages as $m) {
$message .= "\n - ".$m;
}
throw new InvalidArgumentException($message);
}
} finally {
$this->usedBindings = array();
$this->unusedBindings = array();
$this->errorMessages = array();
}
}
@ -94,6 +103,7 @@ class ResolveBindingsPass extends AbstractRecursivePass
$calls[] = array($constructor, $value->getArguments());
}
} catch (RuntimeException $e) {
$this->errorMessages[] = $e->getMessage();
$this->container->getDefinition($this->currentId)->addError($e->getMessage());
return parent::processValue($value, $isRoot);

View File

@ -18,6 +18,7 @@ use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy;
use Symfony\Component\DependencyInjection\Tests\Fixtures\ParentNotExists;
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
use Symfony\Component\DependencyInjection\TypedReference;
@ -61,6 +62,21 @@ class ResolveBindingsPassTest extends TestCase
$pass->process($container);
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessageRegexp Unused binding "$quz" in service [\s\S]+ Invalid service ".*\\ParentNotExists": class NotExists not found\.
*/
public function testMissingParent()
{
$container = new ContainerBuilder();
$definition = $container->register(ParentNotExists::class, ParentNotExists::class);
$definition->setBindings(array('$quz' => '123'));
$pass = new ResolveBindingsPass();
$pass->process($container);
}
public function testTypedReferenceSupport()
{
$container = new ContainerBuilder();