Skip to content

[Serializer] Improve collecting errors on denormalization and promoted property constructors #45112

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

Conversation

barell
Copy link

@barell barell commented Jan 22, 2022

Q A
Branch? 5.4
Bug fix? yes
New feature? no
Deprecations? no
Tickets Fix #44772
License MIT

There are few improvements/fixes:

  1. It will show all missing properties based on the constructor parameters (previously it was only first one)
  2. There will be proper path and expected type (with support for union types) instead of unknown expected type and null path
  3. It won't throw TypeError anymore on incompatible constructor types and will continue to collect all errors

@barell
Copy link
Author

barell commented Jan 22, 2022

After some crazy rollercoaster with git branches I think I managed to make it right this time.

@carsonbot
Copy link

Hey!

I think @Th3Mouk has recently worked with this code. Maybe they can help review this?

Cheers!

Carsonbot

@barell
Copy link
Author

barell commented Jan 27, 2022

This PR is based on #44782 which I messed up a bit.

I fixed all checks but not sure why psalm is broken. Any feedback will be appreciated!

@barell barell force-pushed the collect-denormalizaton-errors-in-constructor-improvements-5.4-fixed branch from 1cb0f8b to ca2a646 Compare January 27, 2022 15:45
@barell
Copy link
Author

barell commented Jan 28, 2022

@dunglas @nicolas-grekas any feedback on this PR will be appreciated. These fixes would really help simplify a lot of things where we use Symfony Serializer 🙏

Copy link
Contributor

@mtarld mtarld left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @barell !
Thank you for that PR 🙂
Could you target the 6.2 branch instead?

$expectedTypes = ['unknown'];

if ($constructorParameter->hasType()) {
if (\PHP_VERSION_ID >= 80000) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed as Symfony will now require at least PHP8.1

@@ -1050,6 +1051,141 @@ public function testCollectDenormalizationErrorsWithConstructor()

$this->assertSame($expected, $exceptionsAsArray);
}

/** @requires PHP 8.0 */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove it as well (same for others)

}

/** @requires PHP 8.0 */
public function testCollectDenormalizationErrorsWithConstructorPartiallyMissingParameters()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That test and the previous one (testCollectDenormalizationErrorsWithConstructorMissingParameters) are kind of testing the same stuff, WDYT?

Comment on lines +420 to +424
if ($constructorParameter->getType() instanceof \ReflectionUnionType) {
$expectedTypes = array_map(function ($type) { return $type->getName(); }, $constructorParameter->getType()->getTypes());
} else {
$expectedTypes = [$constructorParameter->getType()->getName()];
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In PHP8.1, there is a new "intersection" type. And the ReflectionIntersectionType do not have any getName method.
Therefore IMHO, the easiest way to go is to rely on the fact that the ReflectionPropertyType is stringable.

So we can do something like that:

if ($constructorParameter->getType() instanceof \ReflectionUnionType) {
    $expectedTypes = array_map(function (\ReflectionType $t): string { return (string) $t; }, $constructorParameter->getType()->getTypes());
} else {
    $expectedTypes = [(string) $constructorParameter->getType()];
}

It'll handle every kind of ReflectionPropertyType and only split the expected type array whenever it's an union type.

@nicolas-grekas
Copy link
Member

I'm closing because this stalled. Also because closing my encourage taking over? @mtarld maybe? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants