Skip to content

Commit

Permalink
bug #57708 [PropertyInfo] Check if property is nullable when using `R…
Browse files Browse the repository at this point in the history
…eflectionExtractor` (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 #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
-------

31b68fad4f [PropertyInfo] Check if property is nullable when using `ReflectionExtractor`
  • Loading branch information
fabpot committed Jul 26, 2024
2 parents a87c9aa + 9ad37e2 commit 88a279d
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Extractor/ReflectionExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ public function getType(string $class, string $property, array $context = []): ?
$type = $this->typeResolver->resolve($mutatorReflection->getParameters()[0]);

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

return $type;
Expand Down
2 changes: 2 additions & 0 deletions Tests/Extractor/PhpDocExtractorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ public static function provideLegacyTypes()
['listOfStrings', [new LegacyType(LegacyType::BUILTIN_TYPE_ARRAY, false, null, true, new LegacyType(LegacyType::BUILTIN_TYPE_INT), new LegacyType(LegacyType::BUILTIN_TYPE_STRING))], null, null],
['self', [new LegacyType(LegacyType::BUILTIN_TYPE_OBJECT, false, Dummy::class)], null, null],
['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],
['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],
];
}

Expand Down Expand Up @@ -548,6 +549,7 @@ public static function typeProvider(): iterable
yield ['collection', Type::list(Type::object(\DateTimeImmutable::class)), null, null];
yield ['nestedCollection', Type::list(Type::list(Type::string())), null, null];
yield ['mixedCollection', Type::array(), null, null];
yield ['nullableTypedCollection', Type::nullable(Type::list(Type::object(Dummy::class))), null, null];
yield ['a', Type::int(), 'A.', null];
yield ['b', Type::nullable(Type::object(ParentDummy::class)), 'B.', null];
yield ['c', Type::nullable(Type::bool()), null, null];
Expand Down
4 changes: 4 additions & 0 deletions Tests/Extractor/ReflectionExtractorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public function testGetProperties()
'listOfStrings',
'parentAnnotation',
'genericInterface',
'nullableTypedCollection',
'foo',
'foo2',
'foo3',
Expand Down Expand Up @@ -144,6 +145,7 @@ public function testGetPropertiesWithCustomPrefixes()
'listOfStrings',
'parentAnnotation',
'genericInterface',
'nullableTypedCollection',
'foo',
'foo2',
'foo3',
Expand Down Expand Up @@ -200,6 +202,7 @@ public function testGetPropertiesWithNoPrefixes()
'listOfStrings',
'parentAnnotation',
'genericInterface',
'nullableTypedCollection',
'foo',
'foo2',
'foo3',
Expand Down Expand Up @@ -867,6 +870,7 @@ public function testTypedProperties()
$this->assertEquals(Type::list(Type::string()), $this->extractor->getType(Php74Dummy::class, 'stringCollection'));
$this->assertEquals(Type::nullable(Type::int()), $this->extractor->getType(Php74Dummy::class, 'nullableWithDefault'));
$this->assertEquals(Type::array(), $this->extractor->getType(Php74Dummy::class, 'collection'));
$this->assertEquals(Type::nullable(Type::list(Type::object(Dummy::class))), $this->extractor->getType(Php74Dummy::class, 'nullableTypedCollection'));
}

/**
Expand Down
7 changes: 7 additions & 0 deletions Tests/Fixtures/Dummy.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ class Dummy extends ParentDummy
*/
public $genericInterface;

/** @var Dummy[]|null */
public $nullableTypedCollection = null;

public static function getStatic()
{
}
Expand Down Expand Up @@ -269,4 +272,8 @@ public function addDate(\DateTimeImmutable $date)
public function hasElement(string $element): bool
{
}

public function addNullableTypedCollection(Dummy $dummy): void
{
}
}

0 comments on commit 88a279d

Please sign in to comment.