-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[PropertyInfo] ConstructorExtractor can read from promoted properties
#62385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 7.3
Are you sure you want to change the base?
Conversation
19fe14f to
fae062d
Compare
|
@xavierleune Why not just disable the |
|
@HypeMC disabling it globally feels like a bit harsh, moreover the current implementation already reads the PHPDoc, but for the function only and not for the promoted props. So the expected behavior ("read the data from the constructor") is incomplete and a BC break. |
src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php
Show resolved
Hide resolved
mtarld
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this fix might be needed.
Indeed, the PhpDocAwareReflectionTypeResolver of TypeInfo does the same.
src/Symfony/Component/PropertyInfo/Extractor/PhpStanExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/PropertyInfo/Extractor/PhpStanExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/PropertyInfo/Extractor/PhpStanExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/PropertyInfo/Extractor/PhpStanExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/PropertyInfo/Extractor/PhpStanExtractor.php
Outdated
Show resolved
Hide resolved
src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php
Outdated
Show resolved
Hide resolved
…t with `PhpDocAwareReflectionTypeResolver`)
…t with `PhpDocAwareReflectionTypeResolver`)
7cbfa54 to
cbfd37a
Compare
|
@nicolas-grekas thanks for the review, code is up to date. |
ConstructorExtractor can read from promoted properties
| if (!$docBlock = $this->getDocBlockFromPromotedProperty($class, $property)) { | ||
| if (!$docBlock = $this->getDocBlockFromConstructor($class, $property)) { | ||
| return null; | ||
| } | ||
|
|
||
| if (!$docBlock) { | ||
| return null; | ||
| $tags = $docBlock->getTagsByName('param'); | ||
| } else { | ||
| $tags = $docBlock->getTagsByName('var'); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this would be a bit more readable:
if ($docBlock = $this->getDocBlockFromPromotedProperty($class, $property)) {
$tags = $docBlock->getTagsByName('var');
} elseif ($docBlock = $this->getDocBlockFromConstructor($class, $property)) {
$tags = $docBlock->getTagsByName('param');
} else {
return null;
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'll go for:
$tags = $this->getDocBlockFromPromotedProperty($class, $property)?->getTagsByName('var')
?? $this->getDocBlockFromConstructor($class, $property)?->getTagsByName('param');
if (null === $tags) {
return null;
}
| public static function constructorPromotedPropertyWithDocblockProvider(): iterable | ||
| { | ||
| // ReflectionExtractor can only extract native PHP types, not generic types from docblocks | ||
| yield ['dates', Type::array()]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for the data provider if there's only one case.
|
|
||
| public function provideDeserializeArrayOfObjectData(): array | ||
| { | ||
| return [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not yield here as well?
| /** | ||
| * @dataProvider provideDeserializeArrayOfObjectData | ||
| */ | ||
| public function testDeserializeArrayOfObject(string $expectedClass, bool $usePromotedProperties, bool $withConstructorExtractor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lowest-deps build is failing because it's using PropertyInfo v6.4.0. Even though the with_constructor_extractor option was added in v7.3, the actual constructor extractor logic was added in v5.2.
It might make sense to split the PR and apply the PropertyInfo part of the fix to 6.4, but I'm not completely sure about that.
| class Php80PromotedDummyWithDocblock | ||
| { | ||
| /** | ||
| * @param \DateTime[] $datesWithIncoherentDocBlock |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are testing with Type::list, you might want to write list<\DateTime> instead. Otherwise, tests will fail after #62388 being merged.
The issue #60795 and the discussion #62045 describes a BC Break with symfony 7.3 regarding the
ConstructorExtractor. Old behavior could extract types from promoted properties docblock, while the new behavior only works with the function docblock. As the lastConstructorExtractorisReflectionExtractor, the extraction fails to provide an accurate description typed arrays, leading to incorrect deserialization.This PR adds a fallback to read docblock from promoted properties too, to restore the original behavior.