Merge branch '5.1'

* 5.1:
  [DI] fix inlining of non-shared services
This commit is contained in:
Nicolas Grekas 2020-09-01 20:07:33 +02:00
commit 78eca9607a
4 changed files with 120 additions and 0 deletions

View File

@ -29,6 +29,7 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass
private $connectedIds = [];
private $notInlinedIds = [];
private $inlinedIds = [];
private $notInlinableIds = [];
private $graph;
public function __construct(AnalyzeServiceReferencesPass $analyzingPass = null)
@ -85,6 +86,10 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass
} while ($this->inlinedIds && $this->analyzingPass);
foreach ($remainingInlinedIds as $id) {
if (isset($this->notInlinableIds[$id])) {
continue;
}
$definition = $container->getDefinition($id);
if (!$definition->isShared() && !$definition->isPublic()) {
@ -94,6 +99,7 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass
} finally {
$this->container = null;
$this->connectedIds = $this->notInlinedIds = $this->inlinedIds = [];
$this->notInlinableIds = [];
$this->graph = null;
}
}
@ -124,6 +130,8 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass
$definition = $this->container->getDefinition($id);
if (!$this->isInlineableDefinition($id, $definition)) {
$this->notInlinableIds[$id] = true;
return $value;
}

View File

@ -930,6 +930,10 @@ EOF;
return '';
}
if ($this->container->hasDefinition($targetId) && ($def = $this->container->getDefinition($targetId)) && !$def->isShared()) {
return '';
}
$hasSelfRef = isset($this->circularReferences[$id][$targetId]) && !isset($this->definitionVariables[$definition]);
if ($hasSelfRef && !$forConstructor && !$forConstructor = !$this->circularReferences[$id][$targetId]) {

View File

@ -21,6 +21,7 @@ use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceLocator as ArgumentServiceLocator;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\ContainerBuilder;
@ -720,6 +721,24 @@ class PhpDumperTest extends TestCase
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_non_shared_lazy.php', $dumper->dump());
}
public function testNonSharedDuplicates()
{
$container = new ContainerBuilder();
$container->register('foo', 'stdClass')->setShared(false);
$container->register('baz', 'stdClass')->setPublic(true)
->addArgument(new ServiceLocatorArgument(['foo' => new Reference('foo')]));
$container->register('bar', 'stdClass')->setPublic(true)
->addArgument(new Reference('foo'))
->addArgument(new Reference('foo'))
;
$container->compile();
$dumper = new PhpDumper($container);
$dumper->setProxyDumper(new \DummyProxyDumper());
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_non_shared_duplicates.php', $dumper->dump());
}
public function testInitializePropertiesBeforeMethodCalls()
{
require_once self::$fixturesPath.'/includes/classes.php';

View File

@ -0,0 +1,89 @@
<?php
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
/**
* @internal This class has been auto-generated by the Symfony Dependency Injection Component.
*/
class ProjectServiceContainer extends Container
{
protected $parameters = [];
protected $getService;
public function __construct()
{
$this->getService = \Closure::fromCallable([$this, 'getService']);
$this->services = $this->privates = [];
$this->methodMap = [
'bar' => 'getBarService',
'baz' => 'getBazService',
];
$this->aliases = [];
}
public function compile(): void
{
throw new LogicException('You cannot compile a dumped container that was already compiled.');
}
public function isCompiled(): bool
{
return true;
}
public function getRemovedIds(): array
{
return [
'.service_locator.mtT6G8y' => true,
'Psr\\Container\\ContainerInterface' => true,
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
'foo' => true,
];
}
/**
* Gets the public 'bar' shared service.
*
* @return \stdClass
*/
protected function getBarService()
{
return $this->services['bar'] = new \stdClass((new \stdClass()), (new \stdClass()));
}
/**
* Gets the public 'baz' shared service.
*
* @return \stdClass
*/
protected function getBazService()
{
return $this->services['baz'] = new \stdClass(new \Symfony\Component\DependencyInjection\Argument\ServiceLocator($this->getService, [
'foo' => [false, 'foo', 'getFooService', false],
], [
'foo' => '?',
]));
}
/**
* Gets the private 'foo' service.
*
* @return \stdClass
*/
protected function getFooService()
{
$this->factories['service_container']['foo'] = function () {
return new \stdClass();
};
return $this->factories['service_container']['foo']();
}
}