feature #36636 Add support of PHP8 static return type for withers (l-vo)
This PR was merged into the 5.1-dev branch.
Discussion
----------
Add support of PHP8 static return type for withers
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | no
| New feature? | yes
| Deprecations? | no
| Tickets | https://github.com/orgs/symfony/projects/1#card-35852557
| License | MIT
| Doc PR |
Commits
-------
04fdf05cff
Add support of PHP8 static return type for withers
This commit is contained in:
commit
eebb3efa2c
1
.github/patch-types.php
vendored
1
.github/patch-types.php
vendored
@ -23,6 +23,7 @@ foreach ($loader->getClassMap() as $class => $file) {
|
||||
case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Compiler/OptionalServiceClass.php'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/ParentNotExists.php'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/BadClasses/MissingParent.php'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/WitherStaticReturnType.php'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/ErrorHandler/Tests/Fixtures/'):
|
||||
case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php'):
|
||||
|
@ -20,6 +20,7 @@ CHANGELOG
|
||||
* deprecated `Definition::getDeprecationMessage()`, use `Definition::getDeprecation()` instead
|
||||
* deprecated `Alias::getDeprecationMessage()`, use `Alias::getDeprecation()` instead
|
||||
* deprecated PHP-DSL's `inline()` function, use `service()` instead
|
||||
* added support of PHP8 static return type for withers
|
||||
|
||||
5.0.0
|
||||
-----
|
||||
|
@ -51,7 +51,7 @@ class AutowireRequiredMethodsPass extends AbstractRecursivePass
|
||||
while (true) {
|
||||
if (false !== $doc = $r->getDocComment()) {
|
||||
if (false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) {
|
||||
if (preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@return\s++static[\s\*]#i', $doc)) {
|
||||
if ($this->isWither($reflectionMethod, $doc)) {
|
||||
$withers[] = [$reflectionMethod->name, [], true];
|
||||
} else {
|
||||
$value->addMethodCall($reflectionMethod->name, []);
|
||||
@ -81,4 +81,20 @@ class AutowireRequiredMethodsPass extends AbstractRecursivePass
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function isWither(\ReflectionMethod $reflectionMethod, string $doc): bool
|
||||
{
|
||||
$match = preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@return\s++(static|\$this)[\s\*]#i', $doc, $matches);
|
||||
if ($match && 'static' === $matches[1]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($match && '$this' === $matches[1]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$reflectionType = $reflectionMethod->hasReturnType() ? $reflectionMethod->getReturnType() : null;
|
||||
|
||||
return $reflectionType instanceof \ReflectionNamedType && 'static' === $reflectionType->getName();
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\DependencyInjection\Compiler\AutowireRequiredMethodsPass;
|
||||
use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\WitherStaticReturnType;
|
||||
|
||||
require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php';
|
||||
|
||||
@ -99,4 +100,28 @@ class AutowireRequiredMethodsPassTest extends TestCase
|
||||
];
|
||||
$this->assertSame($expected, $methodCalls);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8
|
||||
*/
|
||||
public function testWitherWithStaticReturnTypeInjection()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register(Foo::class);
|
||||
|
||||
$container
|
||||
->register('wither', WitherStaticReturnType::class)
|
||||
->setAutowired(true);
|
||||
|
||||
(new ResolveClassPass())->process($container);
|
||||
(new AutowireRequiredMethodsPass())->process($container);
|
||||
|
||||
$methodCalls = $container->getDefinition('wither')->getMethodCalls();
|
||||
|
||||
$expected = [
|
||||
['withFoo', [], true],
|
||||
['setFoo', []],
|
||||
];
|
||||
$this->assertSame($expected, $methodCalls);
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\FooWithAbstractArgument;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\ScalarFactory;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\SimilarArgumentsDummy;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\WitherStaticReturnType;
|
||||
use Symfony\Component\DependencyInjection\TypedReference;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
|
||||
@ -1624,6 +1625,25 @@ class ContainerBuilderTest extends TestCase
|
||||
$this->assertInstanceOf(Foo::class, $wither->foo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8
|
||||
*/
|
||||
public function testWitherWithStaticReturnType()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register(Foo::class);
|
||||
|
||||
$container
|
||||
->register('wither', WitherStaticReturnType::class)
|
||||
->setPublic(true)
|
||||
->setAutowired(true);
|
||||
|
||||
$container->compile();
|
||||
|
||||
$wither = $container->get('wither');
|
||||
$this->assertInstanceOf(Foo::class, $wither->foo);
|
||||
}
|
||||
|
||||
public function testAutoAliasing()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
@ -42,6 +42,7 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\ScalarFactory;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestDefinition1;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber;
|
||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\WitherStaticReturnType;
|
||||
use Symfony\Component\DependencyInjection\TypedReference;
|
||||
use Symfony\Component\DependencyInjection\Variable;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
@ -1362,6 +1363,31 @@ class PhpDumperTest extends TestCase
|
||||
$this->assertInstanceOf(Foo::class, $wither->foo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires PHP 8
|
||||
*/
|
||||
public function testWitherWithStaticReturnType()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container->register(Foo::class);
|
||||
|
||||
$container
|
||||
->register('wither', WitherStaticReturnType::class)
|
||||
->setPublic(true)
|
||||
->setAutowired(true);
|
||||
|
||||
$container->compile();
|
||||
$dumper = new PhpDumper($container);
|
||||
$dump = $dumper->dump(['class' => 'Symfony_DI_PhpDumper_Service_WitherStaticReturnType']);
|
||||
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_wither_staticreturntype.php', $dump);
|
||||
eval('?>'.$dump);
|
||||
|
||||
$container = new \Symfony_DI_PhpDumper_Service_WitherStaticReturnType();
|
||||
|
||||
$wither = $container->get('wither');
|
||||
$this->assertInstanceOf(Foo::class, $wither->foo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @group legacy
|
||||
*/
|
||||
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
|
||||
|
||||
class WitherStaticReturnType
|
||||
{
|
||||
public $foo;
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
public function withFoo(Foo $foo): static
|
||||
{
|
||||
$new = clone $this;
|
||||
$new->foo = $foo;
|
||||
|
||||
return $new;
|
||||
}
|
||||
|
||||
/**
|
||||
* @required
|
||||
* @return $this
|
||||
*/
|
||||
public function setFoo(Foo $foo): static
|
||||
{
|
||||
$this->foo = $foo;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
<?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 Symfony_DI_PhpDumper_Service_WitherStaticReturnType extends Container
|
||||
{
|
||||
protected $parameters = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->services = $this->privates = [];
|
||||
$this->methodMap = [
|
||||
'wither' => 'getWitherService',
|
||||
];
|
||||
|
||||
$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 [
|
||||
'Psr\\Container\\ContainerInterface' => true,
|
||||
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
|
||||
'Symfony\\Component\\DependencyInjection\\Tests\\Compiler\\Foo' => true,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public 'wither' shared autowired service.
|
||||
*
|
||||
* @return \Symfony\Component\DependencyInjection\Tests\Compiler\WitherStaticReturnType
|
||||
*/
|
||||
protected function getWitherService()
|
||||
{
|
||||
$instance = new \Symfony\Component\DependencyInjection\Tests\Compiler\WitherStaticReturnType();
|
||||
|
||||
$a = new \Symfony\Component\DependencyInjection\Tests\Compiler\Foo();
|
||||
|
||||
$this->services['wither'] = $instance = $instance->withFoo($a);
|
||||
$instance->setFoo($a);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user