8000 [PropertyAccessor] Fix unexpected collection when generics · symfony/symfony@487b24c · GitHub
[go: up one dir, main page]

Skip to content

Commit 487b24c

Browse files
committed
[PropertyAccessor] Fix unexpected collection when generics
1 parent 218313e commit 487b24c

File tree

8 files changed

+39
-7
lines changed
  • Util
  • Serializer/Tests
  • 8 files changed

    +39
    -7
    lines changed

    src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php

    Lines changed: 5 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -419,6 +419,11 @@ public function testUnknownPseudoType()
    419419
    $this->assertEquals([new Type(Type::BUILTIN_TYPE_OBJECT, false, 'scalar')], $this->extractor->getTypes(PseudoTypeDummy::class, 'unknownPseudoType'));
    420420
    }
    421421

    422+
    public function testGenericInterface()
    423+
    {
    424+
    $this->assertNull($this->extractor->getTypes(Dummy::class, 'genericInterface'));
    425+
    }
    426+
    422427
    protected static function isPhpDocumentorV5()
    423428
    {
    424429
    if (class_exists(InvalidTag::class)) {

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

    Lines changed: 6 additions & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -388,7 +388,7 @@ public static function unionTypesProvider(): array
    388388
    ['b', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]],
    389389
    ['c', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]],
    390390
    ['d', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING)])])]],
    391-
    ['e', [new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class, true, [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING)])], [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_STRING, false, null, true, [], [new Type(Type::BUILTIN_TYPE_OBJECT, false, DefaultValue::class)])])]), new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)]],
    391+
    ['e', [new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class, false, [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING)])], [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [new Type(Type::BUILTIN_TYPE_INT)], [new Type(Type::BUILTIN_TYPE_OBJECT, false, \Traversable::class, true, [], [new Type(Type::BUILTIN_TYPE_OBJECT, false, DefaultValue::class)])])]), new Type(Type::BUILTIN_TYPE_OBJECT, false, ParentDummy::class)]],
    392392
    ['f', null],
    393393
    ['g', [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, [], [new Type(Type::BUILTIN_TYPE_STRING), new Type(Type::BUILTIN_TYPE_INT)])]],
    394394
    ];
    @@ -427,6 +427,11 @@ public static function intRangeTypeProvider(): array
    427427
    ['c', [new Type(Type::BUILTIN_TYPE_INT)]],
    428428
    ];
    429429
    }
    430+
    431+
    public function testGenericInterface()
    432+
    {
    433+
    $this->assertNull($this->extractor->getTypes(Dummy::class, 'genericInterface'));
    434+
    }
    430435
    }
    431436

    432437
    class PhpStanOmittedParamTagTypeDocBlock

    src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php

    Lines changed: 3 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -73,6 +73,7 @@ public function testGetProperties()
    7373
    'arrayOfMixed',
    7474
    'listOfStrings',
    7575
    'parentAnnotation',
    76+
    'genericInterface',
    7677
    'foo',
    7778
    'foo2',
    7879
    'foo3',
    @@ -137,6 +138,7 @@ public function testGetPropertiesWithCustomPrefixes()
    137138
    'arrayOfMixed',
    138139
    'listOfStrings',
    139140
    'parentAnnotation',
    141+
    'genericInterface',
    140142
    'foo',
    141143
    'foo2',
    142144
    'foo3',
    @@ -190,6 +192,7 @@ public function testGetPropertiesWithNoPrefixes()
    190192
    'arrayOfMixed',
    191193
    'listOfStrings',
    192194
    'parentAnnotation',
    195+
    'genericInterface',
    193196
    'foo',
    194197
    'foo2',
    195198
    'foo3',

    src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php

    Lines changed: 5 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -165,6 +165,11 @@ class Dummy extends ParentDummy
    165165
    */
    166166
    public $parentAnnotation;
    167167

    168+
    /**
    169+
    * @var \BackedEnum<string>
    170+
    */
    171+
    public $genericInterface;
    172+
    168173
    public static function getStatic()
    169174
    {
    170175
    }

    src/Symfony/Component/PropertyInfo/Tests/Fixtures/DummyUnionType.php

    Lines changed: 1 addition & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -40,7 +40,7 @@ class DummyUnionType
    4040
    public $d;
    4141

    4242
    /**
    43-
    * @var (Dummy<array<mixed, string>, (int | (string<DefaultValue>)[])> | ParentDummy | null)
    43+
    * @var (Dummy<array<mixed, string>, (int | (\Traversable<DefaultValue>)[])> | ParentDummy | null)
    4444
    */
    4545
    public $e;
    4646

    src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php

    Lines changed: 10 additions & 3 deletions
    Original file line numberDiff line numberDiff line change
    @@ -102,9 +102,9 @@ public function getTypes(DocType $varType): array
    102102
    /**
    103103
    * Creates a {@see Type} from a PHPDoc type.
    104104
    */
    105-
    private function createType(DocType $type, bool $nullable, string $docType = null): ?Type
    105+
    private function createType(DocType $type, bool $nullable): ?Type
    106106
    {
    107-
    $docType = $docType ?? (string) $type;
    107+
    $docType = (string) $type;
    108108

    109109
    if ($type instanceof Collection) {
    110110
    $fqsen = $type->getFqsen();
    @@ -115,10 +115,17 @@ private function createType(DocType $type, bool $nullable, string $docType = nul
    115115

    116116
    [$phpType, $class] = $this->getPhpTypeAndClass((string) $fqsen);
    117117

    118+
    $collection = \in_array($class, [\Traversable::class, \Iterator::class, \IteratorAggregate::class, \ArrayAccess::class, \Generator::class], true);
    119+
    120+
    // it's safer to fall back to other extractors if the generic type is too abstract
    121+
    if (!$collection && !class_exists($class)) {
    122+
    return null;
    123+
    }
    124+
    118125
    $keys = $this->getTypes($type->getKeyType());
    119126
    $values = $this->getTypes($type->getValueType());
    120127

    121-
    return new Type($phpType, $nullable, $class, true, $keys, $values);
    128+
    return new Type($phpType, $nullable, $class, $collection, $keys, $values);
    122129
    }
    123130

    124131
    // Cannot guess

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

    Lines changed: 8 additions & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -121,6 +121,13 @@ private function extractTypes(TypeNode $node, NameScope $nameScope): array
    121121
    return [$mainType];
    122122
    }
    123123

    124+
    $collection = $mainType->isCollection() || \in_array($mainType->getClassName(), [\Traversable::class, \Iterator::class, \IteratorAggregate::class, \ArrayAccess::class, \Generator::class], true);
    125+
    126+
    // it's safer to fall back to other extractors if the generic type is too abstract
    127+
    if (!$collection && !class_exists($mainType->getClassName())) {
    128+
    return [];
    129+
    }
    130+
    124131
    $collectionKeyTypes = $mainType->getCollectionKeyTypes();
    125132
    $collectionKeyValues = [];
    126133
    if (1 === \count($node->genericTypes)) {
    @@ -136,7 +143,7 @@ private function extractTypes(TypeNode $node, NameScope $nameScope): array
    136143
    }
    137144
    }
    138145

    139-
    return [new Type($mainType->getBuiltinType(), $mainType->isNullable(), $mainType->getClassName(), true, $collectionKeyTypes, $collectionKeyValues)];
    146+
    return [new Type($mainType->getBuiltinType(), $mainType->isNullable(), $mainType->getClassName(), $collection, $collectionKeyTypes, $collectionKeyValues)];
    140147
    }
    141148
    if ($node instanceof ArrayShapeNode) {
    142149
    return [new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true)];

    src/Symfony/Component/Serializer/Tests/DeserializeNestedArrayOfObjectsTest.php

    Lines changed: 1 addition & 1 deletion
    Original file line numberDiff line numberDiff line change
    @@ -156,7 +156,7 @@ class ZooWithKeyTypes
    156156
    public $animalsString = [];
    157157
    /** @var array<int|string, Animal> */
    158158
    public $animalsUnion = [];
    159-
    /** @var \stdClass<Animal> */
    159+
    /** @var \Traversable<Animal> */
    160160
    public $animalsGenerics = [];
    161161
    }
    162162

    0 commit comments

    Comments
     (0)
    0