Skip to content

chore: modernise dev tooling (Rector, PHPStan 2, PHPUnit 11) - #10

Merged
mwansinck merged 6 commits into
fix/php84-implicit-nullable-paramsfrom
chore/modernise-dev-tooling
Jun 16, 2026
Merged

chore: modernise dev tooling (Rector, PHPStan 2, PHPUnit 11)#10
mwansinck merged 6 commits into
fix/php84-implicit-nullable-paramsfrom
chore/modernise-dev-tooling

Conversation

@mwansinck

@mwansinck mwansinck commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Stacked on #9 (base is that branch, so this diff shows only the modernisation; GitHub will retarget to v3.0 once #9 merges).

Dev-only modernisation — runtime support is unchanged: Symfony floor stays ^6.4 (LTS), PHP stays ^8.2.

Tooling

  • Rector 2.x added with rector.php targeting PHP 8.2 (the lowest supported version, so generated code never emits syntax that breaks 8.2 consumers). Sets: php82 + dead-code, code-quality, type-declaration, early-return.
  • PHPStan ^1.8.7^2.1. The 2.0-removed checkMissingIterableValueType param is replaced by the equivalent ignoreErrors identifier missingType.iterableValue (level 9 kept).
  • PHPUnit ^9.5|^10.0^11.0 || ^12.0 || ^13.0. PHPUnit 13 needs PHP 8.4+, 12 needs 8.3, 11 needs 8.2 — the range lets each matrix PHP version install a compatible major (8.2→11, 8.3→12, 8.4/8.5→13) while keeping the ^8.2 floor. Migrated phpunit.xml.dist to the 13.2 schema (verified it still loads on PHPUnit 11). Tests pass unchanged (OK (3 tests, 7 assertions)).

Dependency cleanup

  • Removed phpdocumentor/reflection-docblock — it was unused. The serializer wires ReflectionExtractor (reads native PHP type declarations), never PhpDocExtractor (the only consumer of reflection-docblock); no test references it and nothing else requires it. Symfony 8 even conflicts with reflection-docblock >=7, so it couldn't be bumped regardless. Tests/serialisation stay green without it.

Code changes (no behavioural change)

Applied by Rector (all PHP 8.2-valid):

  • Constructor property promotion: AbsoluteTimeWindow, RelativeTimeWindow, ShipmentStep, Vehicle
  • Dropped a useless intermediate variable in DateTimeUtil (×2)
  • Removed incorrect @param phpdocs on the supports*() normalizer methods — those receive mixed, and the wrong docblocks made PHPStan flag the instanceof checks as always-true

Manual PHPStan fixes:

  • Serializer::normalize() — added @return \ArrayObject<array-key, mixed>|... so the generic \ArrayObject return type is complete. PHPStan flagged missingType.generics only on Symfony 6.4/7.4/8.0 (8.1's parent signature suppressed it); specifying the generics at the source keeps it green on every version (a plain ignore would go unmatched on the 8.1 jobs).

CI

  • PHPStan + Rector (dry-run) run inside the Symfony matrix, so static analysis is exercised against every Symfony/PHP combination
  • Removed the dead commented-out PHPStan block (stale .phar path)

Verification

  • ✅ Full CI matrix green (12 Symfony/PHP combos + php-cs-fixer)
  • Local (PHP 8.5): phpunit 3/3 (PHPUnit 13) · phpstan no errors on Symfony 6.4/7.4/8.1 · rector clean · php-cs-fixer 0 files · composer validate valid

Dev-only modernisation; runtime support unchanged (Symfony floor stays
^6.4 LTS, PHP stays ^8.2).

Tooling:
- Add Rector 2.x with a rector.php targeting PHP 8.2 (the lowest supported
  version, so generated code never breaks 8.2 consumers)
- Bump PHPStan ^1.8.7 -> ^2.1; drop the removed checkMissingIterableValueType
  / checkGenericClassInNonGenericObjectType params and re-express the same
  opt-outs via ignoreErrors identifiers (level 9 kept)
- Bump PHPUnit ^9.5|^10.0 -> ^11.0 and migrate phpunit.xml.dist (coverage
  include -> source); test run is now deprecation-free

Code (applied by Rector, all PHP 8.2-valid, no behavioural change):
- Constructor property promotion in AbsoluteTimeWindow, RelativeTimeWindow,
  ShipmentStep, Vehicle
- Drop a useless intermediate variable in DateTimeUtil (x2)
- Remove incorrect @param phpdocs on the supports*() normalizer methods
  (they receive mixed; the docblocks made PHPStan flag instanceof as always-true)

CI:
- Run PHPStan and Rector (dry-run) inside the Symfony matrix, so static
  analysis runs against each Symfony/PHP combination
- Remove the dead commented-out PHPStan block (stale .phar path)

Verified locally (PHP 8.5): phpunit 3/3, phpstan no errors, rector clean,
php-cs-fixer 0 files.
@mwansinck
mwansinck force-pushed the chore/modernise-dev-tooling branch from dcfc3bc to 223e21f Compare June 16, 2026 14:43
PHPUnit: ^11.0 -> '^11.0 || ^12.0 || ^13.0'. PHPUnit 13 requires PHP 8.4+,
12 requires 8.3, 11 requires 8.2 — the range lets each matrix PHP version
install a compatible major (8.2->11, 8.3->12, 8.4/8.5->13) while the package
keeps its ^8.2 floor. Migrated phpunit.xml.dist to the 13.2 schema; verified
it still loads on PHPUnit 11. Tests pass unchanged (3/3).

Removed phpdocumentor/reflection-docblock: it was unused. The serializer wires
ReflectionExtractor (reads native PHP type declarations), never PhpDocExtractor
(the only consumer of reflection-docblock); no test references it and nothing
else requires it. Symfony 8 even conflicts with reflection-docblock >=7, so it
could not be bumped anyway. Tests/serialization stay green without it.

phpstan.neon: dropped the now-unmatched missingType.generics ignore (the
underlying error no longer occurs; reportUnmatchedIgnoredErrors would fail on it).

Verified locally (PHP 8.5): phpunit 3/3, phpstan no errors, rector clean,
php-cs-fixer 0 files.
PHPStan 2.x (level 9) reports missingType.generics for the \ArrayObject in
the normalize() return type. The error only surfaced on Symfony 6.4/7.4/8.0
(on 8.1 the parent signature suppressed it), so CI failed on almost every
matrix job while passing locally on 8.1.

Specify the generics via @return \ArrayObject<array-key, mixed>|... so the
type is complete on every Symfony version. Fixing it at the source is robust;
a plain ignore would instead go unmatched on the 8.1 jobs and fail those.

Verified phpstan green on Symfony 6.4, 7.4 and 8.1.
- actions/checkout v4 -> v6 (Node 24; v4 was flagged as deprecated Node 20)
- actions/cache v4 -> v5
- shivammathur/setup-php stays v2 (already the latest major)
Comment thread .github/workflows/ci.yml Outdated
Match the single-pipe (no spaces) OR syntax used by the rest of the file's
Symfony constraints (^6.4|^7.4|^8.0). Functionally identical to ||.
@mwansinck
mwansinck requested a review from rvmourik June 16, 2026 19:17
@mwansinck
mwansinck merged commit ab05070 into fix/php84-implicit-nullable-params Jun 16, 2026
13 checks passed
@mwansinck
mwansinck deleted the chore/modernise-dev-tooling branch June 16, 2026 19:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant