Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
3613 commits
Select commit Hold shift + click to select a range
145249e
Add exceptional case for DateInterval::format return type inference
adamturcsan Oct 15, 2025
0e066c4
Fix build
staabm Feb 6, 2026
a492601
Fix return type of pcntl_signal_get_handler
marc-mabe Nov 10, 2025
386da24
Comparison with strtolower() etc. leads lower/upper-case-string (#4857)
staabm Feb 7, 2026
e85dc34
Support int range in bitwise operations (#4435)
VincentLanglet Feb 8, 2026
d56b82b
More precise `hrtime()` return type (#4353)
takaram Feb 9, 2026
9eb30a6
Update dependency phpunit/phpunit to v11.5.52
renovate[bot] Feb 9, 2026
ee0c447
Update dependency phpunit/phpunit to v9.6.34
renovate[bot] Feb 9, 2026
a15babc
Fix get defined vars return type (#4632)
VincentLanglet Feb 9, 2026
ee071c0
Update PHPUnit
ondrejmirtes Feb 9, 2026
b8fd9a0
Resolve template with value of BackedEnum
VincentLanglet Feb 9, 2026
4b55cbd
Update polyfill packages
ondrejmirtes Feb 9, 2026
a63e97c
MutatingScope: prevent unnecessary scope re-creation after openssl* c…
staabm Feb 9, 2026
cea927d
Update issue-bot
renovate[bot] Feb 9, 2026
d298e69
SplObjectStorage iterates over objects (#4789)
staabm Feb 9, 2026
73e1c8e
Narrow string type when `ctype_*` functions return true
takaram Nov 23, 2025
55d0fd7
Remove extra `dba_fetch` variant in PHP 8.3 functionMap
ondrejmirtes Feb 9, 2026
e0687d0
Constant's `isDeprecated()` depends on `Scope::getPhpVersion()`
staabm Feb 9, 2026
748ad67
Fix get_object_vars() return type
Triplkrypl Feb 9, 2026
a5c375d
Refactor ComposerPhpVersionFactory
staabm Dec 15, 2025
d07af42
Restrict chr param for PHP 8.5+
VincentLanglet Dec 27, 2025
5b85fc7
Introduce `__stringnotstringable` (#4457)
VincentLanglet Feb 9, 2026
c33cfea
FileFinder - sort files before returning
ondrejmirtes Feb 9, 2026
6a57243
Respect sys_get_temp_dir() from the parent process
dktapps Feb 9, 2026
296dfee
add new rule for filter_var
canvural Nov 13, 2025
954d68f
Add default value for getAttribute call in ContinueBreakInLoopRule
canvural Feb 9, 2026
afa1e2d
Add ArrayCombineFunctionThrowTypeExtension (#4414)
VincentLanglet Feb 9, 2026
eb4e247
Refactor InitializerExprTypeResolver (#4861)
staabm Feb 9, 2026
48301e6
Infer non-empty-array after array_key_first/last() (#4536)
staabm Feb 10, 2026
62fd66e
Fix strtr inferences (#4466)
VincentLanglet Feb 10, 2026
a5410fc
Do not degrade closures in array shapes
staabm Feb 10, 2026
0c59cc7
Fix ignore comment handling for multiple traits in a single file
takaram Feb 10, 2026
13a2f02
Do not degrade array-shapes in PHPDocs
staabm Feb 10, 2026
ba8fae8
Introduce `@phpstan-all-methods-(im)pure`
VincentLanglet Feb 10, 2026
a4b3955
Fix build
ondrejmirtes Feb 10, 2026
c7ad25b
Do not report do-while-false pseudo-loops that are interrupted by a b…
claudepache Feb 10, 2026
2a92c7b
Defer invalidating expressions after all args are processed
ondrejmirtes Feb 10, 2026
996ad98
Defer by-ref closure scope modifications after all args are processed
ondrejmirtes Feb 10, 2026
e9d98e5
Faster way of running tests
ondrejmirtes Feb 10, 2026
2512510
Added `make infection` command to run it locally (#4524)
staabm Feb 11, 2026
97288da
Bleeding edge - Require generics for Iterator, IteratorAggregate, Gen…
Flyingmana Feb 11, 2026
7850b66
Don't lose known offset-types in `array_replace()`
staabm Feb 11, 2026
c584747
Introduce `reportNonIntStringArrayKey` parameter
VincentLanglet Feb 11, 2026
3a06311
Add PHPDoc documentation to Type, Scope, and Reflection interfaces
ondrejmirtes Feb 11, 2026
1f016a3
Made closures php-src cachable
staabm Feb 11, 2026
43d5026
PHPDoc tag `@api-do-not-implement` instead of list in BcUncoveredInte…
ondrejmirtes Feb 11, 2026
3103b88
VoidToNullTraverser: Intersections cannot contain void
staabm Feb 11, 2026
349b1ad
Prevent unnecessary type-traversal
staabm Feb 11, 2026
5930232
Use named arguments for unreadable calls
claude Feb 11, 2026
707fbe1
Update PHPStan packages
ondrejmirtes Feb 11, 2026
f2015d4
Fix GMP::toNumber (#4867)
VincentLanglet Feb 11, 2026
c37bc22
Fix phpstan build on PHP 7.4 (#4870)
VincentLanglet Feb 11, 2026
124af5f
Respect original variable type when using extract on optional keys (#…
VincentLanglet Feb 11, 2026
c72d43a
Extract FileAnalyserCallback (#4872)
staabm Feb 11, 2026
8c1d275
Infer non-empty-ness after count($a) == count($b) (#4470)
staabm Feb 11, 2026
fa873f9
Add Claude Easy Fixes workflow for automated bug fixing (#4875)
ondrejmirtes Feb 12, 2026
d3ee397
Fix workflow crash: use Claude Code CLI instead of claude-code-action
claude Feb 12, 2026
31b577d
Update claude-easy-fixes workflow to use phpstan-bot and peter-evans …
claude Feb 12, 2026
136ca97
Remove setup-node
ondrejmirtes Feb 12, 2026
bf2a9c3
Stream Claude output
ondrejmirtes Feb 12, 2026
55b473a
When using --print, --output-format=stream-json requires --verbose
ondrejmirtes Feb 12, 2026
107bb2c
Supervision is not feasible in CI
ondrejmirtes Feb 12, 2026
363bcfd
Parallelize claude-easy-fixes workflow
claude Feb 12, 2026
f43cee6
Remove base64 encoding from issue body in matrix
claude Feb 12, 2026
54f053a
Fix #13211
ondrejmirtes Feb 12, 2026
15db31f
Update claude-easy-fixes.yml
ondrejmirtes Feb 12, 2026
6b63691
Paginate GitHub API to fetch all Easy fixes issues
claude Feb 12, 2026
239c64c
Fix #12875
ondrejmirtes Feb 12, 2026
8dca4e2
Fix #13783
ondrejmirtes Feb 12, 2026
cc71563
Fix #11470
ondrejmirtes Feb 12, 2026
51c6e4b
Fix #5191
ondrejmirtes Feb 12, 2026
434d287
Skill for regression tests
ondrejmirtes Feb 12, 2026
54f39f8
Add regression tests for variable.undefined false positives in match …
ondrejmirtes Feb 12, 2026
73e746b
Fix CS
ondrejmirtes Feb 12, 2026
19f01ad
Fix #10671
ondrejmirtes Feb 12, 2026
36f54d9
Fix build (#4892)
staabm Feb 12, 2026
4b85b04
Fix #4865
ondrejmirtes Feb 12, 2026
a2af4ec
Improve claude-easy-fixes workflow with detailed commit messages and …
claude Feb 12, 2026
fb48001
Loadable classes not recognized since 2.1.34 release (#4891)
staabm Feb 12, 2026
f387269
Fix invokable objects incorrectly labeled as instances of `Closure` (…
HypeMC Feb 12, 2026
e9b6850
Use OAuth token instead of API key in claude-easy-fixes workflow
ondrejmirtes Feb 12, 2026
501721f
Add Claude regression tests workflow and commit step to regression-te…
ondrejmirtes Feb 12, 2026
3daa312
Fix #13303
ondrejmirtes Feb 12, 2026
8d1ac85
Update src/Analyser/NodeScopeResolver.php
ondrejmirtes Feb 12, 2026
1cfb397
Improve regression-tests workflow
ondrejmirtes Feb 12, 2026
68d630c
Add regression test for #11903
phpstan-bot Feb 12, 2026
9f86e84
Add regression test for #7008
phpstan-bot Feb 12, 2026
2e73983
No need to be verbose
ondrejmirtes Feb 12, 2026
b0b3ad1
Update PR description with Closes lines after adding regression tests
ondrejmirtes Feb 12, 2026
7912480
Improve workflow
ondrejmirtes Feb 12, 2026
a073d45
Preserve HasOffsetValueType for constant array spreads in degraded ar…
ondrejmirtes Feb 12, 2026
f375a45
Add regression test for #13805
phpstan-bot Feb 12, 2026
16c632f
Don't invalidate private property expressions of different classes
ondrejmirtes Feb 12, 2026
8a619a5
Add regression test for #6623
phpstan-bot Feb 12, 2026
2f03f56
Fix match exhaustiveness for class-string with union of final classes
ondrejmirtes Feb 12, 2026
8354ecb
Add regression test for #12998
phpstan-bot Feb 12, 2026
65f5d94
Allow passing return values of by-reference functions/methods as by-r…
ondrejmirtes Feb 12, 2026
c5a9df5
Add regression test for #13711
phpstan-bot Feb 12, 2026
1f6cf23
Use REST API instead of GraphQL for PR description update
ondrejmirtes Feb 12, 2026
c39f3ec
Fix build
staabm Feb 12, 2026
526854a
claude-easy-fixes - do not cause name collision
ondrejmirtes Feb 12, 2026
9156e51
Fix build
staabm Feb 12, 2026
685ae14
Add backward compatibility promise section to CLAUDE.md
ondrejmirtes Feb 12, 2026
23ee1cf
Fix build
staabm Feb 12, 2026
5d52bba
Update CallMethodsRuleTest.php
staabm Feb 12, 2026
e30d1e5
Downgrade $this to static when calling methods on static type
ondrejmirtes Feb 12, 2026
1bd832f
Fix @phpstan-assert not working with union types
ondrejmirtes Feb 12, 2026
0da93b4
Add regression test for #13358
phpstan-bot Feb 12, 2026
24de99b
Fix #12222
ondrejmirtes Feb 12, 2026
59cfcd4
Deduplicate easy-fix workflow prompt with regression-test skill
ondrejmirtes Feb 12, 2026
944077a
Extract reusable fix-issue workflow and add milestone trigger
ondrejmirtes Feb 12, 2026
f0ebf57
Move workflow
ondrejmirtes Feb 12, 2026
30fcad1
Fix reusable workflow
ondrejmirtes Feb 12, 2026
5a5fa9f
Rename workflow
ondrejmirtes Feb 12, 2026
9fa2499
Add workflow_dispatch trigger to Claude Fix Issue workflow
ondrejmirtes Feb 12, 2026
dd0ab39
Revert "Respect sys_get_temp_dir() from the parent process"
ondrejmirtes Feb 12, 2026
aaaba11
Fix incorrect type with spread of array with optional named keys
ondrejmirtes Feb 12, 2026
76ac8e0
Workflow for Claude to fix failing CI in its pull requests
ondrejmirtes Feb 12, 2026
4c7aa46
Fix array_count_values key type for general string input
ondrejmirtes Feb 12, 2026
1470227
Fix CI failures [claude-ci-fix]
phpstan-bot Feb 12, 2026
a0f4e0c
Fix workflow_dispatch issue number being converted to float
claude Feb 13, 2026
4fc4e50
Fix ternary type narrowing in assert and truthy contexts
ondrejmirtes Feb 13, 2026
2183ed7
Fix CI failures [claude-ci-fix]
phpstan-bot Feb 13, 2026
7693f5b
Improve array_count_values
ondrejmirtes Feb 13, 2026
920e47f
Revert "Improve array_count_values"
ondrejmirtes Feb 13, 2026
adb86c4
Revert "Fix array_count_values key type for general string input"
ondrejmirtes Feb 13, 2026
575a5bb
Prepare 2.2.x
ondrejmirtes Feb 13, 2026
30c231a
Open 2.2.x
ondrejmirtes Feb 13, 2026
e2cb077
Update merge-maintained-branch workflow
ondrejmirtes Feb 13, 2026
fe8c9bb
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 13, 2026
2522eae
Test a change
ondrejmirtes Feb 13, 2026
57f27b6
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 13, 2026
6ccffab
Close issues on merge workflow
ondrejmirtes Feb 13, 2026
313ebe5
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 13, 2026
af658f3
Revert "Test a change"
ondrejmirtes Feb 13, 2026
1718ecc
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 13, 2026
df68192
Fix merging workflow
ondrejmirtes Feb 13, 2026
0006215
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 13, 2026
38fb314
Test a change
ondrejmirtes Feb 13, 2026
1272139
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 13, 2026
df91618
Faster NetteContainer
staabm Feb 13, 2026
5add2a9
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 13, 2026
e3ea780
MutatingScope: prevent unnecessary work in removeTypeFromExpression()
staabm Feb 13, 2026
e4e435b
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 13, 2026
ac46a7f
Stop ignoring offsetAccess.invalidOffset (#4871)
VincentLanglet Feb 13, 2026
bd31d25
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 13, 2026
e2067b2
Don't invalidate container cache on user-interactions in the shell
staabm Feb 14, 2026
19447f1
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 14, 2026
aa18181
Make sure invocations via blackfire use the same container
staabm Feb 14, 2026
0d1f531
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 14, 2026
f0fc378
Use pull_request_target for close-issues workflow to support fork PRs
ondrejmirtes Feb 14, 2026
b7d3172
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 14, 2026
25b268b
Add agentic workflow to document new config parameters
ondrejmirtes Feb 14, 2026
547f128
Add gh-aw infrastructure files
ondrejmirtes Feb 14, 2026
080bafa
Fix manual dispatch to check all parameters, not just diff
ondrejmirtes Feb 14, 2026
2a5eaba
Skip level-only parameters in config docs workflow
ondrejmirtes Feb 14, 2026
3bb4431
Fix cross-repo patch by pre-fetching config-reference.md
ondrejmirtes Feb 14, 2026
afa5966
Fix git identity for pre-step commit on CI runner
ondrejmirtes Feb 14, 2026
97f58a0
Use direct checkout and bash PR creation instead of safe-outputs
ondrejmirtes Feb 14, 2026
da9ed28
Add main repo checkout so gh-aw git config step works
ondrejmirtes Feb 14, 2026
5c6e070
Correct username
ondrejmirtes Feb 14, 2026
5abeb3c
Instruct agent to extract nested parameters from schema
ondrejmirtes Feb 14, 2026
8ac3a91
Prevent duplicate path normalization (#4931)
staabm Feb 14, 2026
a712fce
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 14, 2026
200a203
DependencyResolver: Reduce duplicate work
staabm Feb 14, 2026
f9efbdc
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 14, 2026
0b4157d
Fix `@phpstan-assert` not working correctly with union types (#4920)
staabm Feb 15, 2026
34a77ac
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 15, 2026
4de1cdc
Fix #13809: `list<mixed>` becomes `array<int<0, max>, mixed>` without…
phpstan-bot Feb 15, 2026
8263f6a
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 15, 2026
a44d54e
Add more foreach with by-ref $value tests (#4934)
staabm Feb 15, 2026
4512e57
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 15, 2026
d9b9af7
Introduce rawMessages key in ignoreErrors (#4929)
VincentLanglet Feb 15, 2026
450cf52
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 15, 2026
cb4b834
Add workflow for Claude to react to PR comments and reviews
ondrejmirtes Feb 16, 2026
5ae8cfd
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 16, 2026
b43a04b
Fix Claude PR reactions workflow: don't cancel in-progress runs
ondrejmirtes Feb 16, 2026
c6a65ac
Remove --max-turns 50 from Claude PR reactions workflow
claude Feb 16, 2026
cbba989
Merge remote-tracking branch 'origin/2.1.x' into 2.2.x
ondrejmirtes Feb 16, 2026
5557c78
Improve count on list with greater/smaller-than (#4507)
staabm Feb 16, 2026
411c411
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 16, 2026
47923ed
Allow to dump more than one thing (#4941)
VincentLanglet Feb 16, 2026
8b39a71
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 16, 2026
d145799
Improve Claude react workflow
ondrejmirtes Feb 16, 2026
7c6309c
Configure phpstan-bot git identity for Claude PR reactions workflow
ondrejmirtes Feb 16, 2026
c476b60
Split claude react-on-comment into two jobs to avoid expensive setup
claude Feb 16, 2026
cee7127
Add param-out for getmxrr (#4943)
VincentLanglet Feb 16, 2026
f554b84
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 16, 2026
0f994d4
speed up TrinaryLogic
kaja47 Feb 16, 2026
37c4f55
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 16, 2026
394461f
Fix Claude credentials to phpstan-bot
ondrejmirtes Feb 16, 2026
5ee32f8
Fix Claude fix CI workflow checking for attempts count
ondrejmirtes Feb 16, 2026
1297915
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 16, 2026
4285599
Cleanup CLAUDE.md
ondrejmirtes Feb 16, 2026
0c27812
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 16, 2026
ebc5354
Fix array + array inference (#4944)
VincentLanglet Feb 16, 2026
0998ee8
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 16, 2026
72f877f
Add scheduled workflow to trigger Claude easy fixes nightly
ondrejmirtes Feb 16, 2026
106fc93
Cleanup ConstantArrayTypeBuilder (#4955)
staabm Feb 16, 2026
c2da2e8
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 16, 2026
0c2ab3b
Add sodium_crypto_secretbox_keygen function stub (#4954)
thePanz Feb 17, 2026
a7a7abc
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 17, 2026
40b3f24
Fix BcMath\Number increment/decrement (#4957)
mpesari Feb 17, 2026
8e131a9
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 17, 2026
2ea33ca
Fix #9820: Method call phpstan error is reported on wrong line (#4967)
phpstan-bot Feb 17, 2026
20243ca
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 17, 2026
88b41d4
Fix TypeError dead catch when assigning mixed to int in property (#4981)
staabm Feb 18, 2026
925c25a
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 18, 2026
f179382
ClassNameCheck: Retrieve extensions just once (#4926)
staabm Feb 18, 2026
9712da0
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 18, 2026
f70e2bc
Filter less expression types (#4937)
VincentLanglet Feb 18, 2026
2e145a5
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 18, 2026
bfac6d2
Improve Claude react workflow
ondrejmirtes Feb 16, 2026
8222875
Configure phpstan-bot git identity for Claude PR reactions workflow
ondrejmirtes Feb 16, 2026
3649f55
Split claude react-on-comment into two jobs to avoid expensive setup
claude Feb 16, 2026
d4dc437
Fix Claude credentials to phpstan-bot
ondrejmirtes Feb 16, 2026
e04947f
Merge 2.1.x
ondrejmirtes Feb 18, 2026
64a7ad9
Fix false positive dead catch for ReflectionMethod::invoke/invokeArgs…
staabm Feb 18, 2026
0e8466f
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 18, 2026
ff3110d
Filter unsupported OpenSSL cipher methods on PHP 8.0-8.4 (#4982)
VincentLanglet Feb 18, 2026
b7b2ba4
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 18, 2026
91b0c06
Fix typo (#4984)
vrana Feb 18, 2026
e94c5c8
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 18, 2026
4557edd
Fix test lint-comment (#4986)
staabm Feb 18, 2026
18c1ef7
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 18, 2026
f844f7b
Fix #12574: Erroneous Offset might not exist (#4988)
staabm Feb 18, 2026
2fb5636
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 18, 2026
bae39a9
Use "Ignored error" instead of "Ignored error pattern" when rawMessag…
janedbal Feb 18, 2026
a10a9a2
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 18, 2026
2ccd7b9
Fix isset() falsey branch not narrowing array type for dim fetches (#…
VincentLanglet Feb 19, 2026
0e54233
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 19, 2026
fb4bd86
Add sodium_xxxx_keygen function stubs (#4987)
thePanz Feb 19, 2026
e696ed0
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 19, 2026
ff98196
More precise array_key_first/array_key_last inference (#4994)
staabm Feb 19, 2026
74d0ddf
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 19, 2026
45a62ae
Fix error reported on the wrong line (#4991)
VincentLanglet Feb 19, 2026
fd4c63b
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 19, 2026
1991098
Specify conditional types for all falsey scalars (#4995)
staabm Feb 19, 2026
94a0731
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 19, 2026
7159f64
Add similar behavior for all Assign nodes (#4996)
VincentLanglet Feb 19, 2026
394e477
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 19, 2026
8717c5d
Fix #11463: Using phpstan-import-type between classes makes alias unr…
staabm Feb 19, 2026
0bfbaf9
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 19, 2026
9ac6d7a
Fix isDummy implementation (#5002)
VincentLanglet Feb 19, 2026
8882d85
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 19, 2026
f2e1c15
Changelog generator: thank PR reviewers instead of phpstan-bot
claude Feb 19, 2026
dc7d857
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 19, 2026
56c1e37
Remove callable.nonNativeMethod
VincentLanglet Feb 19, 2026
95584e1
Merge branch refs/heads/2.1.x into 2.2.x
phpstan-bot Feb 19, 2026
0dde338
Fix stub @param types not applied inside method bodies
mglaman Feb 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
199 changes: 199 additions & 0 deletions .claude/skills/regression-test/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
---
name: regression-test
description: Add a regression test for an already-fixed PHPStan bug given a GitHub issue number
argument-hint: "[issue-number]"
allowed-tools: Read, Grep, Glob, Write, Edit, Bash(curl *), Bash(gh *), Bash(git *), Bash(make tests), Bash(vendor/bin/phpunit *), Bash(php *)
---

# Adding a regression test for a fixed PHPStan bug

You are given a GitHub issue number. Your goal is to write a regression test that locks in the fix so the bug cannot silently resurface.

## Step 1 — Gather context from the issue

Fetch the GitHub issue and its comments:

```
gh issue view <number> --repo phpstan/phpstan --json title,body,comments
```

In the comments, look for:

1. **phpstan-bot's commit link** — this identifies the commit that fixed the bug.
2. **PHPStan Playground links** — URLs matching `https://phpstan.org/r/<UUID>`. These contain the reproducing code and the analysis results before and after the fix.

For each playground link, fetch the sample data:

```
curl -s 'https://api.phpstan.org/sample?id=<UUID>'
```

The API returns JSON with:
- `code` — the PHP code that was analysed
- `level` — the PHPStan rule level used
- `config.strictRules`, `config.bleedingEdge`, `config.treatPhpDocTypesAsCertain` — configuration flags
- `versionedErrors` — array of `{phpVersion, errors: [{line, message, identifier}]}`

The playground sample gives you the reproducing code and tells you what errors PHPStan produces (or should no longer produce) at each line. Use this to determine the correct test type and expected outcomes.

## Step 2 — Decide which kind of test to write

### Type-inference test (NSRT)

Use when the bug is about **wrong inferred type, missing type narrowing, or incorrect type after control flow** — i.e., PHPStan reports the wrong type for an expression but no specific rule error is involved.

- Create `tests/PHPStan/Analyser/nsrt/bug-<number>.php`
- Use `assertType()` and optionally `assertNativeType()` to pin the correct types
- The file is **auto-discovered** — no test-case class changes are needed

Example (`tests/PHPStan/Analyser/nsrt/bug-12875.php`):

```php
<?php // lint >= 8.0

declare(strict_types = 1);

namespace Bug12875;

use function PHPStan\Testing\assertType;

interface HasFoo
{
public function foo(): int;
}

interface HasBar
{
public function bar(): int;
}

class HelloWorld
{
/**
* @param "foo"|"bar" $method
* @param ($method is "foo" ? HasFoo : HasBar) $a
* @param ($method is "foo" ? HasFoo : HasBar) $b
*/
public function add(string $method, HasFoo|HasBar $a, HasFoo|HasBar $b): void
{
assertType('int', $a->{$method}());
assertType('int', $b->{$method}());

$addInArrow = fn () => assertType('int', $a->{$method}());

$addInAnonymous = function () use ($a, $b, $method): void {
assertType('int', $a->{$method}());
assertType('int', $b->{$method}());
};
}
}
```

### Rule test

Use when the bug is about a **false positive** (rule reported an error that shouldn't exist) or a **false negative** (rule failed to report an error that should exist).

1. **Find the relevant rule test case.** Search for the rule's identifier or class name:
```
grep -r 'identifier' tests/PHPStan/Rules/ --include='*Test.php'
```
Or look at the error identifier from the playground output (e.g., `argument.type` points to a rule in `Rules/Methods/` or `Rules/Functions/`).

2. **Create the test data file** at `tests/PHPStan/Rules/<Category>/data/bug-<number>.php`.

3. **Add a test method** in the corresponding `*Test.php` rule test case.

Example — test data (`tests/PHPStan/Rules/Methods/data/bug-11470.php`):

```php
<?php declare(strict_types = 1);

namespace Bug11470;

use DateTimeImmutable;

interface HelloWorld
{
public function sayHello(): dateTimeImmutable;
}

interface HelloWorld2
{
public function sayHello(dateTimeImmutable $a): void;
}

interface HelloWorld3
{
public function sayHello(): ?dateTimeImmutable;
}
```

Example — test method in `ExistingClassesInTypehintsRuleTest.php`:

```php
public function testBug11470(): void
{
$this->analyse([__DIR__ . '/data/bug-11470.php'], [
[
'Class DateTimeImmutable referenced with incorrect case: dateTimeImmutable.',
9,
],
[
'Class DateTimeImmutable referenced with incorrect case: dateTimeImmutable.',
14,
],
[
'Class DateTimeImmutable referenced with incorrect case: dateTimeImmutable.',
19,
],
]);
}
```

For **false-positive** fixes the expected-errors array is usually empty `[]`, meaning the code should analyse clean.

## Step 3 — Write the test

- Use the reproducing code from the playground sample as the basis for the test file.
- Put it in the correct `namespace Bug<number>;`.
- Add `use function PHPStan\Testing\assertType;` for NSRT tests.
- If the playground code requires a minimum PHP version, add `// lint >= 8.0` (or whichever version) on the first line.
- For rule tests, determine the expected errors from the playground `versionedErrors`. If the fix eliminated a false positive, expect `[]`. If the fix added a missing error, list the expected `[message, line]` pairs.

## Step 4 — Verify the test

Run the specific test to confirm it passes with the current (fixed) code:

```bash
# NSRT test — run the full NSRT suite or a filtered subset:
vendor/bin/phpunit tests/PHPStan/Analyser/NodeScopeResolverTest.php --filter 'bug-<number>'

# Rule test — run the specific test class:
vendor/bin/phpunit tests/PHPStan/Rules/<Category>/<TestClass>.php --filter testBug<number>
```

## Step 5 — Confirm the test catches a regression

Temporarily revert the fixing commit and verify the test fails:

```bash
git stash
git revert --no-commit <fixing-commit-hash>
vendor/bin/phpunit <test-command-from-step-4>
# Expect failure
git checkout .
git stash pop
```

If the test passes even with the fix reverted, the test is not correctly covering the bug — revisit the assertions or the reproducing code.

## Step 6 — Commit

Stage the new/modified test files and commit. The commit message must include `Closes https://github.com/phpstan/phpstan/issues/<number>` so the upstream issue is closed automatically.

```bash
git add tests/
git commit -m "Add regression test for #<number>

Closes https://github.com/phpstan/phpstan/issues/<number>"
```
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
*.stub linguist-language=PHP

tests/PHPStan/Command/ErrorFormatter/data/WindowsNewlines.php eol=crlf

.github/workflows/*.lock.yml linguist-generated=true merge=ours
33 changes: 33 additions & 0 deletions .github/actions/downgrade-code/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: 'Downgrade code'
description: 'Downgrade code'
inputs:
php-version:
description: 'Original PHP version'
required: true
runs:
using: "composite"
steps:

- name: "Change to simple-downgrade PHP version"
if: inputs.php-version == '7.4' || inputs.php-version == '8.0' || inputs.php-version == '8.1'
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "8.4"

- name: "Transform source code"
if: inputs.php-version == '7.4' || inputs.php-version == '8.0' || inputs.php-version == '8.1'
shell: bash
run: |
composer install --no-interaction --no-progress --working-dir=compiler
./compiler/vendor/bin/simple-downgrade downgrade -c build/downgrade.php ${{ inputs.php-version }}
composer dump

- name: "Re-store PHP version"
if: inputs.php-version == '7.4' || inputs.php-version == '8.0' || inputs.php-version == '8.1'
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "${{ inputs.php-version }}"
ini-file: development
extensions: ds,mbstring
Loading
Loading