8000 [DependencyInjection] Do not add `return` in `LazyClosure` when retur… · Wink-dev/symfony@692704e · GitHub
[go: up one dir, main page]

Skip to content

Commit 692704e

Browse files
ruudknicolas-grekas
authored andcommitted
[DependencyInjection] Do not add return in LazyClosure when return type of closure is void
1 parent 1a15b12 commit 692704e

File tree

4 files changed

+47
-10
lines changed

4 files changed

+47
-10
lines changed

src/Symfony/Component/DependencyInjection/Argument/LazyClosure.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ public static function getCode(string $initializer, array $callable, Definition
7878
throw new RuntimeException("Cannot create lazy closure{$id} because its corresponding callable is invalid.");
7979
}
8080

81-
$code = ProxyHelper::exportSignature($r->getMethod($method), true, $args);
81+
$methodReflector = $r->getMethod($method);
82+
$code = ProxyHelper::exportSignature($methodReflector, true, $args);
8283

8384
if ($asClosure) {
8485
$code = ' { '.preg_replace('/: static$/', ': \\'.$r->name, $code);
@@ -87,7 +88,7 @@ public static function getCode(string $initializer, array $callable, Definition
8788
}
8889

8990
$code = 'new class('.$initializer.') extends \\'.self::class
90-
.$code.' { return $this->service->'.$callable[1].'('.$args.'); } '
91+
.$code.' { '.($methodReflector->hasReturnType() && 'void' === (string) $methodReflector->getReturnType() ? '' : 'return ').'$this->service->'.$callable[1].'('.$args.'); } '
9192
.'}';
9293

9394
return $asClosure ? '('.$code.')->'.$method.'(...)' : $code;

src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
use Symfony\Component\DependencyInjection\Tests\Compiler\AInterface;
4949
use Symfony\Component\DependencyInjection\Tests\Compiler\Foo;
5050
use Symfony\Component\DependencyInjection\Tests\Compiler\FooAnnotation;
51+
use Symfony\Component\DependencyInjection\Tests\Compiler\FooVoid;
5152
use Symfony\Component\DependencyInjection\Tests\Compiler\IInterface;
5253
use Symfony\Component\DependencyInjection\Tests\Compiler\MyCallable;
5354
use Symfony\Component\DependencyInjection\Tests\Compiler\SingleMethodInterface;
@@ -1874,12 +1875,18 @@ public function testAutowireClosure()
18741875
public function testLazyClosure()
18751876
{
18761877
$container = new ContainerBuilder();
1877-
$container->register('closure', 'Closure')
1878+
$container->register('closure1', 'Closure')
18781879
->setPublic('true')
18791880
->setFactory(['Closure', 'fromCallable'])
18801881
->setLazy(true)
18811882
->setArguments([[new Reference('foo'), 'cloneFoo']]);
1883+
$container->register('closure2', 'Closure')
1884+
->setPublic('true')
1885+
->setFactory(['Closure', 'fromCallable'])
1886+
->setLazy(true)
1887+
->setArguments([[new Reference('foo_void'), '__invoke']]);
18821888
$container->register('foo', Foo::class);
1889+
$container->register('foo_void', FooVoid::class);
18831890
$container->compile();
18841891
$dumper = new PhpDumper($container);
18851892

@@ -1890,11 +1897,18 @@ public function testLazyClosure()
18901897
$container = new \Symfony_DI_PhpDumper_Test_Lazy_Closure();
18911898

18921899
$cloned = Foo::$counter;
1893-
$this->assertInstanceOf(\Closure::class, $container->get('closure'));
1900+
$this->assertInstanceOf(\Closure::class, $container->get('closure1'));
18941901
$this->assertSame($cloned, Foo::$counter);
1895-
$this->assertInstanceOf(Foo::class, $container->get('closure')());
1902+
$this->assertInstanceOf(Foo::class, $container->get('closure1')());
18961903
$this->assertSame(1 + $cloned, Foo::$counter);
1897-
$this->assertSame(1, (new \ReflectionFunction($container->get('closure')))->getNumberOfParameters());
1904+
$this->assertSame(1, (new \ReflectionFunction($container->get('closure1')))->getNumberOfParameters());
1905+
1906+
$counter = FooVoid::$counter;
1907+
$this->assertInstanceOf(\Closure::class, $container->get('closure2'));
1908+
$this->assertSame($counter, FooVoid::$counter);
1909+
$container->get('closure2')('Hello');
1910+
$this->assertSame(1 + $counter, FooVoid::$counter);
1911+
$this->assertSame(1, (new \ReflectionFunction($container->get('closure2')))->getNumberOfParameters());
18981912
}
18991913

19001914
public function testLazyAutowireAttribute()

src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@ public function cloneFoo(\stdClass $bar = null): static
3838
}
3939
}
4040

41+
class FooVoid
42+
{
43+
public static int $counter = 0;
44+
45+
public function __invoke(string $name): void
46+
{
47+
++self::$counter;
48+
}
49+
}
50+
4151
class Bar
4252
{
4353
public function __construct(Foo $foo)

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/lazy_closure.php

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ public function __construct()
2020
{
2121
$this->services = $this->privates = [];
2222
$this->methodMap = [
23-
'closure' => 'getClosureService',
23+
'closure1' => 'getClosure1Service',
24+
'closure2' => 'getClosure2Service',
2425
];
2526

2627
$this->aliases = [];
@@ -40,6 +41,7 @@ public function getRemovedIds(): array
4041
{
4142
return [
4243
'foo' => true,
44+
'foo_void' => true,
4345
];
4446
}
4547

@@ -49,12 +51,22 @@ protected function createProxy($class, \Closure $factory)
4951
}
5052

5153
/**
52-
* Gets the public 'closure' shared service.
54+
* Gets the public 'closure1' shared service.
5355
*
5456
* @return \Closure
5557
*/
56-
protected static function getClosureService($container, $lazyLoad = true)
58+
protected static function getClosure1Service($container, $lazyLoad = true)
5759
{
58-
return $container->services['closure'] = (new class(fn () => new \Symfony\Component\DependencyInjection\Tests\Compiler\Foo()) extends \Symfony\Component\DependencyInjection\Argument\LazyClosure { public function cloneFoo(?\stdClass $bar = null): \Symfony\Component\DependencyInjection\Tests\Compiler\Foo { return $this->service->cloneFoo(...\func_get_args()); } })->cloneFoo(...);
60+
return $container->services['closure1'] = (new class(fn () => new \Symfony\Component\DependencyInjection\Tests\Compiler\Foo()) extends \Symfony\Component\DependencyInjection\Argument\LazyClosure { public function cloneFoo(?\stdClass $bar = null): \Symfony\Component\DependencyInjection\Tests\Compiler\Foo { return $this->service->cloneFoo(...\func_get_args()); } })->cloneFoo(...);
61+
}
62+
63+
/**
64+
* Gets the public 'closure2' shared service.
65+
*
66+
* @return \Closure
67+
*/
68+
protected static function getClosure2Service($container, $lazyLoad = true)
69+
{
70+
return $container->services['closure2'] = (new class(fn () => new \Symfony\Component\DependencyInjection\Tests\Compiler\FooVoid()) extends \Symfony\Component\DependencyInjection\Argument\LazyClosure { public function __invoke(string $name): void { $this->service->__invoke(...\func_get_args()); } })->__invoke(...);
5971
}
6072
}

0 commit comments

Comments
 (0)
0