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 eaac5c8

Browse filesBrowse files
committed
[PropertyAccessor] Fix unexpected collection when generics
1 parent dcbfcb4 commit eaac5c8
Copy full SHA for eaac5c8

File tree

8 files changed

+39
-7
lines changed
Filter options

8 files changed

+39
-7
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php
+5Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpStanExtractorTest.php
+6-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
+3Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php
+5Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Tests/Fixtures/DummyUnionType.php
+1-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php
+10-3Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/PropertyInfo/Util/PhpStanTypeHelper.php
+8-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Serializer/Tests/DeserializeNestedArrayOfObjectsTest.php
+1-1Lines 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)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.