Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c439a58

Browse filesBrowse files
committed
bug #59012 [PropertyInfo] Fix interface handling in PhpStanTypeHelper (janedbal)
This PR was squashed before being merged into the 6.4 branch. Discussion ---------- [PropertyInfo] Fix interface handling in `PhpStanTypeHelper` | Q | A | ------------- | --- | Branch? | 7.1 | Bug fix? | yes | New feature? | no | Deprecations? | no | License | MIT Previously, deserializing object with `Interface<T>` property was failing on undefined array key in `PhpStanTypeHelper` (generic `Clazz<T>` works just fine): ``` ErrorException: Undefined array key 0 /app/backend/vendor/symfony/property-info/Util/PhpStanTypeHelper.php:171 /app/backend/vendor/symfony/property-info/Util/PhpStanTypeHelper.php:49 /app/backend/vendor/symfony/property-info/Extractor/PhpStanExtractor.php:130 /app/backend/vendor/symfony/property-info/PropertyInfoExtractor.php:93 /app/backend/vendor/symfony/property-info/PropertyInfoExtractor.php:66 /app/backend/vendor/symfony/property-info/PropertyInfoCacheExtractor.php:102 /app/backend/vendor/symfony/property-info/PropertyInfoCacheExtractor.php:69 /app/backend/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:669 /app/backend/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:646 /app/backend/vendor/symfony/serializer/Normalizer/AbstractNormalizer.php:386 /app/backend/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:243 /app/backend/vendor/symfony/serializer/Normalizer/AbstractObjectNormalizer.php:349 /app/backend/vendor/symfony/serializer/Serializer.php:247 /app/backend/vendor/symfony/serializer/Serializer.php:152 ``` Commits ------- 88e7a72 [PropertyInfo] Fix interface handling in `PhpStanTypeHelper`
2 parents 33a5a3e + 88e7a72 commit c439a58
Copy full SHA for c439a58

File tree

3 files changed

+127
-2
lines changed
Filter options

3 files changed

+127
-2
lines changed

‎src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php
+85-1Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
1616
use Symfony\Component\PropertyInfo\Extractor\PhpStanExtractor;
17+
use Symfony\Component\PropertyInfo\Tests\Fixtures\Clazz;
1718
use Symfony\Component\PropertyInfo\Tests\Fixtures\ConstructorDummyWithoutDocBlock;
1819
use Symfony\Component\PropertyInfo\Tests\Fixtures\DefaultValue;
1920
use Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy;
2021
use Symfony\Component\PropertyInfo\Tests\Fixtures\DummyCollection;
22+
use Symfony\Component\PropertyInfo\Tests\Fixtures\DummyGeneric;
23+
use Symfony\Component\PropertyInfo\Tests\Fixtures\IFace;
2124
use Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy;
2225
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php80Dummy;
2326
use Symfony\Component\PropertyInfo\Tests\Fixtures\Php80PromotedDummy;
@@ -482,7 +485,88 @@ public static function php80TypesProvider()
482485

483486
public function testGenericInterface()
484487
{
485-
$this->assertNull($this->extractor->getTypes(Dummy::class, 'genericInterface'));
488+
$this->assertEquals(
489+
[
490+
new Type(
491+
builtinType: Type::BUILTIN_TYPE_OBJECT,
492+
class: \BackedEnum::class,
493+
collectionValueType: new Type(
494+
builtinType: Type::BUILTIN_TYPE_STRING,
495+
)
496+
),
497+
],
498+
$this->extractor->getTypes(Dummy::class, 'genericInterface')
499+
);
500+
}
501+
502+
/**
503+
* @param list<Type> $expectedTypes
504+
* @dataProvider genericsProvider
505+
*/
506+
public function testGenericsLegacy(string $property, array $expectedTypes)
507+
{
508+
$this->assertEquals($expectedTypes, $this->extractor->getTypes(DummyGeneric::class, $property));
509+
}
510+
511+
/**
512+
* @return iterable<array{0: string, 1: list<Type>}>
513+
*/
514+
public static function genericsProvider(): iterable
515+
{
516+
yield [
517+
'basicClass',
518+
[
519+
new Type(
520+
builtinType: Type::BUILTIN_TYPE_OBJECT,
521+
class: Clazz::class,
522+
collectionValueType: new Type(
523+
builtinType: Type::BUILTIN_TYPE_OBJECT,
524+
class: Dummy::class,
525+
)
526+
),
527+
],
528+
];
529+
yield [
530+
'nullableClass',
531+
[
532+
new Type(
533+
builtinType: Type::BUILTIN_TYPE_OBJECT,
534+
class: Clazz::class,
535+
nullable: true,
536+
collectionValueType: new Type(
537+
builtinType: Type::BUILTIN_TYPE_OBJECT,
538+
class: Dummy::class,
539+
)
540+
),
541+
],
542+
];
543+
yield [
544+
'basicInterface',
545+
[
546+
new Type(
547+
builtinType: Type::BUILTIN_TYPE_OBJECT,
548+
class: IFace::class,
549+
collectionValueType: new Type(
550+
builtinType: Type::BUILTIN_TYPE_OBJECT,
551+
class: Dummy::class,
552+
)
553+
),
554+
],
555+
];
556+
yield [
557+
'nullableInterface',
558+
[
559+
new Type(
560+
builtinType: Type::BUILTIN_TYPE_OBJECT,
561+
class: IFace::class,
562+
nullable: true,
563+
collectionValueType: new Type(
564+
builtinType: Type::BUILTIN_TYPE_OBJECT,
565+
class: Dummy::class,
566+
)
567+
),
568+
],
569+
];
486570
}
487571
}
488572

+41Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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\PropertyInfo\Tests\Fixtures;
13+
14+
interface IFace {}
15+
16+
class Clazz {}
17+
18+
class DummyGeneric
19+
{
20+
21+
/**
22+
* @var Clazz<Dummy>
23+
*/
24+
public $basicClass;
25+
26+
/**
27+
* @var ?Clazz<Dummy>
28+
*/
29+
public $nullableClass;
30+
31+
/**
32+
* @var IFace<Dummy>
33+
*/
34+
public $basicInterface;
35+
36+
/**
37+
* @var ?IFace<Dummy>
38+
*/
39+
public $nullableInterface;
40+
41+
}

‎src/Symfony/Component/PropertyInfo/Util/PhpStanTypeHelper.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Util/PhpStanTypeHelper.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ private function extractTypes(TypeNode $node, NameScope $nameScope): array
128128
$collection = $mainType->isCollection() || \is_a($mainType->getClassName(), \Traversable::class, true) || \is_a($mainType->getClassName(), \ArrayAccess::class, true);
129129

130130
// it's safer to fall back to other extractors if the generic type is too abstract
131-
if (!$collection && !class_exists($mainType->getClassName())) {
131+
if (!$collection && !class_exists($mainType->getClassName()) && !interface_exists($mainType->getClassName(), false)) {
132132
return [];
133133
}
134134

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.