-
-
Notifications
You must be signed in to change notification settings - Fork 27
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
Add type checking for hook callbacks in add_action
and add_filter
#107
Conversation
This PR brings a fantastic feature to |
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'm waiting for our local PHPStan specialist.
@herndlm
@szepeviktor @herndlm Would be great to get this in |
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.
Sorry for taking so long to take a look at this, I was a bit frightened away in the beginning by the big diff, but this seems to be mostly coming from tests :)
I'm not a specialist for PHPStan Rules tbh, you might already know them better yourself. But I checked the rule and added a couple of comments, in general it looks well-made to me and very useful! I did not check the test thoroughly, you surely know the correct WP function behaviour there better than me :)
{ | ||
$acceptedType = $callbackAcceptor->getReturnType(); | ||
$accepted = $this->ruleLevelHelper->accepts( | ||
new VoidType(), |
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 never even used it myself yet, but does it make sense maybe to also add tests for the never
return type? Not sure what we'd expect, e.g. if PHPStan or this rule is going to complain that the callable never returns / always exits 🤔
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'll take a look!
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.
Ah I've already got tests for this! https://github.com/szepeviktor/phpstan-wordpress/pull/107/files#diff-56e889cfab3a17dd1d1fbc7b198fcf3130ca973b4a7fd3342c696d29df13a96dR199-R213.
Unfortunately it is acceptable for both filters and actions to exit because WP YOLO. I'm not sure how VoidType
relates to NeverType
but this is working as expected and the tests pass, so I think we're all good here.
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.
oh, ok. I missed those tests
ok then, I'd say go for it! :) |
Thank you! and Thank you! |
@johnbillion @herndlm We have a bunch of problems. |
Or PHPStan, or WP stubs? |
Last successful test back in September was also with WP 6.0.1
|
there are still the \FQCN problems there was another issue about. I had an easy solution in mind, but I think you didn't like it because it involved a phpstan min version bump. but I'll check that one out quickly. and the rest are theme related type changes? could be stubs? |
Let's close our eyes for this type of problems! 🙈 |
All right guys! |
…#107) (#121) * Setup the hook callback rule and test. * Add the wp-hooks library. * Start adding tests. * Preparing more tests. * If we don't have enough arguments, bail out and let PHPStan handle the error. * If the callback is not valid, bail out and let PHPStan handle the error: * Simplify this. * More valid test cases. * Update some test line numbers. * First pass at detecting mismatching accepted and expected argument counts. * Remove some accidental duplicates. * Fix some logic. * Let's split this up before it gets out of hand. * Reduce this down. * More tidying up. * We're going to be needing this in multiple methods soon. * Prep for callback return type checking, not yet functional. * Split action return type assertion into its own method. * Bring this message more inline with those used by PHPStan. * Add detection for filter callbacks with no return value. * Don't need this just yet. * Use early exit to reduce code nesting. * Remove unused imports. * Yoda comparisons are disallowed. * Coding standards. * Remove unused code. * Use early return to reduce code nesting. * Remove more unused code. * Renaming. * Use early return to reduce code nesting. * Tidying up. * Correct logic introduced during refactoring. * Exclude "maybe" callables. * More handling for parameter counts. * More handling for optional parameters in hook callbacks. * Make the tests more manageable. * Tests for more callback types. * Tidying up. * This isn't used. * More test cases. * Tests for variadic callbacks. * More specific handling for variadic callbacks. * More tests. * The hooks names are not relevant to the tests. * Remove an `else`. * I'm still not entirely sure why this works, but it does. Props @herndlm. * Another test for an action with a return value. * More variadic handling. * Turns out PHPStan handles typed and untyped functions differently. * Partly broken callbacks will trigger an error in PHPStan so we don't need to handle them. * Terminology. * Refactoring. * PHP 7.2 compatibility. * Reorder the processing so the return type is checked first. * More tests. Co-authored-by: Viktor Szépe <[email protected]> Co-authored-by: John Blackbourn <[email protected]>
oh, this was actually one thing, the FQCN change in PHPStan 1.8.7 was causing the WP_Theme extension class to not do anything anymore (because the extension relied on the old faulty behaviour). should be fixed with #122 |
* Fix FQCN * Add type checking for hook callbacks in `add_action` and `add_filter` (#107) (#121) * Setup the hook callback rule and test. * Add the wp-hooks library. * Start adding tests. * Preparing more tests. * If we don't have enough arguments, bail out and let PHPStan handle the error. * If the callback is not valid, bail out and let PHPStan handle the error: * Simplify this. * More valid test cases. * Update some test line numbers. * First pass at detecting mismatching accepted and expected argument counts. * Remove some accidental duplicates. * Fix some logic. * Let's split this up before it gets out of hand. * Reduce this down. * More tidying up. * We're going to be needing this in multiple methods soon. * Prep for callback return type checking, not yet functional. * Split action return type assertion into its own method. * Bring this message more inline with those used by PHPStan. * Add detection for filter callbacks with no return value. * Don't need this just yet. * Use early exit to reduce code nesting. * Remove unused imports. * Yoda comparisons are disallowed. * Coding standards. * Remove unused code. * Use early return to reduce code nesting. * Remove more unused code. * Renaming. * Use early return to reduce code nesting. * Tidying up. * Correct logic introduced during refactoring. * Exclude "maybe" callables. * More handling for parameter counts. * More handling for optional parameters in hook callbacks. * Make the tests more manageable. * Tests for more callback types. * Tidying up. * This isn't used. * More test cases. * Tests for variadic callbacks. * More specific handling for variadic callbacks. * More tests. * The hooks names are not relevant to the tests. * Remove an `else`. * I'm still not entirely sure why this works, but it does. Props @herndlm. * Another test for an action with a return value. * More variadic handling. * Turns out PHPStan handles typed and untyped functions differently. * Partly broken callbacks will trigger an error in PHPStan so we don't need to handle them. * Terminology. * Refactoring. * PHP 7.2 compatibility. * Reorder the processing so the return type is checked first. * More tests. Co-authored-by: Viktor Szépe <[email protected]> Co-authored-by: John Blackbourn <[email protected]> * Fix * Fix Co-authored-by: John Blackbourn <[email protected]>
@johnbillion How well is this supposed to work yet? I am getting lots of "Filter callback return statement is missing" false positives. Example: The top three lines are getting flagged because those methods don't have a return type (just in PHPDoc). Looks like it doesn't take |
It's supposed to be perfect, beautiful, flawless, delightful, and kind, but it probably needs some tweaking. Can you open a new issue please? |
FYI @swissspidy There is no Please open that issue with the first problem 🚀 |
thx again for this, renovatebot is just updating this in our projects, CI still green so far 🤞 🎉 |
This implements part of #106.
I'm learning more about PHPStan internals as I work on this, so it's going to take some time 😄 . Once everything's working and covered by tests then I'll refactor it.
Applicable to all hooks:
$accepted_args
parameter should match the number of parameters that the callback acceptsadd_filter
must return a valueadd_action
must return voidApplicable when the hook signature is known (eg. a WordPress core hook):The signature of the callback function should be checked against the parameters that get passed to the hookA filter should not be used as an action, nor vice versaThe callback foradd_filter
must return a value with a type which is compatible with the type passed to itI've decided to implement the WordPress core hook handling in a separate PR because it relies on the wp-hooks API package that I'm writing and it's not ready yet.