Skip to content

Commit b1a730e

Browse files
[DependencyInjection] Optimize out "current()" when it's used as service factory
1 parent 560f092 commit b1a730e

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

Dumper/PhpDumper.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,9 @@ private function addNewInstance(Definition $definition, string $return = '', str
11541154
if (null !== $definition->getFactory()) {
11551155
$callable = $definition->getFactory();
11561156

1157+
if ('current' === $callable && [0] === array_keys($definition->getArguments()) && \is_array($value) && [0] === array_keys($value)) {
1158+
return $return.$this->dumpValue($value[0]).$tail;
1159+
}
11571160
if (['Closure', 'fromCallable'] === $callable && [0] === array_keys($definition->getArguments())) {
11581161
$callable = $definition->getArgument(0);
11591162
if ($callable instanceof ServiceClosureArgument) {

Tests/Dumper/PhpDumperTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1503,6 +1503,37 @@ public function testWitherWithStaticReturnType()
15031503
$this->assertInstanceOf(Foo::class, $wither->foo);
15041504
}
15051505

1506+
public function testCurrentFactoryInlining()
1507+
{
1508+
$container = new ContainerBuilder();
1509+
$container->register(Foo::class);
1510+
1511+
$container
1512+
->register('inlined_current', Foo::class)
1513+
->setFactory('current')
1514+
->setPublic(true)
1515+
->setArguments([[new Reference(Foo::class)]]);
1516+
1517+
$container
1518+
->register('not_inlined_current', Foo::class)
1519+
->setFactory('current')
1520+
->setPublic(true)
1521+
->setArguments([[new Reference(Foo::class), 123]]);
1522+
1523+
$container->compile();
1524+
$dumper = new PhpDumper($container);
1525+
$dump = $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Service_CurrentFactoryInlining']);
1526+
file_put_contents(self::$fixturesPath.'/php/services_current_factory_inlining.php', $dump);
1527+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_current_factory_inlining.php', $dump);
1528+
eval('?>'.$dump);
1529+
1530+
$container = new \Symfony_DI_PhpDumper_Service_CurrentFactoryInlining();
1531+
1532+
$foo = $container->get('inlined_current');
1533+
$this->assertInstanceOf(Foo::class, $foo);
1534+
$this->assertSame($foo, $container->get('not_inlined_current'));
1535+
}
1536+
15061537
public function testDumpServiceWithAbstractArgument()
15071538
{
15081539
$this->expectException(RuntimeException::class);
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
4+
use Symfony\Component\DependencyInjection\ContainerInterface;
5+
use Symfony\Component\DependencyInjection\Container;
6+
use Symfony\Component\DependencyInjection\Exception\LogicException;
7+
use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
8+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
9+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
10+
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
11+
12+
/**
13+
* @internal This class has been auto-generated by the Symfony Dependency Injection Component.
14+
*/
15+
class Symfony_DI_PhpDumper_Service_CurrentFactoryInlining extends Container
16+
{
17+
protected $parameters = [];
18+
protected readonly \WeakReference $ref;
19+
20+
public function __construct()
21+
{
22+
$this->ref = \WeakReference::create($this);
23+
$this->services = $this->privates = [];
24+
$this->methodMap = [
25+
'inlined_current' => 'getInlinedCurrentService',
26+
'not_inlined_current' => 'getNotInlinedCurrentService',
27+
];
28+
29+
$this->aliases = [];
30+
}
31+
32+
public function compile(): void
33+
{
34+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
35+
}
36+
37+
public function isCompiled(): bool
38+
{
39+
return true;
40+
}
41+
42+
public function getRemovedIds(): array
43+
{
44+
return [
45+
'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\Foo' => true,
46+
];
47+
}
48+
49+
/**
50+
* Gets the public 'inlined_current' shared service.
51+
*
52+
* @return \Symfony\Component\DependencyInjection\Tests\Compiler\Foo
53+
*/
54+
protected static function getInlinedCurrentService($container)
55+
{
56+
return $container->services['inlined_current'] = ($container->privates['Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\Foo'] ??= new \Symfony\Component\DependencyInjection\Tests\Compiler\Foo());
57+
}
58+
59+
/**
60+
* Gets the public 'not_inlined_current' shared service.
61+
*
62+
* @return \Symfony\Component\DependencyInjection\Tests\Compiler\Foo
63+
*/
64+
protected static function getNotInlinedCurrentService($container)
65+
{
66+
return $container->services['not_inlined_current'] = \current([($container->privates['Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\Foo'] ??= new \Symfony\Component\DependencyInjection\Tests\Compiler\Foo()), 123]);
67+
}
68+
}

0 commit comments

Comments
 (0)