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

Add PHPStan strict rules (except for empty.notAllowed) #1241

Merged
merged 24 commits into from
Jul 23, 2024

Conversation

westonruter
Copy link
Member

@westonruter westonruter commented May 23, 2024

Part of #1219
See #775

Note: This does not fix the empty.notAllowed issues since they are more complicated and deserve a separate PR.

Just adding phpstan-strict-rules results in the following 863 errors in the codebase:

    712 staticMethod.dynamicCall
     60 empty.notAllowed
     36 booleanNot.exprNotBoolean
     21 if.condNotBoolean
     11 booleanAnd.leftNotBoolean
      5 cast.useless
      4 booleanOr.rightNotBoolean
      4 arrayFilter.strict
      3 method.childReturnType
      2 ternary.condNotBoolean
      2 booleanAnd.rightNotBoolean
      1 variable.implicitArray
      1 plus.leftNonNumeric
      1 elseif.condNotBoolean

This report was generated via:

npm run phpstan -- -- -v | grep 🪪 | cut -c16- | sed 's/ *$//' | sort | uniq -c | sort -nr

When ignoring staticMethod.dynamicCall, booleanNot.exprNotBoolean, and if.condNotBoolean in tests, this goes down to just 144 errors:

     60 empty.notAllowed
     34 booleanNot.exprNotBoolean
     16 if.condNotBoolean
     11 booleanAnd.leftNotBoolean
      5 cast.useless
      4 booleanOr.rightNotBoolean
      4 arrayFilter.strict
      3 method.childReturnType
      2 ternary.condNotBoolean
      2 booleanAnd.rightNotBoolean
      1 variable.implicitArray
      1 plus.leftNonNumeric
      1 elseif.condNotBoolean

The following remain to be addressed:

  • empty.notAllowed (60)
  • booleanNot.exprNotBoolean (34)
  • if.condNotBoolean (16)
  • booleanAnd.leftNotBoolean (11)
  • cast.useless (5)
  • booleanOr.rightNotBoolean (4)
  • arrayFilter.strict (4) (rule disabled)
  • method.childReturnType (3)
  • ternary.condNotBoolean (2)
  • booleanAnd.rightNotBoolean (2)
  • variable.implicitArray (1)
  • plus.leftNonNumeric (1)
  • elseif.condNotBoolean (1)

@westonruter westonruter added this to the performance-lab 3.2.0 milestone May 23, 2024
@westonruter westonruter added the [Type] Enhancement A suggestion for improvement of an existing feature label May 23, 2024
@westonruter
Copy link
Member Author

The one last PHPStan error remaining is empty.notAllowed. There are 60 instances of this.

@@ -57,3 +59,6 @@ parameters:
-
identifier: cast.string
path: */tests/*
-
identifier: staticMethod.dynamicCall
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure why this issue is being reported for assertion method calls in tests.

@westonruter westonruter changed the title Add PHPStan strict rules Add PHPStan strict rules (except for empty.notAllowed) Jun 13, 2024
@westonruter westonruter marked this pull request as ready for review June 13, 2024 10:13
Copy link

github-actions bot commented Jun 13, 2024

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: westonruter <westonruter@git.wordpress.org>
Co-authored-by: joemcgill <joemcgill@git.wordpress.org>
Co-authored-by: swissspidy <swissspidy@git.wordpress.org>
Co-authored-by: mukeshpanchal27 <mukesh27@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Copy link
Member

@joemcgill joemcgill left a comment

Choose a reason for hiding this comment

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

This looks good to me. I've added some suggestions, but none blocking so I'm pre-approving. Feel free to apply or ignore.

plugins/embed-optimizer/hooks.php Outdated Show resolved Hide resolved
@@ -63,7 +63,7 @@ function embed_optimizer_filter_oembed_html( string $html ): string {
if ( 1 === $script_count && ! $has_inline_script && $html_processor->has_bookmark( 'script' ) ) {
add_action( 'wp_footer', 'embed_optimizer_lazy_load_scripts' );
if ( $html_processor->seek( 'script' ) ) {
if ( $html_processor->get_attribute( 'type' ) ) {
if ( is_string( $html_processor->get_attribute( 'type' ) ) ) {
Copy link
Member

Choose a reason for hiding this comment

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

Same as above.

Suggested change
if ( is_string( $html_processor->get_attribute( 'type' ) ) ) {
if ( null !== $html_processor->get_attribute( 'type' ) ) ) {

Copy link
Member Author

Choose a reason for hiding this comment

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

In this case, I think the code should stay as-is. Since get_attribute can return true in the case of a boolean attribute, we wouldn't want to try passing a true to set_attrbute(). I believe PHPStan would complain about that anyway.

@@ -465,7 +465,7 @@ function perflab_get_plugin_settings_url( string $plugin_slug ): ?string {
return null;
}
$href = $p->get_attribute( 'href' );
if ( $href && is_string( $href ) ) {
if ( is_string( $href ) && '' !== $href ) {
Copy link
Member

Choose a reason for hiding this comment

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

I could go either way here, but for consistency...

Suggested change
if ( is_string( $href ) && '' !== $href ) {
if ( null !== $href && '' !== $href ) {

Copy link
Member Author

Choose a reason for hiding this comment

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

This should stay as is because if <a href> is encountered, then $href here would be true which would be a type error since the function returns a string or null.

@@ -67,7 +67,7 @@ public function register_metric( string $metric_slug, array $args ): void {
return;
}

if ( did_action( 'perflab_server_timing_send_header' ) && ! doing_action( 'perflab_server_timing_send_header' ) ) {
if ( 0 !== did_action( 'perflab_server_timing_send_header' ) && ! doing_action( 'perflab_server_timing_send_header' ) ) {
Copy link
Member

Choose a reason for hiding this comment

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

This is such a common pattern in WP that I wouldn't even think of needing to specify, but makes sense.

Comment on lines +290 to 291
if ( '' === $resource_url ) {
return '';
Copy link
Member

Choose a reason for hiding this comment

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

Could just return the value early in this case.

Suggested change
if ( '' === $resource_url ) {
return '';
if ( '' === $resource_url ) {
return $resource_url;

Co-authored-by: Joe McGill <801097+joemcgill@users.noreply.github.com>
Copy link
Member

@swissspidy swissspidy left a comment

Choose a reason for hiding this comment

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

LGTM, pending the merge conflict resolution

… add/phpstan-strict-rules

* 'trunk' of https://github.com/WordPress/performance: (206 commits)
  fix(webp-uploads): prevent picture element when JPEG output disabled
  Prepare 0.4.1 release of Optimization Detective
  Update attribute order in Image Prioritizer test after eliminating excessive seek() calls
  Account for visitors calling next_token() not just seek()
  Update attribute order in embed-optimizer test due to not seeking
  Add test to ensure tag visitation does not exceed seek limit
  Fix attribute order in tests now that seeking is not happening
  Add missing bookmark name to warning message
  Only seek back to the current tag if a tag visitor seeked
  Migrate commander for v12
  Upgrade commander to 12.1.0
  Bump yoast/phpunit-polyfills from 1.1.1 to 2.0.1
  Bump @wordpress/scripts from 26.19.0 to 28.3.0
  Bump @wordpress/env from 9.6.0 to 10.3.0
  Migrate husky
  Update Octokit to use dynamic import
  Bump husky from 8.0.3 to 9.1.0
  Add labels for Dependabot PRs
  Bump web-vitals from 3.5.0 to 4.2.1
  Bump phpstan/extension-installer from 1.3.1 to 1.4.1
  ...
… add/phpstan-strict-rules

* 'trunk' of https://github.com/WordPress/performance:
  Fix OD test case for WP 6.7-alpha
if (
! is_string( $class_name )
||
1 !== preg_match( '/(?:^|\s)wp-image-([1-9]\d*)(?:\s|$)/i', $class_name, $matches )
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
1 !== preg_match( '/(?:^|\s)wp-image-([1-9]\d*)(?:\s|$)/i', $class_name, $matches )
1 !== (int) preg_match( '/(?:^|\s)wp-image-([1-9]\d*)(?:\s|$)/i', $class_name, $matches )

Do we needs to cast int here?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, because it can either be an int or false, and we're checking to see if it is not identical to the value.

@@ -534,22 +534,26 @@ function webp_uploads_update_image_references( $content ): string {

// This content does not have any tag on it, move forward.
// TODO: Eventually this should use the HTML API to parse out the image tags and then update them.
if ( ! preg_match_all( '/<(img)\s[^>]+>/', $content, $img_tags, PREG_SET_ORDER ) ) {
if ( 0 === (int) preg_match_all( '/<(img)\s[^>]+>/', $content, $img_tags, PREG_SET_ORDER ) ) {
Copy link
Member Author

Choose a reason for hiding this comment

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

The use of (int) isn't needed here either...

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, actually it is. Because it's preg_match_all() so we don't know the number of image tags being matched. Otherwise, it could be 1 === .... So by casting the return value to (int), it will convert both 0 and false to 0. Alternatively, this could be:

Suggested change
if ( 0 === (int) preg_match_all( '/<(img)\s[^>]+>/', $content, $img_tags, PREG_SET_ORDER ) ) {
if ( false === (bool) preg_match_all( '/<(img)\s[^>]+>/', $content, $img_tags, PREG_SET_ORDER ) ) {

But false indicates the error state. The integer return value is the normal case, the number of matches.

tests/bootstrap.php Outdated Show resolved Hide resolved
Copy link
Member

@mukeshpanchal27 mukeshpanchal27 left a comment

Choose a reason for hiding this comment

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

Thanks @westonruter, LGTM!

@mukeshpanchal27
Copy link
Member

@westonruter Could you please merge as it not allow me. Shows that Merging can be performed automatically with 1 approving review.

@westonruter westonruter merged commit de93b65 into trunk Jul 23, 2024
15 checks passed
@westonruter westonruter deleted the add/phpstan-strict-rules branch July 23, 2024 05:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Enhancement A suggestion for improvement of an existing feature
Projects
Status: Done 😃
Development

Successfully merging this pull request may close these issues.

4 participants