-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
chore: Implement PHPStan Preg::match()
extensions
#8103
Conversation
PHPStan Preg::match()
extensionsPreg::match()
extensions
use PHPStan\Type\Php\RegexArrayShapeMatcher; | ||
use PHPStan\Type\StaticMethodTypeSpecifyingExtension; | ||
|
||
final class PregMatchTypeSpecifyingExtension implements StaticMethodTypeSpecifyingExtension, TypeSpecifierAwareExtension |
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 wonder how we can avoid those custom extensions.
Preg::match is proxy to preg_match, can't we rely on php-stan knowledge of preg_match typing?
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.
That's exactly what this extension does, can't see how it could be any shorter.
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 wonder if we can avoid extension at all and have in-place (close to definition of Preg::match
) declaration, something like @returns ReturnType<preg_match>
(if I would do it in typescript - sorry, not that deeply familiar with PHPStan typing)
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.
It's not possible. This is the closest we can get and still be flexible. Some preg_match
"replacements" sometimes have a bit different behaviour in regard to some flags for example. Some replacements still use by-ref parameters, some other replacements return matches instead.
@staabm could you please rebase this PR and resolve conflicts? I can do it too but later (AFK now). |
@Wirone done |
Auto-review tests have to be adjusted. But I believe PHPStan extensions classes have to be placed outside of the |
This comment was marked as duplicate.
This comment was marked as duplicate.
moved the code to a dev-tools/phpstan. should I regenerate the baseline? I did not yet do that as this might easily produce conflicts with other PRs. the CI job looks like with this added type knowledge, a lot of false positive will be deleted from the baseline :-) |
Yes, failing CI cannot be reviewed :) |
just updated the PR to the latest RegexArrayShapeMatcher api (which adds support for |
PR looks good to me, we just need to clean up some CI jobs to make this PR green. @staabm yes, baseline must be regenerated as I don't have rights to merge PRs with failed jobs (other PRs have to resolve conflicts). |
added support for |
FYI: I did an interactive rebase and cleaned up commits a little (kept only meaningful changes). |
let me know whether there is anything I can do to help getting this landed. |
I believe we need proper inner structure for PHPStan-related files, with more precise namespaces. In the future we may need classes that act as a PHPStan services (not extensions), tests are also nice to have 😉.
Personally I find it better than if/else with similar calls to different methods with exact same parameters.
@staabm Instead of doing classic review I just applied changes I would like to see. Please get familiar with the changes and let me know if you're OK with them 🙂. |
I will add tests sometime this week |
$flagsType = $scope->getType($flagsArg->value); | ||
} | ||
|
||
$matcherMethod = ('match' === $methodReflection->getName()) ? 'matchExpr' : 'matchAllExpr'; |
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.
$matcherMethod = ('match' === $methodReflection->getName()) ? 'matchExpr' : 'matchAllExpr'; | |
$matcherMethod = 'match' === $methodReflection->getName() | |
? 'matchExpr' | |
: 'matchAllExpr'; |
pure cs fix, one more in another file
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 CS tool does not complain, then it's a personal preference - I use multiline ternaries only when these are longer than the max line length (in IDE), parentheses are superfluous but make the expression more readable.
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.
see #7587
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 am aware of this feature request, but this is not part of current Fixer's coding standard, so it's not applicable 🙂.
Thank you @staabm 🍻! |
use PHPStan\Type\Php\RegexArrayShapeMatcher; | ||
use PHPStan\Type\StaticMethodTypeSpecifyingExtension; | ||
|
||
final class PregMatchTypeSpecifyingExtension implements StaticMethodTypeSpecifyingExtension, TypeSpecifierAwareExtension |
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 have noticed Preg::replaceCallback
is not passing the shape to the callback, would you mind writing an extension for it as well?
In PHPStan 1.11.6 I have implemented array-shape inference for
preg_match
in PHPStan.See a in detail write-up in my Blog: https://staabm.github.io/2024/07/05/array-shapes-for-preg-match-matches.html
TL;DR: PHPStan is able to figure out the type
$matches
has after apreg_match
call.The underlying feature was implemented in a way, that it can be re-used in 3rd party libs, which wrap calls to
preg_match
in a API-compatible way. With this PR I am providing the necessary PHPStan extensions so calls to PHP-CS-Fixers ownPreg::match
static method can utilize the new capabilities.This means code like e.g.
PHP-CS-Fixer/src/Console/Command/SelfUpdateCommand.php
Lines 97 to 99 in f391652
PHPStan is able to infer the type of
$matches
- likedumpType($matches);
:before this PR
after this PR
After all this means PHPStan is able to determine more precise typings while analyzing PHP-CS-Fixer
Update: PHPStan 1.11.9 introduced additional type narrowing for
preg_match_all()
. This was also incorporated in this PR.