8000 [PropertyInfo] strip only leading `\` when unknown docType by EmilMassey · Pull Request #45720 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[PropertyInfo] strip only leading \ when unknown docType #45720

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
Mar 18, 2022
Merged

[PropertyInfo] strip only leading \ when unknown docType #45720

merged 1 commit into from
Mar 18, 2022

Conversation

EmilMassey
Copy link
Q A
Branch? 4.4, 5.4, 6.0
Bug fix? yes
New feature? no
Deprecations? no
Tickets Fix #44455 (partially)
License MIT
Doc PR -

Fixes issue in PhpDocExtractor when dealing with some pseudo-types (non-empty-string, positive-int, etc.):

class TestClass {
    /** @var non-empty-string */
    public $foo;

    /** @var positive-int */
    public $bar;
}

$extractor = new \Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor();
$fooType = $extractor->getTypes(TestClass::class, 'foo'); // $builtinType: object, $class: on-empty-string (first character trimmed)
$barType = $extractor->getTypes(TestClass::class, 'bar'); // $builtinType: object, $class: ositive-int (first character trimmed)

The bug exists in 4.4, 5.4 and 6.0. It may exist in 6.1 as the invalid line is still there, but due to changes made in #44451, above snippet will no longer produce the bug. I was not able to reproduce the error in 6.1, but I suspect there may exist some pseudo-type that is still affected by the bug.

I'm not sure if the test I wrote is OK, but it is the only way I could think of to validate my fix. In my opinion (see #44455), unknown pseudo-type should not be mapped to an object, so after the fix handling of pseudo-types is still broken but at least the results are consistent between PhpStanExtractor and PhpDocExtractor. But I agree with @derrabus (#44455 (comment)) that until there is no way to detect if we are dealing with a pseudo-type, assuming it is a reference to an object is the sanest thing to do.

@@ -164,6 +164,6 @@ private function getPhpTypeAndClass(string $docType): array
return ['object', $docType];
}

return ['object', substr($docType, 1)];
return ['object', ltrim($docType, '\\')]; // strip the namespace's `\`-prefix

Choose a reason for hiding this comment

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

With this "fix" pseudo types will be considered as an object. That's wrong.

object(Symfony\Component\PropertyInfo\Type)#15949 (6) {
  ["builtinType":"Symfony\Component\PropertyInfo\Type":private]=>
  string(6) "object"
  ["nullable":"Symfony\Component\PropertyInfo\Type":private]=>
  bool(false)
  ["class":"Symfony\Component\PropertyInfo\Type":private]=>
  string(14) "numeric-string"
  ["collection":"Symfony\Component\PropertyInfo\Type":private]=>
  bool(false)
  ["collectionKeyType":"Symfony\Component\PropertyInfo\Type":private]=>
  array(0) {
  }
  ["collectionValueType":"Symfony\Component\PropertyInfo\Type":private]=>
  array(0) {
  }
}

Copy link
Author

Choose a reason for hiding this comment

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

pseudo types will be considered as an object

My fix doesn't change that. Before the fix it is an object too (but the $class property value has the first character trimmed, and this bug is the subject of my fix):

class Symfony\Component\PropertyInfo\Type#1168 (6) {
    private $builtinType =>
    string(6) "object"
    private $nullable =>
    bool(false)
    private $class =>
    string(13) "umeric-string"
    private $collection =>
    bool(false)
    private $collectionKeyType =>
    NULL
    private $collectionValueType =>
    NULL
  }

Although it may be NULL in some cases. I think it depends on phpdocumentor version, but I'm not sure yet. Can you confirm?

By the way, if you expected numeric-string pseudo-type to be mapped to string built-in type, it will be done so in Symfony 6.1 thanks to #44451

Choose a reason for hiding this comment

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

Yes, currently it will be mapped to object (and the first character got removed).
But think about your fix. Is numeric-string really an object? No.

And in some software there will be done additional checks/procedures when it's an object. So this commit isn't really an fix.

Copy link
Author
@EmilMassey EmilMassey Mar 14, 2022

Choose a reason for hiding this comment

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

I'm not trying here to fix the issue with psuedo-types being treated as object. It still is a big issue and I believe this behavior cannot be changed in older branches as this will be a BC break. It is undocumented feature - the documentation does not promise that the component handles pseudo-types and before v6.1 it only handles a few of them. In my opinion we should implement it in major version and that's why I created #44455. But it's a hard problem to solve.

At the moment the least I can do without causing BC break is to merely fix the very issue with the first character being removed. If we fix it, I can work around the problem somehow (e.g. by checking if class_exists or by comparing it to predefined pseudo-types strings) in my project, what I can't do without the fix because the original phpdoc is in fact lost due to this bug.

Is numeric-string really an object? No.

Due to string being a reserved keyword in PHP and - which is not allowed in a class name it never is. But consider this example:

class SomeClass
{
    /**
     * @var scalar
     */
    public $scalarProperty;
}

class scalar {}

scalar is a pseudo-type handled by PHPStan. But if the scalar class is defined, it may as well be an object. Before the fix, extractor gives me an object with calar className and I expect scalar - that my fix resolves.

@derrabus
Copy link
Member

The test failure looks realted:

There was 1 failure:

1) Symfony\Component\PropertyInfo\Tests\Extractor\PhpDocExtractorTest::testUnknownPseudoType
null does not match expected type "array".

/home/runner/work/symfony/symfony/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php:356

@fabpot
Copy link
Member
fabpot commented Mar 18, 2022

Thank you @EmilMassey.

@fabpot fabpot merged commit a2cfd7e into symfony:4.4 Mar 18, 2022
@EmilMassey EmilMassey deleted the phpdoc-extractor-pseudotype branch March 18, 2022 08:04
This was referenced Apr 2, 2022
@gnutix
Copy link
Contributor
gnutix commented Apr 4, 2022

I'm using NelmioApiDocBundle, and the following code started breaking with : get_parent_class(): Argument #1 ($object_or_class) must be an object or a valid class name, string given

    public function supports(Model $model): bool
    {
        return Enum::class === get_parent_class((string) $model->getType()->getClassName());
    }

The problem being that now sometimes $model->getType()->getClassName() returns ?\Some\Namespaced\ClassName with a leading ? for the "nullable". Which leads the bundle to not properly recognize classes that it used to describe automatically. :(

@EmilMassey
Copy link
Author

@gnutix Thanks for noticing the bug. Is the code snippet from the bundle or it is a fragment of your project? If it’s from the bundle, could you please link the source?

Maybe it’s a good idea to create a new issue so it can be seen by more people as this PR is already closed?

@gnutix
Copy link
Contributor
gnutix commented Sep 16, 2022

@EmilMassey I've finally had the time to look at it again, and fixed it. It was a bad typing on our part in a constructor :

/** @var array<?ExtraHoursReportCell> */
public array $weeks,

The ? was triggering the issue, and was not necessary anymore because the code had evolved and it never received a null there anymore... 😄

@EmilMassey
Copy link
Author

@gnutix

I'm glad you've managed to solve the problem, and thanks for the response :)

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.

7 participants
0