Skip to content
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

[PropertyInfo] Add support for phpDocumentor and PHPStan pseudo-types #44451

Merged
merged 1 commit into from Dec 17, 2021

Conversation

EmilMassey
Copy link
Contributor

@EmilMassey EmilMassey commented Dec 3, 2021

Q A
Branch? 6.1
Bug fix? no
New feature? yes
Deprecations? no
Tickets -
License MIT
Doc PR -

More and more apps are using pseudo-types like non-empty-string, positive-int which are understood by static analysis tools but are not a part of the language. This PR adds support for these types to PhpDocExtractor and PhpStanExtractor. Pseudo-type is mapped to built-in type(s) (e.g. non-empty-string => string, positive-int => int, number => int|float).

This PR adds support for all pseudo-types defined by the phpDocumentor (some of them like list or true, false are already supported) and PHPStan's basic types.

@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 6.1 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

@stof
Copy link
Member

stof commented Dec 3, 2021

The PhpstanExtractor should support the phpstan pseudo-types

@EmilMassey
Copy link
Contributor Author

The PhpstanExtractor should support the phpstan pseudo-types

I agree and it would be great if PropertyInfo supported all of PHPStan's types, but it is a very complex system with integer ranges, generics, complex array shapes, literals and constants etc. so it will need a lot of work to support them all. We can work on it in future PRs but I think it is too much for just one PR.

All pseudo-types that are currently supported by phpDocumentor are also valid PHPStan pseudo-types so it didn't make sense to me not to add them to PhpstanExtractor. It can already recognize true, false or list pseudo-types and my PR adds just some more to the list. I know it's incomplete but we can gradually add support for more types. At the moment the problem is that there's no such list with all pseudo-types recognized by the PHPStan and I'm sure there will be more and more types as the tool evolves dynamically.

@stof
Copy link
Member

stof commented Dec 3, 2021

@EmilMassey supporting the full type system might be too complex indeed. But you could at least support the full list of pseudo-types (i.e. also negative-int).
the phpdoc types are documented at https://phpstan.org/writing-php-code/phpdoc-types. And you can look at the source code in case the doc is incomplete: https://github.com/phpstan/phpstan-src/blob/c2ff0bd31327e861f651e55db364823cba0f0262/src/PhpDoc/TypeNodeResolver.php#L130

@EmilMassey EmilMassey changed the title [PropertyInfo] Add support for phpDocumentor pseudo-types [PropertyInfo] Add support for phpDocumentor and PHPStan pseudo-types Dec 3, 2021
Copy link
Member

@dunglas dunglas left a comment

Choose a reason for hiding this comment

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

In a future iteration, it could be useful to give access to the pseudo type to the end use.

For instance, this could help generating a more precise JSON Schema in API Platform.

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.

The low-deps test failure looks related. Can you have a look?

@EmilMassey EmilMassey force-pushed the propertyinfo-pseudotypes branch 2 times, most recently from 106e654 to 68cb7e6 Compare December 13, 2021 19:30
@EmilMassey
Copy link
Contributor Author

The low-deps test failure looks related. Can you have a look?

Fixed, thanks

Copy link
Contributor

@Korbeil Korbeil left a comment

Choose a reason for hiding this comment

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

Thanks for adding this feature to PhpStanExtractor !

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

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

Not sure: do we need to merge this as a bugfix on 5.4 since we changed the default extractor, and not supporting theses types might break existing apps?

In a future iteration, it could be useful to give access to the pseudo type to the end use.

true, PR welcome or issue at least :)

@derrabus
Copy link
Member

Not sure: do we need to merge this as a bugfix on 5.4

The change is too heavy for a bugfix, imho.

since we changed the default extractor, and not supporting theses types might break existing apps?

The PHPDoc extractor on 5.3 did not understand most pseudo-types either. See #44578.

@nicolas-grekas
Copy link
Member

Thank you @EmilMassey.

@nicolas-grekas nicolas-grekas merged commit 53e49a8 into symfony:6.1 Dec 17, 2021
@EmilMassey EmilMassey deleted the propertyinfo-pseudotypes branch December 17, 2021 12:12
fabpot added a commit that referenced this pull request Mar 18, 2022
… (EmilMassey)

This PR was squashed before being merged into the 4.4 branch.

Discussion
----------

[PropertyInfo] strip only leading `\` when unknown docType

| 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.):
```php
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.

Commits
-------

723cd09 [PropertyInfo] strip only leading `\` when unknown docType
@fabpot fabpot mentioned this pull request Apr 15, 2022
@astronom
Copy link

@nicolas-grekas if it possible to backport this changes to 5.4 branch?

@nicolas-grekas
Copy link
Member

That's a new feature. 5.4 only accepts bug fixes now.

@EmilMassey
Copy link
Contributor Author

EmilMassey commented Sep 30, 2022

@astronom If you need to support extracting these pseudotypes in v5.4, you can implement your own extractor. Note that this implementation requires phpstan/phpdoc-parser and I tested it in v5.3, so with v5.4 it may require some tweaks.

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.

None yet

8 participants