[Sets] Move every per-version rule into the composer-based set - #758
Merged
Conversation
… composer-based Every rule these three sets registered is already in composer-based.php, bound to the exact phpunit/phpunit version it needs: - 12.0: RemoveOverrideFinalConstructTestCaseRector (>=12.0.3), plus the mock-to-stub set and composer-based set it imports - 12.5: the three AllowMockObjects rules (>=12.5.2) - 13.0: the expectExceptionMessage() to expectExceptionMessageIsOrContains() rename (>=13.2) The bond is also more accurate than the set trigger was: a 13.0 or 13.1 project no longer gets the rename of a method that only exists from 13.2, and the same for 12.0 versus 12.0.3 and 12.5 versus 12.5.2. The set files stay reachable through the PHPUnitSetList constants.
Each rule now declares the phpunit/phpunit version its target API is available from, so it can be registered once in composer-based.php instead of in a set that only fires on one major version. A project upgrading from PHPUnit 6 to 12 gets all of them in a single run. 21 rules gained a ComposerPackageConstraintInterface bond and the configured rules moved over with ruleWithConfigurationComposerVersionBound. With nothing left to trigger, PHPUnitSetProvider registers the composer-based set as a plain set, and no ComposerTriggeredSet remains. Two rules target APIs that PHPUnit 10 removed, so they carry an upper bound and their tests read the version from a stub composer.json. The per-version set files stay reachable through the PHPUnitSetList constants.
TomasVotruba
added a commit
to rectorphp/rector-src
that referenced
this pull request
Aug 5, 2026
…traintInterface A set triggered on a single major version has to be repeated for every version an upgrade passes through. A rule bonded with ComposerPackageConstraintInterface, added in #7877, states the exact package version its target API is available from and applies from there upwards, so one set covers every upgrade path. rectorphp/rector-symfony#1010 and rectorphp/rector-phpunit#758 moved both extensions over, leaving Twig as the only remaining user. The internal resolving of the class is kept working and ignored in phpstan.neon until that lands too.
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.
Follow-up to #757, which removed the three already-covered sets. This moves the remaining eight — PHPUnit 4.0 through 11.0 — into
composer-based.php, so noComposerTriggeredSetis left in this package.Each rule now declares the PHPUnit version its target API is available from:
That is what makes one set enough. A project upgrading from PHPUnit 6 straight to 12 previously needed every version set in between; now a single set applies exactly the rules its installed version supports.
Version bonds
Grounded in the API that the rule produces:
GetMockRector,GetMockBuilderGetMockToCreateMockRector>=5.4createMock()ExceptionAnnotationRector,DelegateExceptionArgumentsRector>=5.2expectException(),expectExceptionMessage()SpecificAssertInternalTypeRector,SpecificAssertContainsRector,AssertEqualsParameterToSpecificMethodsTypeRector>=7.5assertIsArray(),assertStringContainsString(),assertEqualsWithDelta()AssertRegExpRector>=9.1assertMatchesRegularExpression()ExplicitPhpErrorApiRector>=8.4 <10.0expectDeprecation()family, removed in 10.0TestListenerToHooksRector>=9.0 <10.0The remaining rules keep the version of the set they came from, marked as such in their docblock (
inherited from the PHPUnit 10.0 set). That never applies a rule below where its set already claimed it worked, and the bond can be tightened to an exact minor later.Upper bounds and their tests
ExplicitPhpErrorApiRectorandTestListenerToHooksRectortarget APIs PHPUnit 10 removed. Left open-ended they would rewrite code on PHPUnit 12 into methods that no longer exist, so both carry<10.0— which then disables them under the PHPUnit 13 installed here. Their tests read the version from a stub instead:Two things deliberately left out
PropertyExistsWithoutAssertRectoris not registered in composer-based. It matchesassertObjectHasProperty()— the exact method the>=10.1rename already in this set produces — so the two rewrite each other's output. The conflict is not new (both sat in thephpunit100set together), but I did not want to encode its outcome as expected test output. Worth a separate look; the rule keeps its bond and its set file registration.Duplicate configuration was dropped rather than moved. The
phpunit90andphpunit100renames ofassertRegExp(),assertObjectHasAttribute(),setMethods()and the file/directory asserts are already in composer-based againstPHPUnit\Framework\Assert, whichTestCaseextends. Same forphpunit80'sMockObjectclass rename, already covered by the>=6.0map.Fixtures
Two composer-based fixtures gained an
assertTrue(true).AddDoesNotPerformAssertionToNonAssertingTestRectoris now part of the set and was adding#[DoesNotPerformAssertions]to their empty test methods, which had nothing to do with what those fixtures test.Green locally: 652 tests, PHPStan, ECS and Rector clean.