Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[PropertyInfo] Make ReflectionExtractor correctly extract nullability #40699

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

Merged
merged 1 commit into from
May 7, 2021

Conversation

maxim-dovydenok
Copy link
Contributor

Q A
Branch? 4.4
Bug fix? yes
New feature? no
Deprecations? no
Tickets Fix #40659
License MIT
Doc PR no

When the property had a default value ReflectionExtractor was always returning isNullable: false. After PHP 7.4 we can get isNullable from the typehint.

@carsonbot
Copy link

Hey!

I see that this is your first PR. That is great! Welcome!

Symfony has a contribution guide which I suggest you to read.

In short:

  • Always add tests
  • Keep backward compatibility (see https://symfony.com/bc).
  • Bug fixes must be submitted against the lowest maintained branch where they apply (see https://symfony.com/releases)
  • Features and deprecations must be submitted against the 5.x branch.

Review the GitHub status checks of your pull request and try to solve the reported issues. If some tests are failing, try to see if they are failing because of this change.

When two Symfony core team members approve this change, it will be merged and you will become an official Symfony contributor!
If this PR is merged in a lower version branch, it will be merged up to all maintained branches within a few days.

I am going to sit back now and wait for the reviews.

Cheers!

Carsonbot

Copy link
Member

@derrabus derrabus left a comment

Choose a reason for hiding this comment

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

Thank you for working on this issue.

What bothers me about your solution is that you have taught a method named extractFromDefaultValue() how to extract the desired information from the property type declaration. Now, the method doesn‘t do anymore what its name suggests.

Then again, there is a method named extractFromReflectionType() that already does what you‘re trying to achieve.

@maxim-dovydenok
Copy link
Contributor Author

maxim-dovydenok commented Apr 4, 2021

@derrabus, thank you for the review.

I agree that currently extractFromDefaultValue() knows more than only how to get the type from the default value. I did that because after PHP 7.4 it's no longer possible to correctly get property nullability from the default value.

Before this version, I tried to copy nullability from the extractFromReflectionType() result, but we can't do it since Type objects are not editable.

Then I was thinking about the following code, but it's harder to understand and we would also need to change extractFromDefaultValue() method arguments. And even more, currently, we know that a nullability of all Types in the $fromReflectionType is the same, but probably it can change in the future, so using the nullability of the first one is not the best option.

public function getTypes($class, $property, array $context = []): ?array
{
    ...
    $isNullable = false;
    $fromReflectionType = null;
    if (\PHP_VERSION_ID >= 70400) {
        try {
            $reflectionProperty = new \ReflectionProperty($class, $property);
            $type = $reflectionProperty->getType();
            if (null !== $type && $fromReflectionType = $this->extractFromReflectionType($type, $reflectionProperty->getDeclaringClass())) {
                $isNullable = isset($fromReflectionType[0]) && $fromReflectionType[0]->isNullable();
            }
        } catch (\ReflectionException $e) {
            // noop
        }
    }

    if ($fromDefaultValue = $this->extractFromDefaultValue($class, $property, $isNullable)) {
        return $fromDefaultValue;
    }

    if ($fromReflectionType) {
        return $fromReflectionType;
    }

    return null;
}

Another solution would be to replace part of the current version of getTypes().

...
if ($fromDefaultValue = $this->extractFromDefaultValue($class, $property)) {
    return $fromDefaultValue;
}

if (\PHP_VERSION_ID >= 70400) {
    ...
    return $this->extractFromReflectionType($type, $reflectionProperty->getDeclaringClass())) {
    ...
}

return null;

With

...
if ($fromPropertyDeclaration = $this->extractFromPropertyDeclaration($class, $property)) {
    return $fromPropertyDeclaration;
}

return null;

and

private function extractFromPropertyDeclaration(string $class, string $property): ?array
{
    // calculate nullability
    // try to get from the default value
    // try to get from the property type, if PHP >= 7.4
    // else null
}

What do you think about these solutions?

@derrabus
Copy link
Member

derrabus commented Apr 4, 2021

Okay, but if we have a typed property – why would we want to look at the default value at all? Wouldn't it be enough to prioritize the property type over the default value when extracting type information? Or am I missing something?

@maxim-dovydenok
Copy link
Contributor Author

maxim-dovydenok commented Apr 4, 2021

I did some research on why typehint extraction is at the end. Typehint support was initially added in #34557, and it had the highest priority. And then in #38041 it was moved to the end of the method. After this issue was merged, in one of the comments, issue #38416 was mentioned.

I'm not sure if in this issue we should focus on property type priority versus constructor, mutator, and accessor. But I believe we can change the code so it uses property typehint on PHP 7.4 (and default value if there's no typehint) and a default value for older versions.

I don't think we're missing something, it's not possible to have a default value different from typehint.

@maxim-dovydenok maxim-dovydenok force-pushed the ticket_40659 branch 2 times, most recently from 649ca46 to a0d4d12 Compare April 4, 2021 15:51
@dpinheiro
Copy link

dpinheiro commented Apr 5, 2021

I did some research on why typehint extraction is at the end. Typehint support was initially added in #34557, and it had the highest priority. And then in #38041 it was moved to the end of the method. After this issue was merged, in one of the comments, issue #38416 was mentioned.

I'm not sure if in this issue we should focus on property type priority versus constructor, mutator, and accessor. But I believe we can change the code so it uses property typehint on PHP 7.4 (and default value if there's no typehint) and a default value for older versions.

I don't think we're missing something, it's not possible to have a default value different from typehint.

I would like to take this opportunity to discuss this priority if possible. In my point of view #38041 introduced a BC break as serializer started having a different behaviour, and currently this in an impediment for me to update some of my projects, as described in #38416. Do you think we could change this order? I'm available to help with that

@derrabus
Copy link
Member

derrabus commented Apr 7, 2021

@dpinheiro I understand that the issue you've mentioned is important to you. But please let's leave the discussion on that ticket.

@nicolas-grekas
Copy link
Member

Thank you @shiftby.

@nicolas-grekas nicolas-grekas merged commit fab61ee into symfony:4.4 May 7, 2021
This was referenced May 9, 2021
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.

5 participants