Skip to content

PHPStan: Fix next_tag() string query false positives and quiet the stubs generator - #86109

Merged
westonruter merged 7 commits into
trunkfrom
update/phpstan-stubs-up-to-date-notice
Nov 3, 2026
Merged

westonruter merged 7 commits into
trunkfrom
update/phpstan-stubs-up-to-date-notice

Conversation

@westonruter

@westonruter westonruter commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

What?

See #86088, in particular #86088 (comment).

This removes the 27 false-positive argument.type errors (24 baseline entries) for passing a tag name to WP_HTML_Tag_Processor::next_tag(), such as next_tag( 'FIGURE' ), by generating the WordPress stubs from the core change that types $query. It also makes the stubs generator say when it has nothing to do, and keeps composer phpstan quiet about that.

Why?

Core documents the $query parameter of next_tag() as array|string|null, but the hash notation only describes the array form. When the stub generator turns that hash into a @phpstan-param array shape, it drops the string form, so every call that passes a bare tag name is reported. Core has no such errors, since its own analysis reads the @param type directly.

Separately, composer phpstan:generate-wordpress-stubs printed nothing at all when the stubs were already up to date, which looked like it had silently failed.

How?

  • HTML API: Improve PHPStan types for tag queries and tag names wordpress-develop#15305 adds explicit PHPStan types for tag queries to WP_HTML_Tag_Processor and WP_HTML_Processor, so the generator no longer has to derive a shape from the hash. It was committed in r65220, the stubs are regenerated from that commit on trunk, and the baseline drops the 24 next_tag() entries. The newer stubs also include r65161, which fixes the wp_tag_cloud() argument error in the Tag Cloud block, so that baseline entry is dropped too.
  • When the stubs are already generated from the recorded source, the generator now reports which source that is, and that --force generates them again.
  • A new --quiet option leaves that notice out. composer phpstan, which runs the generator before every analysis, passes it, so the notice only appears when the generator is run directly. Generating the stubs is still reported either way.

Testing Instructions

  1. Run composer phpstan:generate-wordpress-stubs. If the stubs need generating, they are generated. Run it again, and it reports that the stubs are already generated from WordPress/wordpress-develop@140b18225239, and exits with status 0.
  2. Run composer phpstan:generate-wordpress-stubs -- --force, and the stubs are generated again.
  3. Run composer phpstan. It does not print the notice, and PHPStan reports no errors.
  4. Confirm that tools/phpstan/baseline.neon no longer has entries for next_tag() being passed a string.

Testing Instructions for Keyboard

Not applicable, since this only changes development tooling.

Screenshots or screencast

Not applicable.

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5 (medium effort)
Used for: Implementing the generator notice and --quiet option, and writing this description. The changes were directed and reviewed by me, and the stubs and baseline were regenerated by me.

westonruter and others added 4 commits October 31, 2026 20:20
When the stubs are up to date with the recorded source, `composer phpstan:generate-wordpress-stubs` exited without any output, which looked like it did nothing. It now says which source the stubs were generated from, and that `--force` generates them again.

Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com>
Claude-Code-Session-Id: 2c14c65e-32a4-4332-8e55-c2d31a16a529
`composer phpstan` runs the generator before every analysis, so the notice that the stubs are already generated was printed on every run, where it is only noise. It is meant for running `composer phpstan:generate-wordpress-stubs` directly. With `--quiet`, which `composer phpstan` now passes, the notice is left out. Generating the stubs is still reported, since that takes a while and changes what gets analyzed.

Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com>
Claude-Code-Session-Id: 2c14c65e-32a4-4332-8e55-c2d31a16a529
@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

🤖 PR meta 🤖

Preview in WordPress Playground

🎉 Props

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: huzaifaalmesbah <huzaifaalmesbah@git.wordpress.org>
Co-authored-by: sirreal <jonsurrell@git.wordpress.org>

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


Props Bot commands

You can trigger Props Bot actions by commenting on this PR:

  • @propsbot add <username> to give props to a GitHub user. Requires write access.
  • @propsbot remove <username> to leave a user out of the props. Requires write access.
  • @propsbot refresh to refresh this list. Adding the props-bot label works too.

Updated as activity occurs, without notifying anyone named here. Add the props-bot label to refresh.

⚡ Performance

Show the results

Client side metrics exclude the server response time.

front-end-block-theme

Metric 187eabf trunk % Change
timeToFirstByte 35.65 ms +5.75% -7.15% 34.75 ms +7.77% -7.63% 2.59%
largestContentfulPaint 64 ms +6.25% -9.38% 60 ms +10% -3.33% 6.67%
lcpMinusTtfb 28.4 ms +8.98% -18.31% 25 ms +11.6% -5% 13.6%
wpBeforeTemplate 18.3 ms +8.42% -3.01% 17.71 ms +5.31% -5.08% 3.33%
wpTemplate 13.5 ms +11.26% -8.07% 13.11 ms +13.04% -5.11% 2.97%
wpTotal 32.6 ms +5.92% -6.93% 31.81 ms +6.29% -8.2% 2.48%
wpMemoryUsage 7.71 MB +0% -0% 7.67 MB +0% -0% 0.43%
wpDbQueries 16 +0% -0% 16 +0% -0% 0%

front-end-classic-theme

Metric 187eabf trunk % Change
timeToFirstByte 30.3 ms +6.77% -2.48% 30.1 ms +6.64% -5.81% 0.66%
largestContentfulPaint 68 ms +0% -2.94% 68 ms +2.94% -5.88% 0%
lcpMinusTtfb 36.95 ms +3.11% -4.6% 36.55 ms +5.61% -3.15% 1.09%
wpBeforeTemplate 16.41 ms +11.33% -2.01% 16.09 ms +10.38% -3.98% 1.99%
wpTemplate 10.66 ms +4.88% -4.03% 10.46 ms +8.99% -4.21% 1.91%
wpTotal 27.58 ms +8.05% -2.76% 27.39 ms +6.97% -6.1% 0.69%
wpMemoryUsage 6.40 MB +0% -0% 6.36 MB +0% -0% 0.53%
wpDbQueries 13 +0% -0% 13 +0% -0% 0%

media-processing

Metric 187eabf trunk % Change
mediaProcessingJpeg 220.46 ms +0.9% -2.24% 217.67 ms +2.66% -2.04% 1.28%
mediaProcessingAvif 3585.18 ms +0.74% -0.34% 3561.36 ms +0.68% -0.45% 0.67%
mediaProcessingJpegToAvif 2484.27 ms +0.53% -0.38% 2470.19 ms +1.02% -0.31% 0.57%

media-upload

Metric 187eabf trunk % Change
jpegUploadProcessing 1412.2 ms +0.25% -0.78% 1397.31 ms +0.64% -0.45% 1.07%
pngUploadProcessing 184.68 ms +9.49% -5.89% 175.86 ms +6.81% -5.04% 5.02%
largeJpegUploadProcessing 1420.28 ms +1.07% -0.59% 1393.82 ms +0.61% -0.3% 1.9%
multipleImageUploadProcessing 1475.09 ms +0.48% -0.69% 1454.46 ms +0.6% -0.52% 1.42%

post-editor

Metric 187eabf trunk % Change
serverResponse 391.37 ms +9.37% -6.08% 403.16 ms +3.85% -7.88% -2.92%
firstPaint 394.79 ms +26.26% -14.11% 379.89 ms +7.79% -21.11% 3.92%
domContentLoaded 868.45 ms +2.49% -1.77% 862.37 ms +1.75% -2.66% 0.71%
loaded 869.49 ms +2.46% -1.78% 863.45 ms +1.76% -2.68% 0.7%
firstContentfulPaint 499.44 ms +5.9% -1.62% 500.47 ms +4.69% -3.76% -0.21%
firstBlock 2163.66 ms +0.65% -0.64% 2152.75 ms +1.39% -0.71% 0.51%
type 18.83 ms +9.13% -8.23% 19.19 ms +0.99% -12.71% -1.88%
typeWithoutInspector 18.69 ms +1.77% -14.71% 18.02 ms +3.44% -6.27% 3.72%
typeWithTopToolbar 24.22 ms +3.47% -4.71% 23.93 ms +3.13% -2.26% 1.21%
typeContainer 8.82 ms +4.54% -7.37% 8.34 ms +19.3% -4.08% 5.76%
focus 121.73 ms +18.79% -4.77% 117.17 ms +1.01% -6.11% 3.89%
firstFocus 247.04 ms +0% -0% 261.86 ms +0% -0% -5.66%
selectAll 399.41 ms +0.71% -2.28% 408.97 ms +1.3% -2.31% -2.34%
undo 32.89 ms +3.37% -9.39% 33.48 ms +16.28% -6.48% -1.76%
listViewOpen 76.58 ms +7.9% -5.58% 76.88 ms +9.44% -3.73% -0.39%
inserterOpen 43.57 ms +1.86% -3.83% 42.52 ms +11.69% -8.04% 2.47%
inserterHover 11.76 ms +4.93% -10.63% 11.78 ms +6.28% -7.56% -0.17%
inserterSearch 8.97 ms +6.24% -3.79% 9.18 ms +7.52% -6.97% -2.29%
loadPatterns 654.06 ms +3.82% -5.05% 646.17 ms +3.53% -2.99% 1.22%
wpTotal 380.37 ms +9.32% -6.35% 391.83 ms +4.07% -8% -2.92%
wpMemoryUsage 14.75 MB +0% -0% 14.72 MB +0% -0% 0.24%
wpDbQueries 55 +0% -0% 55 +0% -0% 0%

site-editor

Metric 187eabf trunk % Change
serverResponse 257.56 ms +2.76% -6.76% 262.69 ms +2.63% -6.94% -1.95%
firstPaint 243.42 ms +15.6% -3.82% 262.92 ms +24.54% -3.02% -7.42%
domContentLoaded 591.42 ms +14.5% -2.42% 592.33 ms +3% -2.1% -0.15%
loaded 592.2 ms +14.53% -2.38% 593.15 ms +2.99% -2.11% -0.16%
firstContentfulPaint 345.8 ms +17.44% -3.33% 352.44 ms +2.84% -4.44% -1.88%
firstBlock 1707.96 ms +8.02% -1.13% 1737.59 ms +1.89% -0.82% -1.71%
type 13.84 ms +9.83% -4.62% 13.05 ms +5.36% -5.9% 6.05%
navigate 87.96 ms +11.32% -0.52% 91.65 ms +3.38% -11% -4.03%
loadPatterns 1038.78 ms +7.22% -10.11% 997.4 ms +5.86% -5.95% 4.15%
loadPages 959.92 ms +2.18% -2.04% 973.85 ms +2.28% -3.88% -1.43%
wpTotal 251.11 ms +2.88% -7.08% 255.98 ms +2.72% -7.17% -1.9%
wpMemoryUsage 12.77 MB +0% -0% 12.73 MB +0% -0% 0.27%
wpDbQueries 45 +0% -0% 45 +0% -0% 0%

a188b1b Run

🏁 Flaky tests

Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

The navigation text color should apply to all navigation links including submenu and overlay text in /test/e2e/specs/editor/blocks/navigation-colors.spec.js, passed after 1 failed attempt.
Error: apiRequestContext.fetch: socket hang up
Call log:
  - → GET http://localhost:8891/wp-json/wp/v2/pages?per_page=100&status=publish%2Cfuture%2Cdraft%2Cpending%2Cprivate%2Ctrash
    - user-agent: Playwright/1.63.0 (x64; ubuntu 24.04) node/24.20 CI/1
    - accept: */*
    - accept-encoding: gzip,deflate,br
    - X-WP-Nonce: 4b38c0b737
    - cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_da433b7faafd8180ebeb1624ceeeab7e=admin%7C1793864151%7Cl9z2MRzL1TCD9V7MbUZ5J6ja8ji9SLbc2pqiPY6Pmqp%7Cab43f3ca097a8b88f0065e92af6aad20d842074b52b66c012795a1ef2389be73; wp-settings-time-1=1793691422

    at RequestUtils.rest (/home/runner/work/gutenberg/gutenberg/packages/e2e-test-utils-playwright/src/request-utils/rest.ts:111:39)
    at RequestUtils.deleteAllPages (/home/runner/work/gutenberg/gutenberg/packages/e2e-test-utils-playwright/src/request-utils/pages.ts:44:27)
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/blocks/navigation-colors.spec.js:38:17
moves selected text within a paragraph in /test/e2e/specs/editor/various/draggable-blocks.spec.js, passed after 1 failed attempt.
Error: expect(received).toMatchObject(expected)

- Expected  - 1
+ Received  + 1

  Array [
    Object {
      "attributes": Object {
-       "content": "second First third",
+       "content": "First second third",
      },
      "name": "core/paragraph",
    },
  ]

Call Log:
- Timeout 5000ms exceeded while waiting on the predicate
    at /home/runner/work/gutenberg/gutenberg/test/e2e/specs/editor/various/draggable-blocks.spec.js:1209:41

a188b1b Run

westonruter and others added 2 commits November 2, 2026 23:04
The typing of HTML API tag queries and tag names is now committed to core in r65220, so the stubs are generated from that trunk commit instead of from the pull request. The baseline no longer has the `wp_tag_cloud()` argument error, which the newer stubs resolve.

Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com>
Claude-Code-Session-Id: 2c14c65e-32a4-4332-8e55-c2d31a16a529
@westonruter
westonruter marked this pull request as ready for review November 3, 2026 06:14

@sirreal sirreal left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks!

@huzaifaalmesbah huzaifaalmesbah left a comment •

Copy link
Copy Markdown
Member

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 left one optional nit for the alignment of the --commit line in the usage text, which shouldn't block merging.

I tested it in Docker (PHP 8.5.12, Composer 2.11.1, PHPStan 2.3.4), using dependencies installed without a lock file and PHP files from an existing local build:

  • With no stubs, composer phpstan:generate-wordpress-stubs generates them from WordPress/wordpress-develop@140b18225239 (r65220).
  • Running it again reports that they are already generated, and exits with status 0.
  • With --quiet, the generator prints nothing and exits with status 0.
  • The notice goes to standard error, so standard output stays empty.
  • -- --force generates the stubs again.
  • composer phpstan does not print the notice, and reports no errors. Since reportUnmatchedIgnoredErrors is on, that also confirms that the baseline has no stale entries.

I also confirmed that the baseline drops 25 entries: 24 for next_tag(), covering 27 errors, and 1 for wp_tag_cloud().

AI Review: Claude Opus 5.5

Co-authored-by: huzaifaalmesbah <huzaifaalmesbah@git.wordpress.org>
@westonruter
westonruter merged commit 299c5ec into trunk Nov 3, 2026
80 checks passed
@westonruter
westonruter deleted the update/phpstan-stubs-up-to-date-notice branch November 3, 2026 07:53
@github-actions github-actions Bot added this to the Gutenberg 24.4 milestone Nov 3, 2026
@ingeniumed ingeniumed added [Type] Build Tooling Issues or PRs related to build tooling and removed [Type] Code Quality Issues or PRs that relate to code quality labels Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Build Tooling Issues or PRs related to build tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants