[DI] fix perf issue with lazy autowire error messages

This commit is contained in:
Nicolas Grekas 2019-07-24 16:20:30 +02:00
parent 1fc080b8aa
commit 3c3bda5423

View File

@ -37,6 +37,7 @@ class AutowirePass extends AbstractRecursivePass
private $getPreviousValue; private $getPreviousValue;
private $decoratedMethodIndex; private $decoratedMethodIndex;
private $decoratedMethodArgumentIndex; private $decoratedMethodArgumentIndex;
private $typesClone;
public function __construct(bool $throwOnAutowireException = true) public function __construct(bool $throwOnAutowireException = true)
{ {
@ -49,16 +50,16 @@ class AutowirePass extends AbstractRecursivePass
public function process(ContainerBuilder $container) public function process(ContainerBuilder $container)
{ {
try { try {
$this->typesClone = clone $this;
parent::process($container); parent::process($container);
} finally { } finally {
$this->types = null;
$this->ambiguousServiceTypes = null;
$this->decoratedClass = null; $this->decoratedClass = null;
$this->decoratedId = null; $this->decoratedId = null;
$this->methodCalls = null; $this->methodCalls = null;
$this->getPreviousValue = null; $this->getPreviousValue = null;
$this->decoratedMethodIndex = null; $this->decoratedMethodIndex = null;
$this->decoratedMethodArgumentIndex = null; $this->decoratedMethodArgumentIndex = null;
$this->typesClone = null;
} }
} }
@ -375,20 +376,22 @@ class AutowirePass extends AbstractRecursivePass
private function createTypeNotFoundMessageCallback(TypedReference $reference, $label) private function createTypeNotFoundMessageCallback(TypedReference $reference, $label)
{ {
$container = new ContainerBuilder($this->container->getParameterBag()); if (null === $this->typesClone->container) {
$container->setAliases($this->container->getAliases()); $this->typesClone->container = new ContainerBuilder($this->container->getParameterBag());
$container->setDefinitions($this->container->getDefinitions()); $this->typesClone->container->setAliases($this->container->getAliases());
$container->setResourceTracking(false); $this->typesClone->container->setDefinitions($this->container->getDefinitions());
$this->typesClone->container->setResourceTracking(false);
}
$currentId = $this->currentId; $currentId = $this->currentId;
return function () use ($container, $reference, $label, $currentId) { return (function () use ($reference, $label, $currentId) {
return $this->createTypeNotFoundMessage($container, $reference, $label, $currentId); return $this->createTypeNotFoundMessage($reference, $label, $currentId);
}; })->bindTo($this->typesClone);
} }
private function createTypeNotFoundMessage(ContainerBuilder $container, TypedReference $reference, $label, string $currentId) private function createTypeNotFoundMessage(TypedReference $reference, $label, string $currentId)
{ {
if (!$r = $container->getReflectionClass($type = $reference->getType(), false)) { if (!$r = $this->container->getReflectionClass($type = $reference->getType(), false)) {
// either $type does not exist or a parent class does not exist // either $type does not exist or a parent class does not exist
try { try {
$resource = new ClassExistenceResource($type, false); $resource = new ClassExistenceResource($type, false);
@ -401,8 +404,8 @@ class AutowirePass extends AbstractRecursivePass
$message = sprintf('has type "%s" but this class %s.', $type, $parentMsg ? sprintf('is missing a parent class (%s)', $parentMsg) : 'was not found'); $message = sprintf('has type "%s" but this class %s.', $type, $parentMsg ? sprintf('is missing a parent class (%s)', $parentMsg) : 'was not found');
} else { } else {
$alternatives = $this->createTypeAlternatives($container, $reference); $alternatives = $this->createTypeAlternatives($this->container, $reference);
$message = $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, $alternatives); $message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $alternatives);
if ($r->isInterface() && !$alternatives) { if ($r->isInterface() && !$alternatives) {