Skip to content

Commit 94589a6

Browse files
mtarldKorbeil
andcommitted
[TypeInfo] Introduce component
Co-authored-by: Baptiste Leduc <baptiste.leduc@gmail.com>
1 parent 19f5240 commit 94589a6

File tree

82 files changed

+3870
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+3870
-0
lines changed

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
"symfony/translation": "self.version",
110110
"symfony/twig-bridge": "self.version",
111111
"symfony/twig-bundle": "self.version",
112+
"symfony/type-info": "self.version",
112113
"symfony/uid": "self.version",
113114
"symfony/validator": "self.version",
114115
"symfony/var-dumper": "self.version",

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.1
5+
---
6+
7+
* Register TypeInfo services
8+
49
7.0
510
---
611

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class UnusedTagsPass implements CompilerPassInterface
6969
'mime.mime_type_guesser',
7070
'monolog.logger',
7171
'notifier.channel',
72+
'type_info.resolver',
7273
'property_info.access_extractor',
7374
'property_info.initializable_extractor',
7475
'property_info.list_extractor',

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

+14
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
use Symfony\Component\Serializer\Encoder\JsonDecode;
4444
use Symfony\Component\Serializer\Serializer;
4545
use Symfony\Component\Translation\Translator;
46+
use Symfony\Component\TypeInfo\Type;
4647
use Symfony\Component\Uid\Factory\UuidFactory;
4748
use Symfony\Component\Validator\Validation;
4849
use Symfony\Component\Webhook\Controller\WebhookController;
@@ -158,6 +159,7 @@ public function getConfigTreeBuilder(): TreeBuilder
158159
$this->addAnnotationsSection($rootNode);
159160
$this->addSerializerSection($rootNode, $enableIfStandalone);
160161
$this->addPropertyAccessSection($rootNode, $willBeAvailable);
162+
$this->addTypeInfoSection($rootNode, $enableIfStandalone);
161163
$this->addPropertyInfoSection($rootNode, $enableIfStandalone);
162164
$this->addCacheSection($rootNode, $willBeAvailable);
163165
$this->addPhpErrorsSection($rootNode);
@@ -1148,6 +1150,18 @@ private function addPropertyInfoSection(ArrayNodeDefinition $rootNode, callable
11481150
;
11491151
}
11501152

1153+
private function addTypeInfoSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
1154+
{
1155+
$rootNode
1156+
->children()
1157+
->arrayNode('type_info')
1158+
->info('Type info configuration')
1159+
->{$enableIfStandalone('symfony/type-info', Type::class)}()
1160+
->end()
1161+
->end()
1162+
;
1163+
}
1164+
11511165
private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable): void
11521166
{
11531167
$rootNode

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

+20
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@
167167
use Symfony\Component\Translation\LocaleSwitcher;
168168
use Symfony\Component\Translation\PseudoLocalizationTranslator;
169169
use Symfony\Component\Translation\Translator;
170+
use Symfony\Component\TypeInfo\Type;
171+
use Symfony\Component\TypeInfo\TypeResolver\StringTypeResolver;
170172
use Symfony\Component\Uid\Factory\UuidFactory;
171173
use Symfony\Component\Uid\UuidV4;
172174
use Symfony\Component\Validator\Constraints\ExpressionLanguageProvider;
@@ -388,6 +390,10 @@ public function load(array $configs, ContainerBuilder $container): void
388390
$container->removeDefinition('console.command.serializer_debug');
389391
}
390392

393+
if ($this->readConfigEnabled('type_info', $container, $config['type_info'])) {
394+
$this->registerTypeInfoConfiguration($container, $loader);
395+
}
396+
391397
if ($propertyInfoEnabled) {
392398
$this->registerPropertyInfoConfiguration($container, $loader);
393399
}
@@ -1950,6 +1956,20 @@ private function registerPropertyInfoConfiguration(ContainerBuilder $container,
19501956
}
19511957
}
19521958

1959+
private function registerTypeInfoConfiguration(ContainerBuilder $container, PhpFileLoader $loader): void
1960+
{
1961+
if (!class_exists(Type::class)) {
1962+
throw new LogicException('TypeInfo support cannot be enabled as the TypeInfo component is not installed. Try running "composer require symfony/type-info".');
1963+
}
1964+
1965+
$loader->load('type_info.php');
1966+
1967+
if (ContainerBuilder::willBeAvailable('phpstan/phpdoc-parser', PhpDocParser::class, ['symfony/framework-bundle', 'symfony/type-info'])) {
1968+
$container->register('type_info.resolver.string', StringTypeResolver::class)
1969+
->addTag('type_info.resolver', ['priority' => -1000]);
1970+
}
1971+
}
1972+
19531973
private function registerLockConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
19541974
{
19551975
$loader->load('lock.php');

src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php

+2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass;
6565
use Symfony\Component\Translation\DependencyInjection\TranslatorPass;
6666
use Symfony\Component\Translation\DependencyInjection\TranslatorPathsPass;
67+
use Symfony\Component\TypeInfo\DependencyInjection\TypeInfoPass;
6768
use Symfony\Component\Validator\DependencyInjection\AddAutoMappingConfigurationPass;
6869
use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass;
6970
use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass;
@@ -150,6 +151,7 @@ public function build(ContainerBuilder $container): void
150151
$this->addCompilerPassIfExists($container, TranslationDumperPass::class);
151152
$container->addCompilerPass(new FragmentRendererPass());
152153
$this->addCompilerPassIfExists($container, SerializerPass::class);
154+
$this->addCompilerPassIfExists($container, TypeInfoPass::class);
153155
$this->addCompilerPassIfExists($container, PropertyInfoPass::class);
154156
$container->addCompilerPass(new ControllerArgumentValueResolverPass());
155157
$container->addCompilerPass(new CachePoolPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 32);

src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

+5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
<xsd:element name="property-access" type="property_access" minOccurs="0" maxOccurs="1" />
2828
<xsd:element name="scheduler" type="scheduler" minOccurs="0" maxOccurs="1" />
2929
<xsd:element name="serializer" type="serializer" minOccurs="0" maxOccurs="1" />
30+
<xsd:element name="type-info" type="type_info" minOccurs="0" maxOccurs="1" />
3031
<xsd:element name="property-info" type="property_info" minOccurs="0" maxOccurs="1" />
3132
<xsd:element name="cache" type="cache" minOccurs="0" maxOccurs="1" />
3233
<xsd:element name="workflow" type="workflow" minOccurs="0" maxOccurs="unbounded" />
@@ -326,6 +327,10 @@
326327
<xsd:attribute name="max-depth-handler" type="xsd:string" />
327328
</xsd:complexType>
328329

330+
<xsd:complexType name="type_info">
331+
<xsd:attribute name="enabled" type="xsd:boolean" />
332+
</xsd:complexType>
333+
329334
<xsd:complexType name="property_info">
330335
<xsd:attribute name="enabled" type="xsd:boolean" />
331336
</xsd:complexType>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
13+
14+
use Symfony\Component\TypeInfo\TypeContext\TypeContextFactory;
15+
use Symfony\Component\TypeInfo\TypeResolver\ChainTypeResolver;
16+
use Symfony\Component\TypeInfo\TypeResolver\ReflectionParameterTypeResolver;
17+
use Symfony\Component\TypeInfo\TypeResolver\ReflectionPropertyTypeResolver;
18+
use Symfony\Component\TypeInfo\TypeResolver\ReflectionReturnTypeResolver;
19+
use Symfony\Component\TypeInfo\TypeResolver\ReflectionTypeResolver;
20+
use Symfony\Component\TypeInfo\TypeResolver\TypeResolverInterface;
21+
22+
return static function (ContainerConfigurator $container) {
23+
$container->services()
24+
// type context
25+
->set('type_info.type_context_factory', TypeContextFactory::class)
26+
->args([service('type_info.resolver.string')->nullOnInvalid()])
27+
28+
// type resolvers
29+
->set('type_info.resolver', ChainTypeResolver::class)
30+
->args([abstract_arg('type resolvers')])
31+
->alias(TypeResolverInterface::class, 'type_info.resolver')
32+
33+
->set('type_info.resolver.reflection_type', ReflectionTypeResolver::class)
34+
->args([service('type_info.type_context_factory')])
35+
->tag('type_info.resolver', ['priority' => -1001])
36+
37+
->set('type_info.resolver.reflection_parameter', ReflectionParameterTypeResolver::class)
38+
->args([service('type_info.resolver.reflection_type'), service('type_info.type_context_factory')])
39+
->tag('type_info.resolver', ['priority' => -1002])
40+
41+
->set('type_info.resolver.reflection_property', ReflectionPropertyTypeResolver::class)
42+
->args([service('type_info.resolver.reflection_type'), service('type_info.type_context_factory')])
43+
->tag('type_info.resolver', ['priority' => -1003])
44+
45+
->set('type_info.resolver.reflection_return', ReflectionReturnTypeResolver::class)
46+
->args([service('type_info.resolver.reflection_type'), service('type_info.type_context_factory')])
47+
->tag('type_info.resolver', ['priority' => -1004])
48+
;
49+
};

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
use Symfony\Component\RateLimiter\Policy\TokenBucketLimiter;
2929
use Symfony\Component\Scheduler\Messenger\SchedulerTransportFactory;
3030
use Symfony\Component\Serializer\Encoder\JsonDecode;
31+
use Symfony\Component\TypeInfo\Type;
3132
use Symfony\Component\Uid\Factory\UuidFactory;
3233

3334
class ConfigurationTest extends TestCase
@@ -623,6 +624,9 @@ protected static function getBundleDefaultConfig()
623624
'throw_exception_on_invalid_index' => false,
624625
'throw_exception_on_invalid_property_path' => true,
625626
],
627+
'type_info' => [
628+
'enabled' => !class_exists(FullStack::class) && class_exists(Type::class),
629+
],
626630
'property_info' => [
627631
'enabled' => !class_exists(FullStack::class),
628632
],

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
'default_context' => ['enable_max_depth' => true],
7171
],
7272
'property_info' => true,
73+
'type_info' => true,
7374
'ide' => 'file%%link%%format',
7475
'request' => [
7576
'formats' => [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
$container->loadFromExtension('framework', [
4+
'annotations' => false,
5+
'http_method_override' => false,
6+
'handle_all_throwables' => true,
7+
'php_errors' => ['log' => true],
8+
'type_info' => [
9+
'enabled' => true,
10+
],
11+
]);

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml

+1
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,6 @@
4040
</framework:default-context>
4141
</framework:serializer>
4242
<framework:property-info />
43+
<framework:type-info />
4344
</framework:config>
4445
</container>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<container xmlns="http://symfony.com/schema/dic/services"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:framework="http://symfony.com/schema/dic/symfony"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
6+
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
7+
8+
<framework:config http-method-override="false" handle-all-throwables="true">
9+
<framework:annotations enabled="false" />
10+
<framework:php-errors log="true" />
11+
<framework:type-info enabled="true" />
12+
</framework:config>
13+
</container>

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ framework:
5959
max_depth_handler: my.max.depth.handler
6060
default_context:
6161
enable_max_depth: true
62+
type_info: ~
6263
property_info: ~
6364
ide: file%%link%%format
6465
request:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
framework:
2+
annotations: false
3+
http_method_override: false
4+
handle_all_throwables: true
5+
php_errors:
6+
log: true
7+
type_info:
8+
enabled: true

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php

+6
Original file line numberDiff line numberDiff line change
@@ -1608,6 +1608,12 @@ public function testSerializerServiceIsNotRegisteredWhenDisabled()
16081608
$this->assertFalse($container->hasDefinition('serializer'));
16091609
}
16101610

1611+
public function testTypeInfoEnabled()
1612+
{
1613+
$container = $this->createContainerFromFile('type_info');
1614+
$this->assertTrue($container->has('type_info.resolver'));
1615+
}
1616+
16111617
public function testPropertyInfoEnabled()
16121618
{
16131619
$container = $this->createContainerFromFile('property_info');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
13+
14+
use Symfony\Component\TypeInfo\Type;
15+
16+
class TypeInfoTest extends AbstractWebTestCase
17+
{
18+
public function testComponent()
19+
{
20+
static::bootKernel(['test_case' => 'TypeInfo']);
21+
22+
$this->assertEquals(Type::union(Type::int(), Type::null()), static::getContainer()->get('type_info.resolver')->resolve('int|null'));
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
13+
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle;
14+
15+
return [
16+
new FrameworkBundle(),
17+
new TestBundle(),
18+
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
imports:
2+
- { resource: ../config/default.yml }
3+
4+
framework:
5+
http_method_override: false
6+
type_info: true
7+
8+
services:
9+
type_info.resolver.alias:
10+
alias: type_info.resolver
11+
public: true

src/Symfony/Bundle/FrameworkBundle/composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"symfony/string": "^6.4|^7.0",
6565
"symfony/translation": "^6.4|^7.0",
6666
"symfony/twig-bundle": "^6.4|^7.0",
67+
"symfony/type-info": "^7.1",
6768
"symfony/validator": "^6.4|^7.0",
6869
"symfony/workflow": "^6.4|^7.0",
6970
"symfony/yaml": "^6.4|^7.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/Tests export-ignore
2+
/phpunit.xml.dist export-ignore
3+
/.gitattributes export-ignore
4+
/.gitignore export-ignore
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vendor/
2+
composer.lock
3+
phpunit.xml
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\TypeInfo;
13+
14+
/**
15+
* List all native PHP types.
16+
*
17+
* @author Mathias Arlaud <mathias.arlaud@gmail.com>
18+
* @author Baptiste Leduc <baptiste.leduc@gmail.com>
19+
*/
20+
enum BuiltinType: string
21+
{
22+
case ARRAY = 'array';
23+
case BOOL = 'bool';
24+
case CALLABLE = 'callable';
25+
case FALSE = 'false';
26+
case FLOAT = 'float';
27+
case INT = 'int';
28+
case ITERABLE = 'iterable';
29+
case MIXED = 'mixed';
30+
case NULL = 'null';
31+
case OBJECT = 'object';
32+
case RESOURCE = 'resource';
33+
case STRING = 'string';
34+
case TRUE = 'true';
35+
case NEVER = 'never';
36+
case VOID = 'void';
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CHANGELOG
2+
=========
3+
4+
7.1
5+
---
6+
7+
* Add the component

0 commit comments

Comments
 (0)