Skip to content

Commit c369803

Browse files
committed
bug symfony#57708 [PropertyInfo] Check if property is nullable when using ReflectionExtractor (benjilebon)
This PR was squashed before being merged into the 7.1 branch. Discussion ---------- [PropertyInfo] Check if property is nullable when using `ReflectionExtractor` | Q | A | ------------- | --- | Branch? | 7.1 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | Fix symfony#57707 | License | MIT When `$type` was resolved into a `CollectionType` with an adder mutator on the given `$class`, the replaced $type ignored if the actual property was nullable or not, causing the returned Type to always report as non nullable even when given property was declared with a `null` union type or a `?` (`?array` for example) See issue for more information and an example case Commits ------- 31b68fa [PropertyInfo] Check if property is nullable when using `ReflectionExtractor`
2 parents 9846d78 + 31b68fa commit c369803

File tree

4 files changed

+14
-1
lines changed

4 files changed

+14
-1
lines changed

src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ public function getType(string $class, string $property, array $context = []): ?
202202
$type = $this->typeResolver->resolve($mutatorReflection->getParameters()[0]);
203203

204204
if (!$type instanceof CollectionType && \in_array($prefix, $this->arrayMutatorPrefixes, true)) {
205-
$type = Type::list($type);
205+
$type = $this->isNullableProperty($class, $property) ? Type::nullable(Type::list($type)) : Type::list($type);
206206
}
207207

208208
return $type;

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ public static function provideLegacyTypes()
164164
['listOfStrings', [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, false, null, true, new LegacyType(LegacyType::BUILTIN_TYPE_INT), new LegacyType(LegacyType::BUILTIN_TYPE_STRING))], null, null],
165165
['self', [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, Dummy::class)], null, null],
166166
['collectionAsObject', [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, DummyCollection::class, true, [new LegacyType(LegacyType::BUILTIN_TYPE_INT)], [new LegacyType(LegacyType::BUILTIN_TYPE_STRING)])], null, null],
167+
['nullableTypedCollection', [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, true, null, true, new LegacyType(LegacyType::BUILTIN_TYPE_INT), new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, Dummy::class))], null, null],
167168
];
168169
}
169170

@@ -548,6 +549,7 @@ public static function typeProvider(): iterable
548549
yield ['collection', Type::list(Type::object(\DateTimeImmutable::class)), null, null];
549550
yield ['nestedCollection', Type::list(Type::list(Type::string())), null, null];
550551
yield ['mixedCollection', Type::array(), null, null];
552+
yield ['nullableTypedCollection', Type::nullable(Type::list(Type::object(Dummy::class))), null, null];
551553
yield ['a', Type::int(), 'A.', null];
552554
yield ['b', Type::nullable(Type::object(ParentDummy::class)), 'B.', null];
553555
yield ['c', Type::nullable(Type::bool()), null, null];

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ public function testGetProperties()
7777
'listOfStrings',
7878
'parentAnnotation',
7979
'genericInterface',
80+
'nullableTypedCollection',
8081
'foo',
8182
'foo2',
8283
'foo3',
@@ -144,6 +145,7 @@ public function testGetPropertiesWithCustomPrefixes()
144145
'listOfStrings',
145146
'parentAnnotation',
146147
'genericInterface',
148+
'nullableTypedCollection',
147149
'foo',
148150
'foo2',
149151
'foo3',
@@ -200,6 +202,7 @@ public function testGetPropertiesWithNoPrefixes()
200202
'listOfStrings',
201203
'parentAnnotation',
202204
'genericInterface',
205+
'nullableTypedCollection',
203206
'foo',
204207
'foo2',
205208
'foo3',
@@ -867,6 +870,7 @@ public function testTypedProperties()
867870
$this->assertEquals(Type::list(Type::string()), $this->extractor->getType(Php74Dummy::class, 'stringCollection'));
868871
$this->assertEquals(Type::nullable(Type::int()), $this->extractor->getType(Php74Dummy::class, 'nullableWithDefault'));
869872
$this->assertEquals(Type::array(), $this->extractor->getType(Php74Dummy::class, 'collection'));
873+
$this->assertEquals(Type::nullable(Type::list(Type::object(Dummy::class))), $this->extractor->getType(Php74Dummy::class, 'nullableTypedCollection'));
870874
}
871875

872876
/**

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ class Dummy extends ParentDummy
177177
*/
178178
public $genericInterface;
179179

180+
/** @var Dummy[]|null */
181+
public $nullableTypedCollection = null;
182+
180183
public static function getStatic()
181184
{
182185
}
@@ -269,4 +272,8 @@ public function addDate(\DateTimeImmutable $date)
269272
public function hasElement(string $element): bool
270273
{
271274
}
275+
276+
public function addNullableTypedCollection(Dummy $dummy): void
277+
{
278+
}
272279
}

0 commit comments

Comments
 (0)