Caching
This release makes the cache smarter about config changes - fewer needless full re-runs, while still invalidating when results could actually differ.
Configured rule value changes now invalidate the cache (#8400)
withConfiguredRule() stored its config on the RectorConfig instance only, never in the cache hash. Changing a rule's values - same class, different config - kept serving the stale result.
return RectorConfig::configure()
->withConfiguredRule(SomeRector::class, [
- 'old value',
+ 'new value',
]);Before: cache kept, files re-analysed with stale value. After: cache dropped, re-analysed with new value. Merged config now flows through a RULE_CONFIGURATIONS parameter into the strict cache hash. Upgrading invalidates the cache once for projects using configured rules.
--only <Rule> reuses the full-run cache (#8400)
Each --only selection has its own cache namespace, so a file left clean by a prior full run was re-analysed under --only even when nothing changed. A scoped run now falls back to the full-run cache (read only, file content still compared, so real edits are still picked up).
vendor/bin/rector process # full run, files left clean are cached
vendor/bin/rector process --only "Rector\..\SomeRector"Before: --only re-analyses every file. After: skips files the full run already left clean.
Directional cache invalidation on config change (#8397)
Previously any change to any config parameter dropped the whole cache. Now changes are compared by direction:
- removing a rule/set, or adding a skip -> strictly less work -> cache kept
- adding a rule/set, or removing a skip -> more work possible -> cache dropped
- output-affecting params (php version, import names, indent) -> any change still drops the cache
- runtime/reporting params (
--parallel, memory limit, deprecation notices) -> never invalidate
return RectorConfig::configure()
->withRules([
SomeRector::class,
- OtherRector::class, // removing a rule -> cache kept
]); return RectorConfig::configure()
->withSkip([
SomeRector::class,
+ AnotherRector::class, // adding a skip -> cache kept
]);Before: full cache dropped, every file re-analysed. After: cache kept, only changed files re-analysed. A legacy cache value from an older version triggers a single safe reset.
Bugfixes 🐛
- Support PHPStan 2.2.10 scope changes (#8420)
- Fix double backslash in
FunctionFirstClassCallableRector(#8398) IfToNullCoalescingAssignRector: fix isset guard never converting (#8389), keep comments aboveif(#8388), skip non-nullable typed property (#8387)InlineIfToExplicitIfRector: skip same local method call and call chain (#8417, #8418)ArrowFunctionDelegatingCallToFirstClassCallableRector: skip callee arity mismatch (#8391)- Fix newline formatting of deprecated skipped rules warning (#8386)
Deprecations 💀
Rules:
ShortenElseIfRector(#8416)CombineIfRector(#8413)ExplicitBoolCompareRector- can make if-train less readable (#8412)SimplifyIfElseToTernaryRector- avoids less readable code (#8411)
Sets and config:
SetList::IF- rules moved into code-quality and coding-style sets (#8414)SetList::INSTANCEOF- rules moved into code-quality and type-declaration sets (#8408)SetList::PHP_*constants - usewithPhpSets()/withPhpLevel()instead (#8405)- Deprecate group approach for composer-based sets; load from Laravel and Drupal directly (#8406)
- Mark prepared sets params and
withCacheMetaExtension()as@deprecated(#8415) - Disable
withSetProviders()(#8392)
Console commands:
Internal / cleanup
- Inline
symplify/easy-parallelintosrc/Parallel(#8401) - Reuse
RectorCheaperGuardsFirstRulefromsymplify/phpstan-rules(#8404) - Remove
SingleServiceRegistrationRule, drop unusedreact/promise(#8403) - Remove unused
RelatedConfigInterface, dead stub files (#8395, #8407) - Trim redundant Issues regression tests (#8399)