Skip to content

Commit

Permalink
feature #22323 [DI] Report cascades of autowiring error messages (nic…
Browse files Browse the repository at this point in the history
…olas-grekas)

This PR was merged into the 3.3-dev branch.

Discussion
----------

[DI] Report cascades of autowiring error messages

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

Enhance DX by reporting the cascade of errors that lead to an autowiring error, eg:
![capture du 2017-04-07 00-03-28](https://cloud.githubusercontent.com/assets/243674/24777441/ac1fb118-1b25-11e7-9459-ecdf13e79798.png)

Also contains a cleanup found along the way: processing of nested definitions should happen before the current one so that TypedReference are processed only once.

Commits
-------

6c0f5e3 [DI] Reporte cascades of autowiring error messages
  • Loading branch information
fabpot committed Apr 6, 2017
2 parents 451c32a + 6c0f5e3 commit 3458edf
Showing 1 changed file with 23 additions and 16 deletions.
39 changes: 23 additions & 16 deletions src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
Expand Up @@ -30,6 +30,7 @@ class AutowirePass extends AbstractRecursivePass
private $types;
private $ambiguousServiceTypes = array();
private $autowired = array();
private $lastFailure;

/**
* {@inheritdoc}
Expand Down Expand Up @@ -77,21 +78,19 @@ protected function processValue($value, $isRoot = false)
{
if ($value instanceof TypedReference) {
if ($ref = $this->getAutowiredReference($value)) {
$value = $ref;
} else {
$this->container->log($this, $this->createTypeNotFoundMessage($value->getType(), 'typed reference'));
return $ref;
}
$this->container->log($this, $this->createTypeNotFoundMessage($value->getType(), 'it'));
}
if (!$value instanceof Definition) {
return parent::processValue($value, $isRoot);
}
if (!$value->isAutowired() || $value->isAbstract() || !$value->getClass()) {
return parent::processValue($value, $isRoot);
$value = parent::processValue($value, $isRoot);

if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) {
return $value;
}
if (!$reflectionClass = $this->container->getReflectionClass($value->getClass())) {
$this->container->log($this, sprintf('Skipping service "%s": Class or interface "%s" does not exist.', $this->currentId, $value->getClass()));

return parent::processValue($value, $isRoot);
return $value;
}

$autowiredMethods = $this->getMethodsToAutowire($reflectionClass);
Expand All @@ -115,7 +114,7 @@ protected function processValue($value, $isRoot = false)
$value->setMethodCalls($methodCalls);
}

return parent::processValue($value, $isRoot);
return $value;
}

/**
Expand Down Expand Up @@ -246,9 +245,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a

if ($parameter->isDefaultValueAvailable()) {
$value = $parameter->getDefaultValue();
} elseif ($parameter->allowsNull()) {
$value = null;
} else {
} elseif (!$parameter->allowsNull()) {
throw new RuntimeException($failureMessage);
}
$this->container->log($this, $failureMessage);
Expand Down Expand Up @@ -279,6 +276,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
*/
private function getAutowiredReference(TypedReference $reference)
{
$this->lastFailure = null;
$type = $reference->getType();

if ($type !== (string) $reference || ($this->container->has($type) && !$this->container->findDefinition($type)->isAbstract())) {
Expand Down Expand Up @@ -396,7 +394,8 @@ private function createAutowiredDefinition($type)
}

$currentId = $this->currentId;
$this->currentId = $this->autowired[$type] = $argumentId = sprintf('autowired.%s', $type);
$this->currentId = $type;
$this->autowired[$type] = $argumentId = sprintf('autowired.%s', $type);
$argumentDefinition = new Definition($type);
$argumentDefinition->setPublic(false);
$argumentDefinition->setAutowired(true);
Expand All @@ -406,7 +405,8 @@ private function createAutowiredDefinition($type)
$this->container->setDefinition($argumentId, $argumentDefinition);
} catch (RuntimeException $e) {
$this->autowired[$type] = false;
$this->container->log($this, $e->getMessage());
$this->lastFailure = $e->getMessage();
$this->container->log($this, $this->lastFailure);

return;
} finally {
Expand All @@ -427,7 +427,14 @@ private function createTypeNotFoundMessage($type, $label)
$message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $this->createTypeAlternatives($type));
}

return sprintf('Cannot autowire service "%s": %s %s', $this->currentId, $label, $message);
$message = sprintf('Cannot autowire service "%s": %s %s', $this->currentId, $label, $message);

if (null !== $this->lastFailure) {
$message = $this->lastFailure."\n".$message;
$this->lastFailure = null;
}

return $message;
}

private function createTypeAlternatives($type)
Expand Down

0 comments on commit 3458edf

Please sign in to comment.