DE-175591 fix: adapt to the Skipper collaborators removed in Rector 2.5.9 - #127
Merged
Conversation
4 tasks
tomasJancar
force-pushed
the
DE-175591-rector-2.5.9-support
branch
from
August 3, 2026 09:30
b1240e6 to
074e5a5
Compare
….5.9 Rector 2.5.9 (rectorphp/rector-src#8226, "Collapse single-use Skipper collaborators") removed Rector\Skipper\FileSystem\FnMatchPathNormalizer, Rector\Skipper\Fnmatcher and Rector\Skipper\RealpathMatcher, inlining them as private methods of FileInfoMatcher. FileInfoMatcher itself stays, but ends up with an empty constructor and without its doesFileInfoMatchPatterns() method. Both neon files registered the three removed classes as services, so every consumer's PHPStan run died before analysing anything: Service (Rector\Skipper\FileSystem\FnMatchPathNormalizer::__construct()): Class 'Rector\Skipper\FileSystem\FnMatchPathNormalizer' not found. Since no repository here commits a composer.lock, CI resolves the newest matching dependency, so the PHPStan and Rector jobs broke across all consumers the day 2.5.9 was published - on branches that changed nothing related. The three services are gone from both neon files, the two rules call matchPattern() (which returns the matched pattern or null and exists in every supported version), and the test instantiates FileInfoMatcher without arguments. FileInfoMatcher is no longer listed either: with an empty constructor it does not need to be, and the rules receive it through the existing autowiring. The rector/rector floor moves to ^2.5.9, because the constructor change cannot be satisfied for both sides at once - neon cannot register a service conditionally and PHPStan autowires the constructor, so <=2.5.8 needs the three collaborators in the service list while >=2.5.9 must not have them. Verified with a fresh install of Rector 2.5.9 and 2.6.0: PHPStan clean, 80 tests green, Rector dry-run clean, ECS clean on both. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
tomasJancar
force-pushed
the
DE-175591-rector-2.5.9-support
branch
from
August 3, 2026 11:47
074e5a5 to
2f345d7
Compare
dvorskyfnice
reviewed
Aug 3, 2026
dvorskyfnice
approved these changes
Aug 3, 2026
dominikkaluza
approved these changes
Aug 4, 2026
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description: Drop the Rector Skipper services removed in 2.5.9, switch to matchPattern(), and raise the rector/rector floor to ^2.5.9
Possible impact: Fixes the PHPStan and Rector CI jobs in every repository consuming this package; raises the minimum Rector version
What broke
rectorphp/rector-src#8226 — "Collapse single-use Skipper collaborators", merged 2026-07-30, shipped in 2.5.9 — removed three classes and inlined them as private methods:
Rector\Skipper\FileSystem\FnMatchPathNormalizerdefault-phpstan.neon+phpstan.neonservice listRector\Skipper\FnmatcherRector\Skipper\RealpathMatcherFileInfoMatcher::doesFileInfoMatchPatterns()DisallowConstantsInTestsRule,DisallowConstantsInTestsRectorFileInfoMatcheritself stays, but ends up with an empty constructor. None of the three removed classes were ever used by our own code — they were in the service list purely so PHPStan could buildFileInfoMatcher's constructor.Every consumer's PHPStan run then died before analysing anything:
Verified via
class_exists()on 2.5.9 and 2.6.0 — the three are genuinely gone, not renamed or aliased.No repository here commits a
composer.lock, so CI resolves the newest matching dependency. The day 2.5.9 was published (3 days after 2.5.8) the PHPStan and Rector jobs went red across all consumers, on branches that changed nothing related.The change
FileInfoMatcheris no longer listed either — with an empty constructor it does not need to be, and the rules still receive it through the existing autowiring.doesFileInfoMatchPatterns(...)→matchPattern(...) !== null.matchPattern()returns the matched pattern ornull, and exists in every supported version.new FileInfoMatcher()without arguments.composer.json:rector/rectorfloor^2.3→^2.5.9.Why the floor has to move
The constructor change cannot be satisfied for both sides at once: neon cannot register a service conditionally and PHPStan autowires the constructor, so ≤2.5.8 needs the three collaborators in the service list while ≥2.5.9 must not have them. Measured both ways:
Class ... not foundService of type FnMatchPathNormalizer required by $fnMatchPathNormalizer ... not foundSo supporting both would mean not using
FileInfoMatcherat all (an earlier revision of this PR copied its ~100 lines locally, at +287/−19). Raising the floor keeps the diff at +10/−17 and keeps the matching in Rector's hands, which is where it belongs.Consumer impact
Checked each consumer's own
rector/rectorconstraint against the new floor with the real composer resolver:^2.0^2.4.12.2.3(exact pin)services-monorepopins an exact version, so it will need that pin raised when a new tag of this package is released. Out of scope here.Test plan
Fresh install of each version, full gate set:
Follow-up
Worth a separate ticket: commit a
composer.lock(or at least pin the dev tooling) in these repos. Without one, any upstream release can turn every CI run red with no local change — exactly what happened here.🤖 Generated with Claude Code