Opened 2 months ago
Last modified 3 weeks ago
#64898 new task (blessed)
PHPStan code quality improvements for 7.1
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | 7.1 | Priority: | normal |
| Severity: | normal | Version: | |
| Component: | General | Keywords: | has-patch has-unit-tests |
| Focuses: | coding-standards | Cc: |
Change History (26)
This ticket was mentioned in PR #11302 on WordPress/wordpress-develop by @Soean.
2 months ago
#1
- Keywords has-patch added
This ticket was mentioned in PR #11303 on WordPress/wordpress-develop by @Soean.
2 months ago
#2
The url value is $tag->link unless '#' === $tag->link, then its #. Which is the same as $tag->link.
So we can simplify it and always use $tag->link.
Trac ticket: https://core.trac.wordpress.org/ticket/64898
@SergeyBiryukov commented on PR #11303:
2 months ago
#4
Thanks for the PR! Merged in r62066.
@SergeyBiryukov commented on PR #11302:
2 months ago
#5
Thanks for the PR! Merged in r62086.
This ticket was mentioned in PR #11340 on WordPress/wordpress-develop by @Soean.
8 weeks ago
#6
This pull request makes minor code cleanups across several files, removing unnecessary uses of the sprintf function when localizing or outputting static strings. These changes simplify the code and improve readability without affecting functionality.
Introduced in:
- https://core.trac.wordpress.org/changeset/21804/trunk/wp-includes/class-wp-xmlrpc-server.php
- https://core.trac.wordpress.org/changeset/40330/trunk/src/wp-includes/class-wp-customize-widgets.php
- https://core.trac.wordpress.org/changeset/41774/trunk/src/wp-admin/plugin-editor.php
Trac ticket: https://core.trac.wordpress.org/ticket/64898
@SergeyBiryukov commented on PR #11340:
8 weeks ago
#8
Thanks for the PR! Merged in r62167.
This ticket was mentioned in PR #11331 on WordPress/wordpress-develop by @Soean.
7 weeks ago
#9
This pull request makes minor code simplifications by removing unnecessary ternary operations and directly assigning boolean expressions. These changes make the code easier to read and maintain, but do not alter the underlying logic.
Trac ticket: https://core.trac.wordpress.org/ticket/64898
@SergeyBiryukov commented on PR #11331:
7 weeks ago
#11
Thanks for the PR! Merged in r62173.
This ticket was mentioned in PR #11429 on WordPress/wordpress-develop by @Soean.
7 weeks ago
#12
The unused variable $hooked_blocks in WP_Block_Patterns_Registry->get_all_registered() has been removed.
Introduced in: https://core.trac.wordpress.org/changeset/56805/trunk/src/wp-includes/class-wp-block-patterns-registry.php
Unused since: https://core.trac.wordpress.org/changeset/59101/trunk/src/wp-includes/class-wp-block-patterns-registry.php
Trac ticket: https://core.trac.wordpress.org/ticket/64898
@Soean commented on PR #11429:
7 weeks ago
#13
Maybe we can use the PHPStan ticket: https://core.trac.wordpress.org/ticket/64898
@westonruter commented on PR #11429:
7 weeks ago
#15
This was committed by @SergeyBiryukov in r62201 (8510818).
This ticket was mentioned in PR #11692 on WordPress/wordpress-develop by @westonruter.
3 weeks ago
#16
- Keywords has-unit-tests added
tl;dr: Adds a PHPStan parser-node visitor that bridges WordPress core's @global Type $varname PHPDoc convention to PHPStan's variable type resolution, eliminating ~3,800 false-positive mixed errors without touching any production code.
I use a local PHPStan configuration at level 10. This causes PHPStan to complain a _lot_, including about the use of globals like $wpdb. For code like this:
I get two errors from PHPStan:
- phpstan: Cannot access property $site on mixed.
- phpstan: Part $wpdb->site (mixed) of encapsed string cannot be cast to string.
This is in spite of the fact that the method has:
and
The issue is that PHPStan doesn't recognize this use of @global. It's a WordPress-specific thing. It does recognize this, however:
/** @var wpdb $wpdb */
global $wpdb;
While we could fix the issues by going throughout core and adding these @var tags, this would be extremely noisy and be of very little value. Instead, we can introduce a PHPStan extension for core which causes PHPStan to treat the @global annotations as aliases for inline @var annotations. This is what is implemented by this PR.
# Approach by Claude
Adds a custom parser node visitor, WordPress\PHPStan\GlobalDocBlockVisitor, that:
- Walks each
FunctionLikenode and parses any@global Type $nametags from its docblock. - For every
global $name;statement inside that function body, if$namematches a documented tag, attaches a synthetic/** @var Type $name */doc comment to theglobalAST node. - PHPStan's existing
@var-on-global handling then assigns the documented type.
Behavior:
- Functions without
@globaltags are untouched; their globals continue to resolve asmixed. - Globals not listed in the function's
@globalblock are untouched; they continue to resolve asmixed. - Hand-written
@varannotations already present on aglobalstatement are respected and preserved. - Nested functions/closures get their own
@globalmap (visitor uses a stack).
The visitor is registered as a phpstan.parser.richParserNodeVisitor service in tests/phpstan/base.neon and autoloaded via a new autoload-dev PSR-4 entry in composer.json mapping WordPress\PHPStan\ to tests/phpstan/. composer install (which runs composer dump-autoload) makes the class available to PHPStan automatically.
# Result
When running composer -- phpstan --configuration=phpstan.neon.dist --level=10:
- Before:
[ERROR] Found 40069 errors - After:
[ERROR] Found 36300 errors
## Claude comparison
### Comparison summary
| Trunk | Branch | Diff | |
| ------------------------------------------- | ----: | -----: | --------: |
| Total errors (PHPStan totals) | 40069 | 36300 | -3769 |
| Unique errors (file+line+id+msg) | 39372 | 35705 | -3667 |
| Fixed by branch (in trunk, not branch) | — | — | 4456 |
| Introduced by branch (in branch, not trunk) | — | — | 789 |
The fixed-vs-introduced asymmetry exists because the visitor narrows $wpdb etc. from mixed to wpdb, which both removes errors (the mixed.method() family) and exposes new ones (real type mismatches in wpdb method signatures, @var array injections that PHPStan wants array<...> for, etc.).
### Top fixed identifiers
1375 method.nonObject -- $foo->method() on what was mixed 1040 property.nonObject -- $foo->prop on what was mixed 607 encapsedStringPart.nonString -- "FROM $wpdb->posts" interpolations 462 argument.type 304 offsetAccess.nonOffsetAccessible 188 binaryOp.invalid 126 foreach.nonIterable 119 return.type 64 cast.int 46 assignOp.invalid 39 property.notFound 32 method.notFound 21 offsetAccess.invalidOffset 15 assign.propertyType 6 preInc.type
### Top fixed messages
304 Cannot call method prepare() on mixed. 233 Cannot access property $posts on mixed. 188 Part $wpdb->posts (mixed) of encapsed string cannot be cast to string. 126 Argument of an invalid type mixed supplied for foreach, only iterables are supported. 111 Cannot access offset string on mixed. 110 Cannot call method query() on mixed. 108 Cannot call method get_results() on mixed. 100 Cannot call method get_var() on mixed. 82 Cannot access offset mixed on mixed. 75 Cannot access property $comments on mixed. 64 Cannot cast mixed to int. 64 Cannot call method get_col() on mixed. 59 Cannot call method update() on mixed. 53 Cannot access property $options on mixed. 52 Part $wpdb->comments (mixed) of encapsed string cannot be cast to string. 51 Cannot call method delete() on mixed. 44 Cannot access property $term_taxonomy on mixed. 41 Cannot call method esc_like() on mixed. 38 Cannot access property $postmeta on mixed. 38 Part $wpdb->options (mixed) of encapsed string cannot be cast to string. 27 Cannot access property $site on mixed. ← your original case
The 4456 fixed errors all stem from globals (mostly $wpdb, $wp_query, $wp_locale, $wp_filter, etc.) becoming concretely typed where @global tags exist. Nothing was suppressed via baseline; these are real PHPStan errors that the visitor now resolves.
Trac ticket: https://core.trac.wordpress.org/ticket/64898
## Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Opus 4.7
Used for: Research and code writing
@westonruter commented on PR #11692:
3 weeks ago
#17
cc @justlevine, @apermo, @SergeyBiryukov
@westonruter commented on PR #11692:
3 weeks ago
#18
cc @szepeviktor
@westonruter commented on PR #11692:
3 weeks ago
#19
With 9fc7599, the error count is now brought down by another _three_ to 36,297 (from 36,300).
@szepe.viktor commented on PR #11692:
3 weeks ago
#20
@westonruter Please do not kill my package.
@westonruter commented on PR #11692:
3 weeks ago
#21
@szepeviktor Not my intention! 😅
If anything, this new PHPStan extension would reduce the need for php-stubs/wordpress-stubs. But it's just here for core. It seems like adding such @global support would be useful in your extension for themes and plugins to leverage?
@westonruter commented on PR #11692:
3 weeks ago
#22
With 38f2bf2, the total error count is brought down by another dozen to 36,285 (from 36,297). The regex was overengineered.
@szepe.viktor commented on PR #11692:
3 weeks ago
#23
It seems like adding such
@globalsupport would be useful in your extension for themes and plugins to leverage?
No. Some day WordPress will use PHP standards.
@westonruter commented on PR #11692:
3 weeks ago
#24
No. Some day WordPress will use PHP standards.
But wouldn't that kill your package? 😏
@westonruter commented on PR #11692:
3 weeks ago
#26
Committed in r62292 (9e0b63d).
This pull request makes a small change to the
check_import_new_usersfunction, simplifying its logic to directly return the result of the permission check.Trac ticket: https://core.trac.wordpress.org/ticket/64898