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/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/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/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/DependencyInjection/Tests/Fixtures/php/'):
|
||||||
case false !== strpos($file, '/src/Symfony/Component/ErrorHandler/Tests/Fixtures/'):
|
case false !== strpos($file, '/src/Symfony/Component/ErrorHandler/Tests/Fixtures/'):
|
||||||
case false !== strpos($file, '/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php'):
|
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 `Definition::getDeprecationMessage()`, use `Definition::getDeprecation()` instead
|
||||||
* deprecated `Alias::getDeprecationMessage()`, use `Alias::getDeprecation()` instead
|
* deprecated `Alias::getDeprecationMessage()`, use `Alias::getDeprecation()` instead
|
||||||
* deprecated PHP-DSL's `inline()` function, use `service()` instead
|
* deprecated PHP-DSL's `inline()` function, use `service()` instead
|
||||||
|
* added support of PHP8 static return type for withers
|
||||||
|
|
||||||
5.0.0
|
5.0.0
|
||||||
-----
|
-----
|
||||||
|
@ -51,7 +51,7 @@ class AutowireRequiredMethodsPass extends AbstractRecursivePass
|
|||||||
while (true) {
|
while (true) {
|
||||||
if (false !== $doc = $r->getDocComment()) {
|
if (false !== $doc = $r->getDocComment()) {
|
||||||
if (false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) {
|
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];
|
$withers[] = [$reflectionMethod->name, [], true];
|
||||||
} else {
|
} else {
|
||||||
$value->addMethodCall($reflectionMethod->name, []);
|
$value->addMethodCall($reflectionMethod->name, []);
|
||||||
@ -81,4 +81,20 @@ class AutowireRequiredMethodsPass extends AbstractRecursivePass
|
|||||||
|
|
||||||
return $value;
|
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\AutowireRequiredMethodsPass;
|
||||||
use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass;
|
use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\WitherStaticReturnType;
|
||||||
|
|
||||||
require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php';
|
require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php';
|
||||||
|
|
||||||
@ -99,4 +100,28 @@ class AutowireRequiredMethodsPassTest extends TestCase
|
|||||||
];
|
];
|
||||||
$this->assertSame($expected, $methodCalls);
|
$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\FooWithAbstractArgument;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\ScalarFactory;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\ScalarFactory;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\SimilarArgumentsDummy;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\SimilarArgumentsDummy;
|
||||||
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\WitherStaticReturnType;
|
||||||
use Symfony\Component\DependencyInjection\TypedReference;
|
use Symfony\Component\DependencyInjection\TypedReference;
|
||||||
use Symfony\Component\ExpressionLanguage\Expression;
|
use Symfony\Component\ExpressionLanguage\Expression;
|
||||||
|
|
||||||
@ -1624,6 +1625,25 @@ class ContainerBuilderTest extends TestCase
|
|||||||
$this->assertInstanceOf(Foo::class, $wither->foo);
|
$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()
|
public function testAutoAliasing()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$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\StubbedTranslator;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestDefinition1;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestDefinition1;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber;
|
||||||
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\WitherStaticReturnType;
|
||||||
use Symfony\Component\DependencyInjection\TypedReference;
|
use Symfony\Component\DependencyInjection\TypedReference;
|
||||||
use Symfony\Component\DependencyInjection\Variable;
|
use Symfony\Component\DependencyInjection\Variable;
|
||||||
use Symfony\Component\ExpressionLanguage\Expression;
|
use Symfony\Component\ExpressionLanguage\Expression;
|
||||||
@ -1362,6 +1363,31 @@ class PhpDumperTest extends TestCase
|
|||||||
$this->assertInstanceOf(Foo::class, $wither->foo);
|
$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
|
* @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