From 12f2e97647941989ccce1359517816a06aa39fd9 Mon Sep 17 00:00:00 2001 From: DerManoMann Date: Sat, 22 Feb 2025 10:07:22 +1300 Subject: [PATCH 1/4] Add `ExplicitStringType` classes to hold specific type details for `string` builtin types --- .../Tests/Extractor/PhpStanExtractorTest.php | 21 +++++----- src/Symfony/Component/TypeInfo/CHANGELOG.md | 1 + .../Tests/Type/ExplicitStringTypeTest.php | 29 ++++++++++++++ .../TypeResolver/StringTypeResolverTest.php | 27 +++++++------ .../Component/TypeInfo/Type/BuiltinType.php | 2 +- .../TypeInfo/Type/ExplicitStringType.php | 39 +++++++++++++++++++ .../Component/TypeInfo/TypeFactoryTrait.php | 6 +++ .../TypeResolver/StringTypeResolver.php | 4 +- 8 files changed, 104 insertions(+), 25 deletions(-) create mode 100644 src/Symfony/Component/TypeInfo/Tests/Type/ExplicitStringTypeTest.php create mode 100644 src/Symfony/Component/TypeInfo/Type/ExplicitStringType.php diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php index 5563af2a1bf07..ed79c91418003 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php @@ -946,23 +946,24 @@ public function testPseudoTypes(string $property, ?Type $type) */ public static function pseudoTypesProvider(): iterable { - yield ['classString', Type::string()]; + yield ['classString', Type::explicitString('class-string')]; // BC layer for type-info < 7.2 if (!interface_exists(WrappingTypeInterface::class)) { yield ['classStringGeneric', Type::generic(Type::string(), Type::object(\stdClass::class))]; } else { - yield ['classStringGeneric', Type::string()]; + yield ['classStringGeneric', Type::explicitString('class-string')]; } - yield ['htmlEscapedString', Type::string()]; - yield ['lowercaseString', Type::string()]; - yield ['nonEmptyLowercaseString', Type::string()]; - yield ['nonEmptyString', Type::string()]; - yield ['numericString', Type::string()]; - yield ['traitString', Type::string()]; - yield ['interfaceString', Type::string()]; - yield ['literalString', Type::string()]; + yield ['htmlEscapedString', Type::explicitString('html-escaped-string')]; + yield ['lowercaseString', Type::explicitString('lowercase-string')]; + yield ['nonEmptyLowercaseString', Type::explicitString('non-empty-lowercase-string')]; + yield ['nonEmptyString', Type::explicitString('non-empty-string')]; + yield ['numericString', Type::explicitString('numeric-string')]; + yield ['traitString', Type::explicitString('trait-string')]; + yield ['interfaceString', Type::explicitString('interface-string')]; + yield ['literalString', Type::explicitString('literal-string')]; + yield ['positiveInt', Type::int()]; yield ['negativeInt', Type::int()]; yield ['nonEmptyArray', Type::array()]; diff --git a/src/Symfony/Component/TypeInfo/CHANGELOG.md b/src/Symfony/Component/TypeInfo/CHANGELOG.md index 5eaf445c6b8a0..aadcb3316aacc 100644 --- a/src/Symfony/Component/TypeInfo/CHANGELOG.md +++ b/src/Symfony/Component/TypeInfo/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.3 --- + * Add `ExplicitStringType` classes to hold specific type details for `string` builtin types * Add `Type::accepts()` method * Add `TypeFactoryTrait::fromValue()` method * Deprecate constructing a `CollectionType` instance as a list that is not an array diff --git a/src/Symfony/Component/TypeInfo/Tests/Type/ExplicitStringTypeTest.php b/src/Symfony/Component/TypeInfo/Tests/Type/ExplicitStringTypeTest.php new file mode 100644 index 0000000000000..70ef77de087c0 --- /dev/null +++ b/src/Symfony/Component/TypeInfo/Tests/Type/ExplicitStringTypeTest.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\TypeInfo\Tests\Type; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\TypeInfo\Type\ExplicitStringType; + +class ExplicitStringTypeTest extends TestCase +{ + public function testToString() + { + $this->assertSame('class-string', (string) new ExplicitStringType('class-string')); + } + + public function testAccepts() + { + $this->assertFalse((new ExplicitStringType('interface-string'))->accepts(false)); + $this->assertTrue((new ExplicitStringType('interface-string'))->accepts('Foo')); + } +} diff --git a/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php b/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php index bbc1ffc93b738..bb4dde5b11414 100644 --- a/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php +++ b/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php @@ -106,18 +106,6 @@ public static function resolveDataProvider(): iterable yield [Type::float(), 'float']; yield [Type::float(), 'double']; yield [Type::string(), 'string']; - yield [Type::string(), 'class-string']; - yield [Type::string(), 'trait-string']; - yield [Type::string(), 'interface-string']; - yield [Type::string(), 'callable-string']; - yield [Type::string(), 'numeric-string']; - yield [Type::string(), 'lowercase-string']; - yield [Type::string(), 'non-empty-lowercase-string']; - yield [Type::string(), 'non-empty-string']; - yield [Type::string(), 'non-falsy-string']; - yield [Type::string(), 'truthy-string']; - yield [Type::string(), 'literal-string']; - yield [Type::string(), 'html-escaped-string']; yield [Type::resource(), 'resource']; yield [Type::object(), 'object']; yield [Type::callable(), 'callable']; @@ -146,6 +134,21 @@ public static function resolveDataProvider(): iterable yield [Type::template('T', Type::union(Type::int(), Type::string())), 'T', $typeContextFactory->createFromClassName(DummyWithTemplates::class)]; yield [Type::template('V'), 'V', $typeContextFactory->createFromReflection(new \ReflectionMethod(DummyWithTemplates::class, 'getPrice'))]; + // explicit string + yield [Type::explicitString('callable-string'), 'callable-string']; + yield [Type::explicitString('numeric-string'), 'numeric-string']; + yield [Type::explicitString('lowercase-string'), 'lowercase-string']; + yield [Type::explicitString('non-empty-lowercase-string'), 'non-empty-lowercase-string']; + yield [Type::explicitString('non-empty-string'), 'non-empty-string']; + yield [Type::explicitString('non-falsy-string'), 'non-falsy-string']; + yield [Type::explicitString('truthy-string'), 'truthy-string']; + yield [Type::explicitString('literal-string'), 'literal-string']; + yield [Type::explicitString('html-escaped-string'), 'html-escaped-string']; + + yield [Type::explicitString('class-string'), 'class-string']; + yield [Type::explicitString('trait-string'), 'trait-string']; + yield [Type::explicitString('interface-string'), 'interface-string']; + // nullable yield [Type::nullable(Type::int()), '?int']; diff --git a/src/Symfony/Component/TypeInfo/Type/BuiltinType.php b/src/Symfony/Component/TypeInfo/Type/BuiltinType.php index 71ff78b3d94ab..110196aa4a0f7 100644 --- a/src/Symfony/Component/TypeInfo/Type/BuiltinType.php +++ b/src/Symfony/Component/TypeInfo/Type/BuiltinType.php @@ -20,7 +20,7 @@ * * @template T of TypeIdentifier */ -final class BuiltinType extends Type +class BuiltinType extends Type { /** * @param T $typeIdentifier diff --git a/src/Symfony/Component/TypeInfo/Type/ExplicitStringType.php b/src/Symfony/Component/TypeInfo/Type/ExplicitStringType.php new file mode 100644 index 0000000000000..5a7b2c4824500 --- /dev/null +++ b/src/Symfony/Component/TypeInfo/Type/ExplicitStringType.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\TypeInfo\Type; + +use Symfony\Component\TypeInfo\TypeIdentifier; + +/** + * Explicit string type. + * + * @author Martin Rademacher + * + * @extends BuiltinType + */ +final class ExplicitStringType extends BuiltinType +{ + public function __construct(private string $explicitType) + { + parent::__construct(TypeIdentifier::STRING); + } + + public function getExplicitType(): string + { + return $this->explicitType; + } + + public function __toString(): string + { + return $this->explicitType; + } +} diff --git a/src/Symfony/Component/TypeInfo/TypeFactoryTrait.php b/src/Symfony/Component/TypeInfo/TypeFactoryTrait.php index df47ff7b3ddb1..bdffb2cf76716 100644 --- a/src/Symfony/Component/TypeInfo/TypeFactoryTrait.php +++ b/src/Symfony/Component/TypeInfo/TypeFactoryTrait.php @@ -15,6 +15,7 @@ use Symfony\Component\TypeInfo\Type\BuiltinType; use Symfony\Component\TypeInfo\Type\CollectionType; use Symfony\Component\TypeInfo\Type\EnumType; +use Symfony\Component\TypeInfo\Type\ExplicitStringType; use Symfony\Component\TypeInfo\Type\GenericType; use Symfony\Component\TypeInfo\Type\IntersectionType; use Symfony\Component\TypeInfo\Type\NullableType; @@ -70,6 +71,11 @@ public static function string(): BuiltinType return self::builtin(TypeIdentifier::STRING); } + public static function explicitString(string $explicitType): ExplicitStringType + { + return new ExplicitStringType($explicitType); + } + /** * @return BuiltinType */ diff --git a/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php b/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php index 5cd0819bd8b76..89272bfca2080 100644 --- a/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php +++ b/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php @@ -137,7 +137,7 @@ private function getTypeFromNode(TypeNode $node, ?TypeContext $typeContext): Typ 'false' => Type::false(), 'int', 'integer', 'positive-int', 'negative-int', 'non-positive-int', 'non-negative-int', 'non-zero-int' => Type::int(), 'float', 'double' => Type::float(), - 'string', + 'string' => Type::string(), 'class-string', 'trait-string', 'interface-string', @@ -149,7 +149,7 @@ private function getTypeFromNode(TypeNode $node, ?TypeContext $typeContext): Typ 'non-falsy-string', 'truthy-string', 'literal-string', - 'html-escaped-string' => Type::string(), + 'html-escaped-string' => Type::explicitString($node->name), 'resource' => Type::resource(), 'object' => Type::object(), 'callable' => Type::callable(), From b049ad6f95a50696323d00d6c9b6eee4391fb367 Mon Sep 17 00:00:00 2001 From: DerManoMann Date: Sat, 22 Feb 2025 16:06:04 +1300 Subject: [PATCH 2/4] Add `ClassLikeStringType` --- .../Tests/Extractor/PhpStanExtractorTest.php | 2 +- src/Symfony/Component/TypeInfo/CHANGELOG.md | 2 +- .../Tests/Fixtures/DummyInterface.php | 16 ++++++++ .../TypeInfo/Tests/Fixtures/DummyTrait.php | 16 ++++++++ .../TypeResolver/StringTypeResolverTest.php | 5 +++ .../TypeInfo/Type/ClassLikeStringType.php | 39 +++++++++++++++++++ .../TypeInfo/Type/ExplicitStringType.php | 2 +- .../Component/TypeInfo/TypeFactoryTrait.php | 6 +++ .../TypeResolver/StringTypeResolver.php | 7 ++++ 9 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyInterface.php create mode 100644 src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyTrait.php create mode 100644 src/Symfony/Component/TypeInfo/Type/ClassLikeStringType.php diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php index ed79c91418003..0157fe16ecd8a 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php @@ -952,7 +952,7 @@ public static function pseudoTypesProvider(): iterable if (!interface_exists(WrappingTypeInterface::class)) { yield ['classStringGeneric', Type::generic(Type::string(), Type::object(\stdClass::class))]; } else { - yield ['classStringGeneric', Type::explicitString('class-string')]; + yield ['classStringGeneric', Type::classLikeString('class-string', Type::object(\stdClass::class))]; } yield ['htmlEscapedString', Type::explicitString('html-escaped-string')]; diff --git a/src/Symfony/Component/TypeInfo/CHANGELOG.md b/src/Symfony/Component/TypeInfo/CHANGELOG.md index aadcb3316aacc..9d2515fa208ea 100644 --- a/src/Symfony/Component/TypeInfo/CHANGELOG.md +++ b/src/Symfony/Component/TypeInfo/CHANGELOG.md @@ -4,7 +4,7 @@ CHANGELOG 7.3 --- - * Add `ExplicitStringType` classes to hold specific type details for `string` builtin types + * Add `ExplicitStringType` and `ClassLikeStringType` classes to hold specific type details for `string` builtin types * Add `Type::accepts()` method * Add `TypeFactoryTrait::fromValue()` method * Deprecate constructing a `CollectionType` instance as a list that is not an array diff --git a/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyInterface.php b/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyInterface.php new file mode 100644 index 0000000000000..423250d097d94 --- /dev/null +++ b/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyInterface.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\TypeInfo\Tests\Fixtures; + +interface DummyInterface +{ +} diff --git a/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyTrait.php b/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyTrait.php new file mode 100644 index 0000000000000..e1ce382c10c43 --- /dev/null +++ b/src/Symfony/Component/TypeInfo/Tests/Fixtures/DummyTrait.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\TypeInfo\Tests\Fixtures; + +trait DummyTrait +{ +} diff --git a/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php b/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php index bb4dde5b11414..22f2c256f7a58 100644 --- a/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php +++ b/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php @@ -19,6 +19,8 @@ use Symfony\Component\TypeInfo\Tests\Fixtures\DummyBackedEnum; use Symfony\Component\TypeInfo\Tests\Fixtures\DummyCollection; use Symfony\Component\TypeInfo\Tests\Fixtures\DummyEnum; +use Symfony\Component\TypeInfo\Tests\Fixtures\DummyInterface; +use Symfony\Component\TypeInfo\Tests\Fixtures\DummyTrait; use Symfony\Component\TypeInfo\Tests\Fixtures\DummyWithTemplates; use Symfony\Component\TypeInfo\Tests\Fixtures\DummyWithTypeAliases; use Symfony\Component\TypeInfo\Type; @@ -146,8 +148,11 @@ public static function resolveDataProvider(): iterable yield [Type::explicitString('html-escaped-string'), 'html-escaped-string']; yield [Type::explicitString('class-string'), 'class-string']; + yield [Type::classLikeString('class-string', Type::object(Dummy::class)), sprintf('class-string<%s>', Dummy::class)]; yield [Type::explicitString('trait-string'), 'trait-string']; + yield [Type::classLikeString('trait-string', Type::object(DummyTrait::class)), sprintf('trait-string<%s>', DummyTrait::class)]; yield [Type::explicitString('interface-string'), 'interface-string']; + yield [Type::classLikeString('interface-string', Type::object(DummyInterface::class)), sprintf('interface-string<%s>', DummyInterface::class)]; // nullable yield [Type::nullable(Type::int()), '?int']; diff --git a/src/Symfony/Component/TypeInfo/Type/ClassLikeStringType.php b/src/Symfony/Component/TypeInfo/Type/ClassLikeStringType.php new file mode 100644 index 0000000000000..d8a025220c4e1 --- /dev/null +++ b/src/Symfony/Component/TypeInfo/Type/ClassLikeStringType.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\TypeInfo\Type; + +use Symfony\Component\TypeInfo\TypeIdentifier; + +/** + * Explicit string type. + * + * @author Martin Rademacher + * + * @extends BuiltinType + */ +final class ClassLikeStringType extends ExplicitStringType +{ + public function __construct(string $explicitType, private ObjectType $objectType) + { + parent::__construct($explicitType); + } + + public function getObjectType(): ObjectType + { + return $this->objectType; + } + + public function __toString(): string + { + return sprintf('%s<%s>', $this->getExplicitType(), $this->objectType); + } +} diff --git a/src/Symfony/Component/TypeInfo/Type/ExplicitStringType.php b/src/Symfony/Component/TypeInfo/Type/ExplicitStringType.php index 5a7b2c4824500..aa5afa84bf37d 100644 --- a/src/Symfony/Component/TypeInfo/Type/ExplicitStringType.php +++ b/src/Symfony/Component/TypeInfo/Type/ExplicitStringType.php @@ -20,7 +20,7 @@ * * @extends BuiltinType */ -final class ExplicitStringType extends BuiltinType +class ExplicitStringType extends BuiltinType { public function __construct(private string $explicitType) { diff --git a/src/Symfony/Component/TypeInfo/TypeFactoryTrait.php b/src/Symfony/Component/TypeInfo/TypeFactoryTrait.php index bdffb2cf76716..6dc6aeaefc0ea 100644 --- a/src/Symfony/Component/TypeInfo/TypeFactoryTrait.php +++ b/src/Symfony/Component/TypeInfo/TypeFactoryTrait.php @@ -13,6 +13,7 @@ use Symfony\Component\TypeInfo\Type\BackedEnumType; use Symfony\Component\TypeInfo\Type\BuiltinType; +use Symfony\Component\TypeInfo\Type\ClassLikeStringType; use Symfony\Component\TypeInfo\Type\CollectionType; use Symfony\Component\TypeInfo\Type\EnumType; use Symfony\Component\TypeInfo\Type\ExplicitStringType; @@ -76,6 +77,11 @@ public static function explicitString(string $explicitType): ExplicitStringType return new ExplicitStringType($explicitType); } + public static function classLikeString(string $explicitType, ObjectType $objectType): ClassLikeStringType + { + return new ClassLikeStringType($explicitType, $objectType); + } + /** * @return BuiltinType */ diff --git a/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php b/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php index 89272bfca2080..b448d1aa302b6 100644 --- a/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php +++ b/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php @@ -40,6 +40,7 @@ use Symfony\Component\TypeInfo\Type; use Symfony\Component\TypeInfo\Type\BuiltinType; use Symfony\Component\TypeInfo\Type\CollectionType; +use Symfony\Component\TypeInfo\Type\ExplicitStringType; use Symfony\Component\TypeInfo\Type\GenericType; use Symfony\Component\TypeInfo\TypeContext\TypeContext; use Symfony\Component\TypeInfo\TypeIdentifier; @@ -215,6 +216,12 @@ private function getTypeFromNode(TypeNode $node, ?TypeContext $typeContext): Typ }; } + if ($type instanceof ExplicitStringType + && in_array($type->getExplicitType(), ['class-string', 'interface-string', 'trait-string'], true) + && 1 === \count($variableTypes) && $variableTypes[0] instanceof Type\ObjectType) { + return Type::classLikeString($type->getExplicitType(), $variableTypes[0]); + } + if ($type instanceof BuiltinType && TypeIdentifier::ARRAY !== $type->getTypeIdentifier() && TypeIdentifier::ITERABLE !== $type->getTypeIdentifier()) { return $type; } From c3a12af02d9af2de7fdb02edae50fdfed6a65aaf Mon Sep 17 00:00:00 2001 From: DerManoMann Date: Sat, 22 Feb 2025 16:26:59 +1300 Subject: [PATCH 3/4] CS --- .../TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php | 6 +++--- src/Symfony/Component/TypeInfo/Type/ClassLikeStringType.php | 2 +- .../Component/TypeInfo/TypeResolver/StringTypeResolver.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php b/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php index 22f2c256f7a58..330911996fea4 100644 --- a/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php +++ b/src/Symfony/Component/TypeInfo/Tests/TypeResolver/StringTypeResolverTest.php @@ -148,11 +148,11 @@ public static function resolveDataProvider(): iterable yield [Type::explicitString('html-escaped-string'), 'html-escaped-string']; yield [Type::explicitString('class-string'), 'class-string']; - yield [Type::classLikeString('class-string', Type::object(Dummy::class)), sprintf('class-string<%s>', Dummy::class)]; + yield [Type::classLikeString('class-string', Type::object(Dummy::class)), \sprintf('class-string<%s>', Dummy::class)]; yield [Type::explicitString('trait-string'), 'trait-string']; - yield [Type::classLikeString('trait-string', Type::object(DummyTrait::class)), sprintf('trait-string<%s>', DummyTrait::class)]; + yield [Type::classLikeString('trait-string', Type::object(DummyTrait::class)), \sprintf('trait-string<%s>', DummyTrait::class)]; yield [Type::explicitString('interface-string'), 'interface-string']; - yield [Type::classLikeString('interface-string', Type::object(DummyInterface::class)), sprintf('interface-string<%s>', DummyInterface::class)]; + yield [Type::classLikeString('interface-string', Type::object(DummyInterface::class)), \sprintf('interface-string<%s>', DummyInterface::class)]; // nullable yield [Type::nullable(Type::int()), '?int']; diff --git a/src/Symfony/Component/TypeInfo/Type/ClassLikeStringType.php b/src/Symfony/Component/TypeInfo/Type/ClassLikeStringType.php index d8a025220c4e1..94bed26501794 100644 --- a/src/Symfony/Component/TypeInfo/Type/ClassLikeStringType.php +++ b/src/Symfony/Component/TypeInfo/Type/ClassLikeStringType.php @@ -34,6 +34,6 @@ public function getObjectType(): ObjectType public function __toString(): string { - return sprintf('%s<%s>', $this->getExplicitType(), $this->objectType); + return \sprintf('%s<%s>', $this->getExplicitType(), $this->objectType); } } diff --git a/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php b/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php index b448d1aa302b6..16248a1c83f1b 100644 --- a/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php +++ b/src/Symfony/Component/TypeInfo/TypeResolver/StringTypeResolver.php @@ -217,7 +217,7 @@ private function getTypeFromNode(TypeNode $node, ?TypeContext $typeContext): Typ } if ($type instanceof ExplicitStringType - && in_array($type->getExplicitType(), ['class-string', 'interface-string', 'trait-string'], true) + && \in_array($type->getExplicitType(), ['class-string', 'interface-string', 'trait-string'], true) && 1 === \count($variableTypes) && $variableTypes[0] instanceof Type\ObjectType) { return Type::classLikeString($type->getExplicitType(), $variableTypes[0]); } From 4130c170d34461e86201c5d3a1b074e7575ed77d Mon Sep 17 00:00:00 2001 From: DerManoMann Date: Sat, 22 Feb 2025 16:31:41 +1300 Subject: [PATCH 4/4] Update CHANGELOG.md --- src/Symfony/Component/TypeInfo/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/TypeInfo/CHANGELOG.md b/src/Symfony/Component/TypeInfo/CHANGELOG.md index 9d2515fa208ea..08df36ca9f6ac 100644 --- a/src/Symfony/Component/TypeInfo/CHANGELOG.md +++ b/src/Symfony/Component/TypeInfo/CHANGELOG.md @@ -4,12 +4,12 @@ CHANGELOG 7.3 --- - * Add `ExplicitStringType` and `ClassLikeStringType` classes to hold specific type details for `string` builtin types * Add `Type::accepts()` method * Add `TypeFactoryTrait::fromValue()` method * Deprecate constructing a `CollectionType` instance as a list that is not an array * Deprecate the third `$asList` argument of `TypeFactoryTrait::iterable()`, use `TypeFactoryTrait::list()` instead * Add type alias support in `TypeContext` and `StringTypeResolver` + * Add `ExplicitStringType` and `ClassLikeStringType` classes to hold specific type details for `string` builtin types 7.2 ---