Repository navigation
Build/Test Tools: Update PHPStan to 2.3.5 and document --fix - #15479
westonruter wants to merge 5 commits into
Conversation
The analysis of `phpstan.neon.dist` reports no errors with this release, and no baseline entry goes stale, so the baselines are unchanged. The phpstan-phpunit and phpstan-strict-rules extensions are already at their latest versions (2.1.1 each). The headline feature of 2.3.5 is `--fix`, which also removes stale `ignoreErrors` entries and `@phpstan-ignore` comments. Its adoption in the docs and CI follows separately. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tnky3GdCg3QL5KeMvuQvwf Claude-Code-Session-Id: 5bac4eea-faaa-40e6-8440-b696b7773ba6
PHPStan 2.3.5 can fix stale ignores itself: `--fix` lowers a baseline entry's count that is now too high, removes an entry that matches nothing, and removes an `@phpstan-ignore` comment that no longer ignores anything. That is quicker than regenerating the baselines, since it reuses the result cache, and unlike regenerating it also clears stale inline ignores, which before had to be removed by hand. Verified against the per-identifier baselines: an inflated count was lowered back to its real value, and removing the last entry of a baseline left that file in place as `ignoreErrors: []`. Regenerating that one identifier then deleted the file and its `includes` entry. A run limited to some paths reports no stale ignores at all, so `--fix` has to be run on the whole tree. The README gains a section describing this, its caveats, and `--fix-ignored`. The CI step summary, the error annotation, and the pull request comment now suggest `--fix` first, with regenerating as the alternative that also retires an emptied baseline. Annotations of errors that PHPStan reports as fixable, which its JSON output now flags, also say how to fix them. That flag is left out of the results passed to the comment workflow, as tips are. A comment about errors not specific to a file is corrected too: since 2.3.5, an unmatched `ignoreErrors` entry without a path is reported against the config file it is in. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tnky3GdCg3QL5KeMvuQvwf Claude-Code-Session-Id: 5bac4eea-faaa-40e6-8440-b696b7773ba6
Test using WordPress PlaygroundThe 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
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
…rator. Running PHPStan with `--fix` removes the entries of fixed errors from a baseline in place, but when it removes the last one it leaves the file behind as `ignoreErrors: []`, with its `includes` entry in `phpstan.neon.dist`. Only regenerating that identifier deleted it, which reruns the whole analysis just to find that nothing is left. `composer phpstan:baselines -- --prune` analyzes nothing. It deletes each per-identifier baseline that lists no entries, whether as an empty inline list or a key with nothing nested under it, and rewrites the list between the `# phpstan:baselines` markers to match. With `--identifier`, only those baselines are considered. A file without an `ignoreErrors` key is left alone with a warning, and `--combined` is rejected, since it writes nothing. Only whole-line comments are skipped when reading a baseline, since a message pattern such as `'#^…$#'` contains `#`. `read_file()` now takes a `non-empty-string` path, as returned by `find_baselines()`, since nothing in it needs the path to be non-falsy. The README and the CI step summary now say to prune after `--fix` empties a baseline, rather than to regenerate it. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tnky3GdCg3QL5KeMvuQvwf Claude-Code-Session-Id: 5bac4eea-faaa-40e6-8440-b696b7773ba6
…selines. Fixing a baselined error meant running `composer phpstan -- --fix`, then `composer phpstan:baselines -- --prune` for any baseline it emptied. Leaving out the `--` makes Composer discard the flag silently, so the analysis just reports the stale entries again. `composer phpstan:fix` (and `npm run typecheck:php:fix`) chains three steps, each run only when the one before it succeeds: * PHPStan with `--fix`, which lowers or removes the stale entries. * `composer phpstan:baselines -- --prune`, which deletes any baseline left with no entries, along with its `includes` entry. * The analysis once more, since PHPStan's `--fix` reports only what it fixed, and succeeds even when other errors remain. It reuses the result cache, so it is quick. Both analyses use `phpstan.neon.dist`, whatever a local `phpstan.neon` says. A configuration at another rule level can report a baselined error with a different message, and `--fix` then removes entries the default configuration still needs. That happened when this was tried against a local level 10 configuration with bleeding edge, which removed entries from five baselines. When nothing is fixable, PHPStan exits with 1 and stops the chain, which the README notes. The README, the CI step summary, the annotation of fixable errors, and the pull request comment now point to the new scripts. Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tnky3GdCg3QL5KeMvuQvwf Claude-Code-Session-Id: 5bac4eea-faaa-40e6-8440-b696b7773ba6
|
cc @apermo |
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. Props Bot commandsYou can trigger Props Bot actions by commenting on this PR:
|
Updates PHPStan from 2.3.4 to 2.3.5, and adds
composer phpstan:fix(andnpm run typecheck:php:fix), which uses its new--fixoption to update the baselines after fixing a baselined error.The phpstan-phpunit and phpstan-strict-rules extensions are already at their latest versions (2.1.1 each). With 2.3.5, the analysis of
phpstan.neon.distreports no errors and no stale baseline entries, so the baselines are unchanged.--fixfor stale ignoresPHPStan 2.3.5 marks errors it can fix itself with 🔧, and these include stale ignores. With
--fix, it lowers a baseline entry's count that is now too high, removes an entry that matches nothing, and removes an@phpstan-ignorecomment that no longer ignores anything. That is quicker thancomposer phpstan:baselines, since it reuses the result cache. Unlike regenerating, it also clears stale inline ignores, which the CI messages previously said had to be removed by hand.Verified against the per-identifier baselines:
ignoreErrors: [], still listed in theincludesofphpstan.neon.dist.--fixhas to be run on the whole tree.--fix, PHPStan reports only what it fixed, and exits with 0 when every fixable error was fixed, even when other errors remain. It exits with 1 when nothing was fixable.phpstan.neonat level 10 with bleeding edge,--fixremoved entries from five baselines thatphpstan.neon.diststill needs, because that configuration reports those errors with different messages.composer phpstan:fixand--prunecomposer phpstan:fixchains three steps, each run only when the one before it succeeds:phpstan analyse --configuration=phpstan.neon.dist --fix, which updates the baselines in place.composer phpstan:baselines -- --prune, a new option of the baseline generator which analyzes nothing. It deletes each baseline that lists no entries, and rewrites the list between the# phpstan:baselinesmarkers to match. It respects--identifierand--output-dir.phpstan analyse --configuration=phpstan.neon.dist, since--fixreports only what it fixed. It reuses the result cache, so it is quick, and it is what makes the script fail when errors remain.Both analyses name
phpstan.neon.dist, whatever a localphpstan.neonsays, given the last finding above. The scripts also avoid the--thatcomposer phpstan -- --fixneeds, which Composer otherwise discards silently along with the flag. When nothing is fixable, PHPStan's exit status of 1 stops the chain after the first step, which the README notes.Changes
tests/phpstan/README.mdgains a section, "Removing stale entries with--fix", covering the above, the fact that--fixapplies every fixable error the run reports, and--fix-ignored.tests/phpstan/generate-baselines.phpgains the--pruneoption.::errorannotation, the annotation of fixable errors, and the pull request comment now point tocomposer phpstan:fix(ornpm run typecheck:php:fix), with regenerating as the alternative.ignoreErrorsentry without a path is reported against the config file it is in, rather than as an error not specific to a file.Not adopted
base.neon: this only works when PHPStan runs on PHP 8.0+, and core's tooling still supports 7.4. The comments documenting each service inbase.neonare also worth keeping.--fix.Trac ticket: Core-65817
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5 (medium effort)
Used for: Researching the 2.3.5 changes, testing
--fixagainst the baselines, and writing the version bump, documentation, and workflow changes, all 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.