Skip to content

Docs: Add class-level PHPStan annotations - #13891

Open
swissspidy wants to merge 4 commits into
WordPress:trunkfrom
swissspidy:fix/phpstan-class-annotations
Open

swissspidy wants to merge 4 commits into
WordPress:trunkfrom
swissspidy:fix/phpstan-class-annotations

Conversation

@swissspidy

@swissspidy swissspidy commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Split out of #13530, as proposed in this comment (subset 4).

  • WP_Theme: @phpstan-property-read for the 14 magic properties that __get() serves.
  • WP_Query: @phpstan-property-read for $query_vars_changed and $query_vars_hash, and @phpstan-method for init_query_flags(). All three are private and are reached through the magic methods.
  • WP_Block_List: @phpstan-implements ArrayAccess<int, WP_Block>. offsetSet()'s canonical @param now documents the null offset it handles for appending.
  • WP_Widget::update_callback() and ::form_callback(): @final. Their documentation already says they are not to be overridden.

Changes from #13530

These follow the review analysis:

  • The WP_Theme properties now include false wherever the underlying method can return it:
    • name, title, version, description and author come from WP_Theme::get() or ::display().
    • parent_theme comes from the parent theme's get( 'Name' ).
    • screenshot comes from ::get_screenshot().
    • tags is string[]|false rather than list<string>, because array_filter() keeps the keys.
  • @final is dropped from display_callback(). At least one popular plugin overrides it, and its documentation doesn't say it shouldn't be.
  • The standalone @phpstan-return void tags on WP_Block_List::offsetSet() and ::offsetUnset() are dropped.

Changes after review

  • WP_Theme::$parent_theme is string|false, like $name, which has the same source.
  • The @phpstan-param int $offset and @phpstan-return WP_Block|null tags on the WP_Block_List offset methods are dropped, since they repeated the canonical tags. For offsetSet(), the canonical @param is corrected to int|null instead.

Effect on the analysis

composer run phpstan passes. The property.notFound and property.private baselines lose their WP_Theme and WP_Query entries. At level 10, compared against trunk, 27 errors are fixed and 4 are introduced. The 4 are in WP_Debug_Data, which passes the theme's name, version and author, now typed string|false, to functions that expect a string.

Trac ticket: https://core.trac.wordpress.org/ticket/65817

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: Splitting #13530 by tag kind, applying the corrections from the review analysis on #13530 and from review on this PR, checking each subset with composer run phpstan (also at level 10, compared against trunk) and phpcs, and drafting the commit messages and this description. Reviewed by me.


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

🤖 Generated with Claude Code

https://claude.ai/code/session_015BuoHZQvJMvPEYp4Sfjgvd

Documents the magic properties of `WP_Theme` and `WP_Query` with `@phpstan-property-read`, along with `WP_Query::init_query_flags()` with `@phpstan-method`, and the element type of `WP_Block_List` with `@phpstan-implements ArrayAccess<int, WP_Block>`.

The `WP_Theme` properties that come from `WP_Theme::get()`, `::display()` or `::get_screenshot()` include `false`, as those methods do.

Marks `WP_Widget::update_callback()` and `::form_callback()` as `@final`, as their documentation says they are not to be overridden.

See #65817.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VieGtSQtUoVfHiGwTmkvtc
Copilot AI balanced review requested due to automatic review settings October 1, 2026 09:01
@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

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.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @claude.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

Core Committers: Use this line as a base for the props when committing in SVN:

Props swissspidy, westonruter.

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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

The annotations match the documented runtime behavior, and the related baseline removals are consistent.

Review effort: Balanced
Findings: None

What changed in this PR

Adds accurate PHPStan metadata for magic APIs, block array access, and non-overridable widget callbacks while removing obsolete baseline suppressions.

Changes:

  • Documents magic WP_Theme and WP_Query members.
  • Types WP_Block_List array access.
  • Marks widget callbacks final for static analysis.
File Description
src/​wp-includes/​class-wp-block-list.php Adds generic ArrayAccess types.
src/​wp-includes/​class-wp-query.php Documents magic private members.
src/​wp-includes/​class-wp-theme.php Types magic read-only properties.
src/​wp-includes/​class-wp-widget.php Marks non-overridable callbacks.
tests/​phpstan/​baselines/​property.notFound.neon Removes resolved property suppressions.
tests/​phpstan/​baselines/​property.private.neon Removes resolved visibility suppressions.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

Copy link
Copy Markdown
Member Author

🤖 Comment by Claude Opus 5.5

Props for this subset, gathered from the full history of functionMap.php in php-stubs/wordpress-stubs. A change counts only where it introduced or changed the specific tag this PR carries, not just any change to the function's map entry. Purely mechanical changes are left out: tag key renames (php-stubs/wordpress-stubs#420), parameter renames (php-stubs/wordpress-stubs#115), coding standards (php-stubs/wordpress-stubs#119) and the duplicate-code refactor (php-stubs/wordpress-stubs#85).

Stubs change Author Entries
php-stubs/wordpress-stubs#66 @swissspidy WP_Block_List, WP_Block_List::offsetExists(), WP_Block_List::offsetGet(), WP_Block_List::offsetSet(), WP_Block_List::offsetUnset()
php-stubs/wordpress-stubs#216 @IanDelMar WP_Theme
php-stubs/wordpress-stubs#220 @IanDelMar WP_Query
php-stubs/wordpress-stubs#426 @IanDelMar WP_Widget::form_callback(), WP_Widget::update_callback()

Props for this PR (swissspidy for the split, westonruter for the review that shaped it):

swissspidy, westonruter, marian1

Generated by Claude Code

claude added 2 commits October 5, 2026 15:46
Type WP_Theme::$parent_theme as string|false, since it comes from the parent theme's Name header, the same source as $name. Drop the @phpstan tags in WP_Block_List that repeat the canonical tags, and document the null offset of offsetSet() in the canonical @PARAM instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015BuoHZQvJMvPEYp4Sfjgvd
@swissspidy
swissspidy requested a review from westonruter October 7, 2026 11:56
Comment thread src/wp-includes/class-wp-query.php Outdated
Comment thread src/wp-includes/class-wp-theme.php Outdated
Use `@property-read` for the `WP_Theme` magic properties, as `WP_Comment` does, and align the property names. Type `WP_Query::$query_vars_hash` as `false|(lowercase-string&non-falsy-string)`.

See #65817.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3XYNUvB9sQNDXA14uJQeH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants