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

@mwansinckmwansinck 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
mwansinckforce-pushed the chore/modernise-dev-tooling branch from dcfc3bc to 223e21fCompareJune 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 rvmourikJune 16, 2026 19:17
@mwansinck
mwansinck merged commit ab05070 into fix/php84-implicit-nullable-paramsJun 16, 2026
13 checks passed
@mwansinck
mwansinck deleted the chore/modernise-dev-tooling branch June 16, 2026 19:25
Sign up for freeto 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

@mwansinck