minor #22451 [DI] Enhance auto-registration failure message (nicolas-grekas)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[DI] Enhance auto-registration failure message

| Q             | A
| ------------- | ---
| Branch?       | 3.3
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | https://github.com/symfony/symfony/pull/22306#issuecomment-294247722
| License       | MIT
| Doc PR        | -

Commits
-------

b23d5da1c3 [DI] Enhance auto-registration failure message
This commit is contained in:
Fabien Potencier 2017-04-17 14:36:54 -06:00
commit e4f854d8c9
2 changed files with 15 additions and 8 deletions

View File

@ -80,7 +80,7 @@ class AutowirePass extends AbstractRecursivePass
if ($ref = $this->getAutowiredReference($value)) { if ($ref = $this->getAutowiredReference($value)) {
return $ref; return $ref;
} }
$this->container->log($this, $this->createTypeNotFoundMessage($value->getType(), 'it')); $this->container->log($this, $this->createTypeNotFoundMessage($value, 'it'));
} }
$value = parent::processValue($value, $isRoot); $value = parent::processValue($value, $isRoot);
@ -240,8 +240,8 @@ class AutowirePass extends AbstractRecursivePass
continue; continue;
} }
if (!$value = $this->getAutowiredReference(new TypedReference($type, $type, !$parameter->isOptional() ? $class : ''))) { if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, !$parameter->isOptional() ? $class : ''))) {
$failureMessage = $this->createTypeNotFoundMessage($type, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method)); $failureMessage = $this->createTypeNotFoundMessage($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method));
if ($parameter->isDefaultValueAvailable()) { if ($parameter->isDefaultValueAvailable()) {
$value = $parameter->getDefaultValue(); $value = $parameter->getDefaultValue();
@ -424,13 +424,13 @@ class AutowirePass extends AbstractRecursivePass
return new TypedReference($argumentId, $type); return new TypedReference($argumentId, $type);
} }
private function createTypeNotFoundMessage($type, $label) private function createTypeNotFoundMessage(TypedReference $reference, $label)
{ {
if (!$r = $this->container->getReflectionClass($type, true)) { if (!$r = $this->container->getReflectionClass($type = $reference->getType(), true)) {
$message = sprintf('has type "%s" but this class does not exist.', $type); $message = sprintf('has type "%s" but this class does not exist.', $type);
} else { } else {
$message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists'; $message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists';
$message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $this->createTypeAlternatives($type)); $message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $this->createTypeAlternatives($reference));
} }
$message = sprintf('Cannot autowire service "%s": %s %s', $this->currentId, $label, $message); $message = sprintf('Cannot autowire service "%s": %s %s', $this->currentId, $label, $message);
@ -443,12 +443,14 @@ class AutowirePass extends AbstractRecursivePass
return $message; return $message;
} }
private function createTypeAlternatives($type) private function createTypeAlternatives(TypedReference $reference)
{ {
if (isset($this->ambiguousServiceTypes[$type])) { if (isset($this->ambiguousServiceTypes[$type = $reference->getType()])) {
$message = sprintf('one of these existing services: "%s"', implode('", "', $this->ambiguousServiceTypes[$type])); $message = sprintf('one of these existing services: "%s"', implode('", "', $this->ambiguousServiceTypes[$type]));
} elseif (isset($this->types[$type])) { } elseif (isset($this->types[$type])) {
$message = sprintf('the existing "%s" service', $this->types[$type]); $message = sprintf('the existing "%s" service', $this->types[$type]);
} elseif ($reference->getRequiringClass() && !$reference->canBeAutoregistered()) {
return ' It cannot be auto-registered because it is from a different root namespace.';
} else { } else {
return; return;
} }

View File

@ -694,6 +694,7 @@ class AutowirePassTest extends TestCase
{ {
return array( return array(
array('setNotAutowireable', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setNotAutowireable()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class does not exist.'), array('setNotAutowireable', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setNotAutowireable()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class does not exist.'),
array('setDifferentNamespace', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setDifferentNamespace()" references class "stdClass" but no such service exists. It cannot be auto-registered because it is from a different root namespace.'),
array(null, 'Cannot autowire service "foo": method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setProtectedMethod()" must be public.'), array(null, 'Cannot autowire service "foo": method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setProtectedMethod()" must be public.'),
); );
} }
@ -1019,6 +1020,10 @@ class NotWireable
{ {
} }
public function setDifferentNamespace(\stdClass $n)
{
}
public function setOptionalNoTypeHint($foo = null) public function setOptionalNoTypeHint($foo = null)
{ {
} }