Skip to content

re #96 raise PHPStan to level 7, zero baseline#113

Merged
tonydspaniard merged 2 commits into
masterfrom
chore/96-burndown-level7
May 28, 2026
Merged

re #96 raise PHPStan to level 7, zero baseline#113
tonydspaniard merged 2 commits into
masterfrom
chore/96-burndown-level7

Conversation

@tonydspaniard
Copy link
Copy Markdown
Member

Summary

Raises phpstan.neon.dist from level 6 → 7 and fixes all 183 new findings at root cause across ~20 packages — no baseline, PHPStan [OK] at level 7. Parallelized via per-package sub-agents with central verification (full stan + test + rector + cs).

Representative fixes (no silencing casts/ignores)

  • string|false returns (json_encode, preg_*, file_*, finfo_*, session funcs) guarded or given JSON_THROW_ON_ERROR; ?GeneratorGenerator.
  • argument.type from mixed flows fixed by propagating generics, precise param/return types, or genuine instanceof/is_* narrowing at boundaries.
  • PhpToken::tokenize() / FilesystemIterator results normalised to list / guarded with instanceof SplFileInfo; class-string<T> params before ReflectionClass.
  • Persistence DatabaseSettings validates non-empty host / positive port to satisfy Cycle's non-empty-string/int<1,max> connection-config constructors.
  • Real bug fixed: DefaultErrorHandler dispatched on handler name vs media type + a missing plain() responder; IpRule netmask via integer bit-shift.
  • Structure: end()/array_key_last narrowing, intdiv for capacity, __get no longer writes null into TKey/TValue-typed properties.

Documented exceptions (config ignoreErrors, with rationale)

CollectionTrait is shared by array-backed collections (Map/Vector/Deque) and delegate-backed adapters (Set→Map, Stack→Vector, Queue→Deque). The adapters narrow $internal to a delegate object but PHP's trait rules force them to keep the trait's $internal = [] default, and PHPStan analyses the trait's array-backed storage per using-class. These are intentional shared-trait-design artefacts, not reachable bugs.

Test plan

  • composer stan (level 7, no baseline) — [OK] No errors
  • composer cs (cache-free) — clean
  • vendor/bin/rector process --dry-run (full) — clean
  • composer test — 5555 tests; only pre-existing local MongoSessionHandlerTest env errors (CI loads ext-mongodb)

Antonio Ramirez added 2 commits May 28, 2026 10:16
Raise phpstan.neon.dist level 6 -> 7 and fix all 183 new findings at root
cause across ~20 packages (parallel per-package sub-agents + central
verification). No baseline; PHPStan [OK] at level 7. Full suite green (only
the pre-existing ext-mongodb-absent MongoSessionHandlerTest errors).

Representative root-cause fixes (no silencing casts/ignores):
- json_encode/preg_*/file_* and other "string|false" returns guarded or given
  JSON_THROW_ON_ERROR; generator methods returning ?Generator -> Generator.
- argument.type from mixed flows fixed by propagating generics, precise
  param/return types, or genuine instanceof / is_* narrowing at boundaries.
- PhpToken::tokenize() / FilesystemIterator results normalised to list / guarded
  with instanceof SplFileInfo; class-string<T> @param added before ReflectionClass.
- Persistence DatabaseSettings now validates non-empty host / positive port to
  satisfy Cycle's non-empty-string/int<1,max> connection-config constructors.
- Real bug: DefaultErrorHandler dispatched on handler name vs media type + a
  missing plain() responder; IpRule netmask via integer bit-shift.
- Structure end()/array_key_last narrowing, intdiv for capacity, __get no longer
  writes null into TKey/TValue-typed properties.

Documented exceptions (config ignoreErrors, not inline) for the php-ds-derived
shared-trait design: CollectionTrait is used by both array-backed collections
and delegate-backed adapters (Set/Stack/Queue narrow $internal to an object but
must keep the trait's `$internal = []` default), so the trait's array-backed
storage/append/capacity hook reads as invalid when analysed in the adapter
context. These are intentional-design artefacts, not reachable bugs.
The level-7 narrowing assumed findOne() returns an array, but it returns a
BSONDocument object by default, so read() always returned '' and broke the
write/read round-trip on CI (where ext-mongodb is loaded). Pass a typeMap so
findOne genuinely returns an array, keeping the is_array narrowing valid.
@tonydspaniard tonydspaniard merged commit c8c8a7b into master May 28, 2026
3 checks passed
@tonydspaniard tonydspaniard deleted the chore/96-burndown-level7 branch May 28, 2026 08:22
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.

1 participant