Skip to content

[TypeInfo] Introduce component #52510

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"symfony/translation": "self.version",
"symfony/twig-bridge": "self.version",
"symfony/twig-bundle": "self.version",
"symfony/type-info": "self.version",
"symfony/uid": "self.version",
"symfony/validator": "self.version",
"symfony/var-dumper": "self.version",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
use Symfony\Component\Serializer\Encoder\JsonDecode;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Translation\Translator;
use Symfony\Component\TypeInfo\Type;
use Symfony\Component\Uid\Factory\UuidFactory;
use Symfony\Component\Validator\Validation;
use Symfony\Component\Webhook\Controller\WebhookController;
Expand Down Expand Up @@ -164,6 +165,7 @@ public function getConfigTreeBuilder(): TreeBuilder
$this->addAnnotationsSection($rootNode);
$this->addSerializerSection($rootNode, $enableIfStandalone);
$this->addPropertyAccessSection($rootNode, $willBeAvailable);
$this->addTypeInfoSection($rootNode, $enableIfStandalone);
$this->addPropertyInfoSection($rootNode, $enableIfStandalone);
$this->addCacheSection($rootNode, $willBeAvailable);
$this->addPhpErrorsSection($rootNode);
Expand Down Expand Up @@ -1162,6 +1164,18 @@ private function addPropertyInfoSection(ArrayNodeDefinition $rootNode, callable
;
}

private function addTypeInfoSection(ArrayNodeDefinition $rootNode, callable $enableIfStandalone): void
{
$rootNode
->children()
->arrayNode('type_info')
->info('Type info configuration')
->{$enableIfStandalone('symfony/type-info', Type::class)}()
->end()
->end()
;
}

private function addCacheSection(ArrayNodeDefinition $rootNode, callable $willBeAvailable): void
{
$rootNode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
use Symfony\Component\Console\Debug\CliRequest;
use Symfony\Component\Console\Messenger\RunCommandMessageHandler;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
Expand Down Expand Up @@ -167,6 +168,8 @@
use Symfony\Component\Translation\LocaleSwitcher;
use Symfony\Component\Translation\PseudoLocalizationTranslator;
use Symfony\Component\Translation\Translator;
use Symfony\Component\TypeInfo\Type;
use Symfony\Component\TypeInfo\TypeResolver\StringTypeResolver;
use Symfony\Component\Uid\Factory\UuidFactory;
use Symfony\Component\Uid\UuidV4;
use Symfony\Component\Validator\Constraints\ExpressionLanguageProvider;
Expand Down Expand Up @@ -388,6 +391,10 @@ public function load(array $configs, ContainerBuilder $container): void
$container->removeDefinition('console.command.serializer_debug');
}

if ($this->readConfigEnabled('type_info', $container, $config['type_info'])) {
$this->registerTypeInfoConfiguration($container, $loader);
}

if ($propertyInfoEnabled) {
$this->registerPropertyInfoConfiguration($container, $loader);
}
Expand Down Expand Up @@ -1953,6 +1960,25 @@ private function registerPropertyInfoConfiguration(ContainerBuilder $container,
}
}

private function registerTypeInfoConfiguration(ContainerBuilder $container, PhpFileLoader $loader): void
{
if (!class_exists(Type::class)) {
throw new LogicException('TypeInfo support cannot be enabled as the TypeInfo component is not installed. Try running "composer require symfony/type-info".');
}

$loader->load('type_info.php');

if (ContainerBuilder::willBeAvailable('phpstan/phpdoc-parser', PhpDocParser::class, ['symfony/framework-bundle', 'symfony/type-info'])) {
$container->register('type_info.resolver.string', StringTypeResolver::class);

/** @var ServiceLocatorArgument $resolversLocator */
$resolversLocator = $container->getDefinition('type_info.resolver')->getArgument(0);
$resolversLocator->setValues($resolversLocator->getValues() + [
'string' => new Reference('type_info.resolver.string'),
]);
}
}

private function registerLockConfiguration(array $config, ContainerBuilder $container, PhpFileLoader $loader): void
{
$loader->load('lock.php');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<xsd:element name="property-access" type="property_access" minOccurs="0" maxOccurs="1" />
<xsd:element name="scheduler" type="scheduler" minOccurs="0" maxOccurs="1" />
<xsd:element name="serializer" type="serializer" minOccurs="0" maxOccurs="1" />
<xsd:element name="type-info" type="type_info" minOccurs="0" maxOccurs="1" />
<xsd:element name="property-info" type="property_info" minOccurs="0" maxOccurs="1" />
<xsd:element name="cache" type="cache" minOccurs="0" maxOccurs="1" />
<xsd:element name="workflow" type="workflow" minOccurs="0" maxOccurs="unbounded" />
Expand Down Expand Up @@ -327,6 +328,10 @@
<xsd:attribute name="max-depth-handler" type="xsd:string" />
</xsd:complexType>

<xsd:complexType name="type_info">
<xsd:attribute name="enabled" type="xsd:boolean" />
</xsd:complexType>

<xsd:complexType name="property_info">
<xsd:attribute name="enabled" type="xsd:boolean" />
</xsd:complexType>
Expand Down
50 changes: 50 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/Resources/config/type_info.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use Symfony\Component\TypeInfo\TypeContext\TypeContextFactory;
use Symfony\Component\TypeInfo\TypeResolver\ReflectionParameterTypeResolver;
use Symfony\Component\TypeInfo\TypeResolver\ReflectionPropertyTypeResolver;
use Symfony\Component\TypeInfo\TypeResolver\ReflectionReturnTypeResolver;
use Symfony\Component\TypeInfo\TypeResolver\ReflectionTypeResolver;
use Symfony\Component\TypeInfo\TypeResolver\TypeResolver;
use Symfony\Component\TypeInfo\TypeResolver\TypeResolverInterface;

return static function (ContainerConfigurator $container) {
$container->services()
// type context
->set('type_info.type_context_factory', TypeContextFactory::class)
->args([service('type_info.resolver.string')->nullOnInvalid()])

// type resolvers
->set('type_info.resolver', TypeResolver::class)
->args([service_locator([
\ReflectionType::class => service('type_info.resolver.reflection_type'),
\ReflectionParameter::class => service('type_info.resolver.reflection_parameter'),
\ReflectionProperty::class => service('type_info.resolver.reflection_property'),
\ReflectionFunctionAbstract::class => service('type_info.resolver.reflection_return'),
])])
->alias(TypeResolverInterface::class, 'type_info.resolver')

->set('type_info.resolver.reflection_type', ReflectionTypeResolver::class)
->args([service('type_info.type_context_factory')])

->set('type_info.resolver.reflection_parameter', ReflectionParameterTypeResolver::class)
->args([service('type_info.resolver.reflection_type'), service('type_info.type_context_factory')])

->set('type_info.resolver.reflection_property', ReflectionPropertyTypeResolver::class)
->args([service('type_info.resolver.reflection_type'), service('type_info.type_context_factory')])

->set('type_info.resolver.reflection_return', ReflectionReturnTypeResolver::class)
->args([service('type_info.resolver.reflection_type'), service('type_info.type_context_factory')])
;
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Symfony\Component\RateLimiter\Policy\TokenBucketLimiter;
use Symfony\Component\Scheduler\Messenger\SchedulerTransportFactory;
use Symfony\Component\Serializer\Encoder\JsonDecode;
use Symfony\Component\TypeInfo\Type;
use Symfony\Component\Uid\Factory\UuidFactory;

class ConfigurationTest extends TestCase
Expand Down Expand Up @@ -624,6 +625,9 @@ protected static function getBundleDefaultConfig()
'throw_exception_on_invalid_index' => false,
'throw_exception_on_invalid_property_path' => true,
],
'type_info' => [
'enabled' => !class_exists(FullStack::class) && class_exists(Type::class),
],
'property_info' => [
'enabled' => !class_exists(FullStack::class),
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
'default_context' => ['enable_max_depth' => true],
],
'property_info' => true,
'type_info' => true,
'ide' => 'file%%link%%format',
'request' => [
'formats' => [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

$container->loadFromExtension('framework', [
'annotations' => false,
'http_method_override' => false,
'handle_all_throwables' => true,
'php_errors' => ['log' => true],
'type_info' => [
'enabled' => true,
],
]);
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,6 @@
</framework:default-context>
</framework:serializer>
<framework:property-info />
<framework:type-info />
</framework:config>
</container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">

<framework:config http-method-override="false" handle-all-throwables="true">
<framework:annotations enabled="false" />
<framework:php-errors log="true" />
<framework:type-info enabled="true" />
</framework:config>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ framework:
max_depth_handler: my.max.depth.handler
default_context:
enable_max_depth: true
type_info: ~
property_info: ~
ide: file%%link%%format
request:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
framework:
annotations: false
http_method_override: false
handle_all_throwables: true
php_errors:
log: true
type_info:
enabled: true
Original file line number Diff line number Diff line change
Expand Up @@ -1616,6 +1616,12 @@ public function testSerializerServiceIsNotRegisteredWhenDisabled()
$this->assertFalse($container->hasDefinition('serializer'));
}

public function testTypeInfoEnabled()
{
$container = $this->createContainerFromFile('type_info');
$this->assertTrue($container->has('type_info.resolver'));
}

public function testPropertyInfoEnabled()
{
$container = $this->createContainerFromFile('property_info');
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;

use PHPStan\PhpDocParser\Parser\PhpDocParser;
use Symfony\Bundle\FrameworkBundle\Tests\Functional\app\TypeInfo\Dummy;
use Symfony\Component\TypeInfo\Type;

class TypeInfoTest extends AbstractWebTestCase
{
public function testComponent()
{
static::bootKernel(['test_case' => 'TypeInfo']);

$this->assertEquals(Type::string(), static::getContainer()->get('type_info.resolver')->resolve(new \ReflectionProperty(Dummy::class, 'name')));

if (!class_exists(PhpDocParser::class)) {
$this->markTestSkipped('"phpstan/phpdoc-parser" dependency is required.');
}

$this->assertEquals(Type::int(), static::getContainer()->get('type_info.resolver')->resolve('int'));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\app\TypeInfo;

/**
* @author Mathias Arlaud <mathias.arlaud@gmail.com>
* @author Baptiste Leduc <baptiste.leduc@gmail.com>
*/
class Dummy
{
public string $name;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle;

return [
new FrameworkBundle(),
new TestBundle(),
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
imports:
- { resource: ../config/default.yml }

framework:
http_method_override: false
type_info: true

services:
type_info.resolver.alias:
alias: type_info.resolver
public: true
1 change: 1 addition & 0 deletions src/Symfony/Bundle/FrameworkBundle/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"symfony/string": "^6.4|^7.0",
"symfony/translation": "^6.4|^7.0",
"symfony/twig-bundle": "^6.4|^7.0",
"symfony/type-info": "^7.1",
"symfony/validator": "^6.4|^7.0",
"symfony/workflow": "^6.4|^7.0",
"symfony/yaml": "^6.4|^7.0",
Expand Down
4 changes: 4 additions & 0 deletions src/Symfony/Component/TypeInfo/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/Tests export-ignore
/phpunit.xml.dist export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
3 changes: 3 additions & 0 deletions src/Symfony/Component/TypeInfo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
vendor/
composer.lock
phpunit.xml
7 changes: 7 additions & 0 deletions src/Symfony/Component/TypeInfo/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CHANGELOG
=========

7.1
---

* Add the component
20 changes: 20 additions & 0 deletions src/Symfony/Component/TypeInfo/Exception/ExceptionInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\TypeInfo\Exception;

/**
* @author Mathias Arlaud <mathias.arlaud@gmail.com>
* @author Baptiste Leduc <baptiste.leduc@gmail.com>
*/
interface ExceptionInterface extends \Throwable
{
}
Loading