Releases: rectorphp/rector
Release list
Released Rector 2.5.6
New Features 🥳
- [DeadCode] Add
RemoveReturnTagIncompatibleWithNativeTypeRector(#8172)
final class SomeClass
{
- /**
- * @return SomeObject
- */
public function getName(): string
{
return $this->someObject->getName();
}
}- [TypeDeclarationDocblocks] Add
MergePhpstanDocTagIntoNativeRectorto merge@phpstan-*doc tags into native tags (#8171)
final class SomeClass
{
/**
- * @var Collection
- *
- * @phpstan-var Collection<int, string>
+ * @var Collection<int, string>
*/
private $items;
}Bugfixes 🐛
- [Php81] Skip array dim fetch args in
NullToStrictStringFuncCallArgRector(#8164) - Fix scoper to clean up prefix under
getRuleDefinition()method, parts 1–5 (#8165, #8166, #8167, #8168, #8169) - Bump
phpstan/phpdoc-parserto^2.3.3(#8174)
PHPUnit 🧪
New rules and changes from rector-phpunit.
New Rules
- [CodeQuality] Add
AssertClassToThisAssertRector(#707)
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\TestCase;
final class SomeClass extends TestCase
{
public function run()
{
- Assert::assertEquals('expected', $result);
+ $this->assertEquals('expected', $result);
}
}- [CodeQuality] Add
BareCreateMockAssignToDirectUseRector— inline a single-usecreateMock()assignment (#708)
final class SomeTest extends TestCase
{
public function test()
{
- $someObject = $this->createMock(SomeClass::class);
- $this->process($someObject);
+ $this->process($this->createMock(SomeClass::class));
}
private function process(SomeClass $someObject): void
{
}
}- [CodeQuality] Add
WillReturnCallbackFallbackToThrowRector— throw on an unexpected extra consecutive call (#710)
$this->someServiceMock->expects($matcher)
->method('run')
->willReturnCallback(function () use ($matcher) {
if ($matcher->numberOfInvocations() === 1) {
return 1;
}
+
+ throw new \PHPUnit\Framework\Exception(sprintf('Method should not be called for the %dth time', $matcher->numberOfInvocations()));
});- [CodeQuality] Add
RemoveReturnFromVoidMethodMockCallbackRector— type a void mock callback and drop its value return (#711)
$this->createMock(SomeClass::class)
->method('run')
- ->willReturnCallback(function ($arg) {
+ ->willReturnCallback(function ($arg): void {
echo $arg;
-
- return true;
});(SomeClass::run() returns void.)
- [CodeQuality] Add
CallbackSingleAssertToSimplerRector— collapse awith()callback with a soleassertSame()toequalTo()(#714)
$builder->expects($this->exactly(2))
->method('add')
- ->with($this->callback(function ($type): bool {
- $this->assertSame(TextType::class, $type);
-
- return true;
- }));
+ ->with($this->equalTo(TextType::class));Improvements
Released Rector 2.5.5
New Features 🥳
- [CodingStyle] Add
AlternativeIfToBracketRector(#8158) - [TypeDeclaration] Add PrivateMethodReturnTypeFromStrictNewArrayRector, split private methods out (#8153)
- [CodeQuality] Decopule array and object variants from ExplicitBoolCompareRector (#8162)
Bugfixes 🐛
- [TypeDeclaration] Fix
AddClosureParamTypeForArrayMapRectorto type closure params from array values, not keys (#8163) - [Php56] Add missing parentheses for lower-precedence operands in PowToExpRector (#8161)
- [Php80] Keep trailing doc comment after annotation in AnnotationToAttributeRector (#8160)
- [CodeQuality] Skip same boolean in both branches in SimplifyIfReturnBoolRector (#8159)
- [CodeQuality] Skip alternative syntax (if/endif) in ShortenElseIfRector (#8157)
- [EarlyReturn] Split nested && operand into its own early return in ReturnBinaryOrToEarlyReturnRector (#8156)
- [CodeQuality] Preserve parentheses around low-precedence operands in LogicalToBooleanRector (#8155)
- [CodeQuality] Skip inner function referenced as string callable in InnerFunctionToPrivateMethodRector (#8154)
- [CodeQuality] Preserve parentheses around right-side assign in LogicalToBooleanRector (#8152)
- [CodeQuality] Wrap assign on right side of binary op in parentheses in LogicalToBooleanRector (#8151)
- [DeadCode] Keep generic static union docblock in RemoveDuplicatedReturnSelfDocblockRector (#8150)
Released Rector 2.5.4
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)