Releases: rectorphp/rector
Release list
Released Rector 2.5.3
New Features 🥳
withTypeGuardedClasses()
Are you an open-source project or package used by others? Do you want to make type changes, but keep BC?
Guard the listed classes and their non-final descendants against method signature changes - e.g. adding a return type or a param type — that would break child classes (#8135)
return RectorConfig::configure()
->withTypeGuardedClasses([SomeContract::class]);New Rules 🎉
NegatedAndsToPositiveOrsRector
(CodeQuality) — simplify a negated "and" to "or" via de Morgan (#8082)
$a = 5;
$b = 10;
-$result = !($a > 20 && $b <= 50);
+$result = $a <= 20 || $b > 50;ExplicitAttributeNamedArgsRector
(CodeQuality) — positional attribute args → named args (#8079), Thanks @DaveLiddament!
-#[SomeAttribute(SomeClass::class, null, ['home'])]
+#[SomeAttribute(value: SomeClass::class, only: null, except: ['home'])]
class SomeClass
{
}SwitchTrueToMatchRector
(CodeQuality) — switch (true) of returning cases → match (true), replaces deprecated SwitchTrueToIfRector (#8113)
- switch (true) {
- case $value === 0:
- return 'no';
- case $value === 1:
- return 'yes';
- default:
- return 'maybe';
- }
+ return match (true) {
+ $value === 0 => 'no',
+ $value === 1 => 'yes',
+ default => 'maybe',
+ };RemoveDuplicatedReturnSelfDocblockRector
(DeadCode) — drop @return duplicating native self/static (#8087)
final class SomeClass
{
- /**
- * @return $this
- */
public function some(): self
{
return $this;
}
}RemoveMixedDocblockOverruledByNativeTypeRector
(DeadCode) — drop @param mixed / @return mixed overruled by native type (#8089)
- /**
- * @param mixed $value
- * @return mixed
- */
public function run(int $value): string
{
}RemoveUselessUnionReturnDocblockRector
(DeadCode) — drop @return union broader than a specific native type (#8126)
- /**
- * @return bool|mixed|string
- */
public function run(): false|string
{
}ClosureReturnTypeFromAssertInstanceOfRector
(TypeDeclaration) — add closure return type narrowed by assertInstanceOf() (#8115)
- $callback = function (object $object) {
+ $callback = function (object $object): SomeType {
$this->assertInstanceOf(SomeType::class, $object);
return $object;
};TypedPropertyFromContainerGetSetUpRector
(TypeDeclaration) — type property from @var when assigned via container get() in setUp() (#8120)
- /**
- * @var SomeService
- */
- private $someService;
+ private SomeService $someService;
protected function setUp(): void
{
$this->someService = static::getContainer()->get(SomeService::class);
}TypedPropertyFromGetRepositorySetUpRector
(TypeDeclaration) — same, for getRepository() assignment in setUp() (#8124)
- /**
- * @var SomeEntityRepository
- */
- private $someEntityRepository;
+ private SomeEntityRepository $someEntityRepository;
protected function setUp(): void
{
$this->someEntityRepository = $this->em->getRepository(SomeEntity::class);
}NarrowBoolDocblockReturnTypeRector
(TypeDeclaration) — narrow @return bool to false/true per native type (#8127)
/**
- * @return bool|string[]
+ * @return false|string[]
*/
public function run(): false|arrayNarrowArrayCollectionUnionReturnDocblockRector
(TypeDeclarationDocblocks) — Type[]|ArrayCollection → generic ArrayCollection<int, Type> (#8136)
/**
- * @return LeadEventLog[]|ArrayCollection
+ * @return ArrayCollection<int, LeadEventLog>
*/
public function getSuccessful(): ArrayCollectionAddClosureParamTypeFromVariableCallRector
(TypeDeclaration) — add closure param type from how the closure variable is called (#8142)
-$printItem = function ($item) {
+$printItem = function (Item $item) {
echo $item->name;
};
$printItem(new Item());rectorphp/rector-symfony 🎵
EventSubscriberMethodReturnVoidRector
(CodeQuality) — subscribed event methods must return void (event is by-reference) (#949)
- public function onEvent(Event $event): Event
+ public function onEvent(Event $event): void
{
- return $event->setSomething('value');
+ $event->setSomething('value');
}rectorphp/rector-phpunit 🟢
PHPUnit 12 cluster — typing createMock() / createStub() properties as intersections after the MockObject → Stub split.
ChangeMockObjectReturnUnionToIntersectionRector
(CodeQuality) — MockObject @return union → intersection (#703)
/**
- * @return Event|\PHPUnit\Framework\MockObject\MockObject
+ * @return Event&\PHPUnit\Framework\MockObject\MockObject
*/
private function createEvent(): \PHPUnit\Framework\MockObject\MockObjectAddIntersectionVarToMockObjectPropertyRector
(CodeQuality) — add MockObject intersection @var to a native MockObject property (#697)
+ /**
+ * @var \PHPUnit\Framework\MockObject\MockObject&\SomeService
+ */
private \PHPUnit\Framework\MockObject\MockObject $someServiceMock;AddStubIntersectionVarToStubPropertyRector
(CodeQuality) — add Stub intersection @var to a native Stub property (#700)
+ /**
+ * @var \PHPUnit\Framework\MockObject\Stub&\SomeService
+ */
private \PHPUnit\Framework\MockObject\Stub $someServiceStub;MockObjectVarToStubRector
(PHPUnit120) — on a property retyped to Stub, update @var from MockObject to Stub (#689)
/**
- * @var FieldModel|MockObject
+ * @var FieldModel|\PHPUnit\Framework\MockObject\Stub
*/
private \PHPUnit\Framework\MockObject\Stub $leadFieldModel;BareVarToStubIntersectionRector
(PHPUnit120) — add &Stub to a bare single-class @var of a Stub property (#690)
/**
- * @var FormBuilderInterface
+ * @var FormBuilderInterface&Stub
*/
private \PHPUnit\Framework\MockObject\Stub $formBuilder;PreferTestsWithCamelCaseRector
(CodeQuality) — rename PHPUnit test methods to camelCase (#668), Thanks @Xammie!
- public function test_something()
+ public function testSomething()
{
}PreferTestsWithSnakeCaseRector
(CodeQuality) — rename PHPUnit test methods to snake_case, the opposite convention (#668), Thanks @Xammie!
- public function testSomething()
+ public function test_something()
{
}Bugfixes 🐛
--only/--only-suffixruns now cache under a rule-scoped key (#8075), Thanks @SanderMuller!- Fix double clear-cache (#8096)
ParamTypeByMethodCallTypeRectorsplit into Object / Scalar / Array rules (#8134)
Deprecations & Removals 💀
Migrate away - these will be removed in a future release:
SwitchTrueToIfRector→ use newSwitchTrueToMatchRector(#8109)StrictStringParamConcatRector— too many false positives (#8090)StaticClosureRector+StaticArrowFunctionRector(#8092)StaticCallOnNonStaticToInstanceCallRector— risky change (#8093)EnumCaseToPascalCaseRector— risky change (#8095)JoinStringConcatRector(#8107)RemoveTypedPropertyNonMockDocblockRector— no real value (#8119)- Removed: long-deprecated rules (5+ months old) (#8094)
rectorphp/rector-symfony
ParameterBagToAutowireAttributeRector([#954](https://githu...
Released Rector 2.5.2
Bugfixes 🐛
- Match class + path in unused-skip reporting — fix combined
class => [paths]skips being wrongly flagged as unused (#8073) - Mark skip used only when rule would change the file — a class/path skip counts as "used" only if the rule would actually touch that file, killing false "used" hits (#8076)
- Improve unused-skip resolver methods — cleaner resolution internals (#8072)
- Track used skips as
class => [paths]map — richer per-path skip tracking backing the report (#8074)
Released Rector 2.5.1
Bugfixes 🐛
- Skip unused-skip reporting on narrowed runs - no more false "unused skip" noise when running Rector on a subset of paths (#8069)
- Display skips only on uncached run - skip report shows on real runs, not when results come from cache (#8071)
RemoveAlwaysTrueIfConditionRector— avoid scanning whole new statements on dynamic variable checks; moved logic toExprAnalyzerand bail early on defined variables (#8057)
Released Rector 2.5
New Features 🥳 🎉 🎉 🎉
This release has 3 interesting new features. Let's look at them:
[dx] Report skips that never matched (#8058)
-
What? - like PHPStan's
reportUnusedIgnores, but for Rector->withSkip(). Flags skip entries that never matched anything during the run, so you can delete stale skips. -
Why? - skips rot. You skip a path/rule to dodge a problem, later the file moves or the rule stops firing there — the skip lingers forever,
silently masking nothing. This surfaces dead skips so config stays honest.
// rector.php
return RectorConfig::configure()
->withSkip([
SimplifyUselessVariableRector::class => [
'*/src/Legacy/*', // still matches — fine
'*/NonexistentUnused/*', // matches nothing — stale
],
])
->reportUnusedSkips();Run output:
[OK] Rector is done!
[WARNING] This skip is unused, it never matched any element.
You can remove it from "->withSkip()"
* Rector\CodeQuality\Rector\FunctionLike\SimplifyUselessVariableRector => */NonexistentUnused/*[dx] Removing unused imports by default (#8047)
You can update your rector.php config:
return RectorConfig::configure()
- ->withImportNames(removeUnusedImports: true);
+ ->withImportNames();In case it's not for you, turn it off:
return RectorConfig::configure()
- ->withImportNames();
+ ->withImportNames(removeUnusedImports: false);[dx] Introducing Drupal composer-based sets (#8041), Thanks @bbrala!
If you're using Drupal Rector, you can now enable it's per-version sets via:
return RectorConfig::configure()
+ ->withComposerBased(drupal: true);To learn more about composer-based-sets, checkout the documentation.
New Rules 🎉
- [php 8.4] [type-declaration] Add
AddArrayAnyAllClosureParamTypeRectorandNarrowArrayAnyAllNullableParamTypeRector(#8049) - [code-quality] Add
MoveInnerFunctionToTopLevelRector(#8042) - [code-quality] Add
NewArrayItemConcatAssignToAssignRector(#8045) - [code-quality] Add
FixClassCaseSensitivityVarDocblockRector(#8046) - [polyfills] add missing polyfill to PHP 8.4 array functions (#8052)
- [rector] Add
AddParamTypeToRefactorMethodRectorif missing (#8061)
Bugfixes 🐛
- [internal] Streamline use imports management to FileNode (#8040)
- [PostRector] Do not keep an unused import matched only by a partial docblock name's tail (#8043), Thanks @ruudk!
- [CodeQuality] Skip native function on
MoveInnerFunctionToTopLevelRector(#8044) - Fix
--onlyruns caching files as unchanged, hiding pending changes from full runs (#8029), Thanks @SanderMuller! - [fix] Fix
RemoveUnusedPrivateMethodRectorfor NeverType (#8050) - [dead-code] Fix RemoveUnusedVariableAssignRector, allow for SplFileInfo as cleanup on purpose for gc (#8054)
- [fixes] Couple ClassPropertyAssignToConstructorPromotionRector, RemoveAlwaysTrueIfConditionRector and RemoveUnusedVariableAssignRector fixes (#8055)
- [TypeDeclaration][DeadCode] Skip class with Doctrine static function mapping (loadMetadata) in TypedPropertyFromAssignsRector and RemoveUnusedPrivatePropertyRector (#8059)
- [TypeDeclaration] Skip class with Doctrine static function mapping (loadMetadata) in TypedPropertyFromStrictConstructorRector (#8060)
rectorphp/rector-doctrine 🟠
- [NodeAnalyzer] Detect Doctrine static function mapping (loadMetadata) entity in DoctrineEntityDetector (736bf61)
Released Rector 2.4.6
New Features 🥳
- [deprecation] Add RenameDeprecatedMethodCallRector inferring rename from @deprecated docblock (#8015)
- [sets] kick of named args set (#8013)
# rector.php
return (RectorConfig::configure())
->withPreparedSets(namedArgs: true);Bugfixes 🐛
- [BetterPhpDocParser] Keep import referenced by @see/@uses tag with a trailing description (#8039), Thanks @ruudk!
- [internals] skip and finalize beforeTraverse() and afterTraverse() as never used, use refactor() instead (#7765)
- [DeadCode] Skip (void) cast with #[NoDiscard] on target method call on RemoveDeadStmtRector (#8038)
- Bump composer/pcre to ^3.4.0 and phpstan/phpstan to ^2.2.2 (#8037)
- [CodeQuality] Handle crash on custom exception not autoloaded on ThrowWithPreviousExceptionRector (#8036)
- refactor: extract AutoloadFileParameterResolver from bin, add tests (#8035), Thanks @SanderMuller!
- Fix cached results surviving a change of
--autoload-file(#8034), Thanks @SanderMuller! - [CodingStyle] Remove AstResolver usage on ArrowFunctionAndClosureFirstClassCallableGuard (#8031)
- [DeadCode] Remove AstResolver on RemoveParentCallWithoutParentRector (#8032)
- [DeadCode] Skip with use of func_num_args() on RemoveNullArgOnNullDefaultParamRector (#8030)
- [Php70] Skip rewriting to $this on static method or static closure on StaticCallOnNonStaticToInstanceCallRector (#8026)
- [ci] add compat test (#8025)
- Fix ReplaceArgumentDefaultValueRector generating invalid self:: constant in unrelated classes (#8023)
- Fix RemoveDeadIfBlockRector dropping else block when merging empty if with elseif (#8022)
- Fix RemoveParentCallWithoutParentRector removing valid call when ancestor hierarchy is unresolvable (#8018)
- split of RemoveNullNamedArgOnNullDefaultParamRector to handle only named args (#8014)
- Add failing tests (#8012), Thanks @u01jmg3!
- Update rector/swiss-knife version to ^2.4.1 (#8011)
rectorphp/rector-symfony 🎶
- [Symfony81] Add new rule for deprecated validator test usages (#948), Thanks @florianhofsaessC24!
- fix: only convert Twig extensions fully reducible to AsTwig attributes (#947)
- [Symfony73] Sort optional parameters last in InvokableCommandInputAttributeRector (#945)
- Add PHPStan rule requiring nested set configs to be imported in parent set config (#943)
- [Symfony81] Add new rule for Security component (#942), Thanks @MrYamous!
- Remove unused imports (#941), Thanks @MrYamous!
- [Symfony81] Add new rule for Filesystem (#940), Thanks @MrYamous!
rectorphp/rector-phpunit 🟢
- [PHPUnit12] Handle crash on property not exists on PropertyCreateMockToCreateStubRector (#681)
- [AnnotationsToAttributes] Convert external @Depends ClassName::method to #[DependsExternal] (#679)
- [PHPUnit12] Drop ConstraintValidatorTestCase from AllowMockObjectsWhereParentClassRector triggers (#678)
rectorphp/rector-downgrade-php ⬇️
- Add DowngradeDomNodeChildNodesForeachRector for null $childNodes before PHP 8.0 (#379)
- Update boundwize/structarmed version to ^0.9 (#378)
- Fix use of existing PhpAttributeAnalyzer service on AddReturnTypeWillChangeAttributeRector (#377)
- Remove no longer exists '--ansi' flag from swiss-knife (#376)
- [DowngradePhp81] Add AddReturnTypeWillChangeAttributeRector (#372), Thanks @jquiaios!
Released Rector 2.4.5
New Features 🥳
Bugfixes 🐛
- fix: skip StaticCallToMethodCallRector when parent declares final __construct (#8001)
- [NodeManipulator] Use ClassReflection parent isFinalByKeyword()->yes() on ClassDependencyManipulator (#8002)
- [BetterPhpDocParser] Don't wrap first-position @method param union in extra parens (#8003), Thanks @kyle-bisnow!
- [ci] kick of auto issue fixer (#8004)
- [automated] Apply Coding Standard (#8005)
- [CodeQuality] Skip possibly undefined variable on SimplifyEmptyCheckOnEmptyArrayRector (#8006)
- [CodingStyle] Handle namespaced function string on FunctionFirstClassCallableRector (#8007)
- Fix compatibility on optional key on array dim fetch to be Mixed on phpstan patch 2.1.x-dev (#8008)
- Update Mongodb constant from DoctrineSetList (#8009)
- Bump to PHPStan ^2.1.56 (#8010)
rectorphp/rector-symfony
- [QA] Add StructArmed to QA (#939)
- [Symfony81] add rule for Ulid::isValid() new argument (#938), Thanks @MrYamous
- [Symfony81] add rule for Serialiazer method change (#937), Thanks @MrYamous
- [Symfony81] add rules for DependencyInjection namespace change (#936), Thanks @MrYamous
rectorphp/rector-doctrine
- [QA] Add StructArmed to QA (#482)
rectorphp/rector-phpunit
- [QA] Add StructArmed to QA (#677)
- fix assert call type resolving (#675)
- fix AssertIsTypeMethodCallRector crash on enum case argument (#674)
rectorphp/rector-downgrade-php
- [QA] Add StructArmed to QA (#375)
Released Rector 2.4.4
New Features 🥳
- [QA] Add StructArmed to QA (#7989)
- feat: create rector to add names to boolean arguments (#7944), Thanks @calebdw!
- [CodeQuality] Add missing MinPhpVersionInterface implements on AddNameToBooleanArgumentRector (#7994)
- [injection] If parent class has dependency via promoted property, but its private, add a new one to child class deps (#7996)
Bugfixes 🐛
- Bump structarmed to ^0.6 (#7990)
- [Php81] Skip NullToStrictStringFuncCallArgRector for magic __get() property access resolving to ErrorType (#7992)
- [automated] Apply Coding Standard (#7993)
- [TypeDeclarationDocblocks] Skip overridden methods in DocblockReturnArrayFromDirectArrayInstanceRector (#7995)
- Fix compatibility with latest phpstan patch 2.1.x-dev (#7997)
- Temporary pin webmozart/assert to 2.3.0 to make downgrade working (#7998)
- Bump webmozart/assert to ^2.4 (#7999)
Removed 💀
- [DeadCode] Skip used by get_object_vars on RemoveUnusedPromotedPropertyRector (#7988)
rectorphp/rector-symfony
- add fixture with failing parent private (#935)
- fix ControllerMethodInjectionToConstructorRector - update call sites when params are moved to constructor (#934)
rectorphp/rector-downgrade-php
- [DowngradePhp82] Handle nullable true on DowngradeStandaloneNullTrueFalseReturnTypeRector (#374)
Released Rector 2.4.3
New Features 🥳
- Add silverstripe-rector link to README (#7974), Thanks @wernerkrauss!
Bugfixes 🐛
- Fix the behavior of
ClassPropertyAssignToConstructorPromotionRectorwhen types do not match (#7972), Thanks @mspirkov! - Rectify (#7973)
- Bump crate-ci/typos from 1.44.0 to 1.46.0 (#7976), Thanks @dependabot[bot]!
- [CodeQuality] Skip union type on UseIdenticalOverEqualWithSameTypeRector (#7975)
- [CodingStyle] Mirror comment on SplitDoubleAssignRector (#7977)
- [phpstan] remove copuel fixed phpstan ignores (#7979)
- trigger code analysis on main (rectorphp/rector-src@adb24d0)
- [CodeQuality] Skip in html for ForRepeatedCountToOwnVariableRector (#7981)
- Clean up PHPStan ignoreErrors (#7982)
- Fix typo namespace Sourde -> Source in rules-tests/TypeDeclarationDocblocks (#7983)
- cs (rectorphp/rector-src@7805989)
- [Naming] Handle rename with use after anonymous class on RenameParamToMatchTypeRector (#7984)
- [DX] Fix run on custom rector config when no rector.php (#7985)
- Temporary pin nette/utils version to 4.1.3 (#7986)
- Bump to nette/utils ^4.1.4 (#7987)
Removed 💀
- [remove] Remove deprecated StmtsAwareInterface (#7978)
- [remove] Remove deprecated FileWithoutNamespace and ScopeResolverNodeVisitorInterface (#7980)
- remove docker-metadata files, as no longer maintained (rectorphp/rector-src@2166603)
rectorphp/rector-symfony
- [symfony 2.4] skip no-route in GetRequestRector (#933)
- fix(CommandHelpToAttributeRector): support concatenated string in setHelp() (#932), Thanks @androshchuk
rectorphp/rector-phpunit
- [CodeQuality] Handle on static closure on WithCallbackIdenticalToStandaloneAssertsRector (#672)
- ReplaceTestAnnotationWithPrefixedFunctionRector does not match @ test annotation if it is being part of string (#671), Thanks @Dukecz
- [PHPUnit12] Skip used as next arg with MockObject Type on ExpressionCreateMockToCreateStubRector (#670)
- [CodeQuality] Skip multiple uses variable as arg after defined on BareCreateMockAssignToDirectUseRector (#669)
rectorphp/rector-downgrade-php
Released Rector 2.4.2
New Features 🥳
- Add some symfony/polyfill support (#7965), Thanks @sreichel!
- [DeadCode] Allow remove useless @ var on aliased object on RemoveUselessVarTagRector (#7967)
Bugfixes 🐛
- [Php81] Handle crash on normal array with variadic inside class on ArrayToFirstClassCallableRector (#7966)
- [CodeQuality] Skip possibly undefined variable on CoalesceToTernaryRector (#7968)
- [Php70] Allow is_null() conversion on TernaryToNullCoalescingRector with parentheses handling (#7969)
- Bump to PHPStan ^2.1.47 (#7970)
- Bump to PHPStan ^2.1.48 (#7971)
rectorphp/rector-symfony 🎵
- Fix unit test due to new PHPStan release (#931)
Released Rector 2.4.1
New Features 🥳
- [DeadCode] Add
RemoveUselessTernaryRector(#7961) - [CodeQuality] Add
CoalesceToTernaryRector(#7960) - Add
--rules-summaryoption to display applied rules summary with count (#7874), Thanks @carlos-granados! - Add support for adding the
#[Override]attribute to methods implementing interfaces (#7934), Thanks @hockdudu! - feat(printer): add per-node NEWLINE_ON_FLUENT_CALL attribute to BetterStandardPrinter (#7910), Thanks @MrPunyapal!
- Show line numbers in diff output (#7875), Thanks @carlos-granados!
Bugfixes 🐛
- [CodeQuality] Skip with HTML on CompleteMissingIfElseBracketRector (#7952)
- [CodeQuality] Handle with assign on SimplifyIfElseToTernaryRector (#7951)
- [CodeQuality] Skip with HTML on TernaryFalseExpressionToIfRector (#7954)
- [automated] Apply Coding Standard (#7955)
- Make compatible with PHPStan 2.1.x-dev for ObjectType::equals() change behaviour (#7956)
- [AutoImport] Handle FQCN in/not in use on auto import + remove unused import as prefix = suffix (#7957)
- perf: use hash map for installed packages (#7878), Thanks @calebdw!
- [ChangesReporting][Alternative] Collect changed_files on --no-diffs with json output with use of JsonOutputFactory (#7821)
- fix: OOM crash in RemoveUnusedVariableAssignRector (#7964), Thanks @calebdw!