From a7635be8a6b591f3eb36907356ac2095da66893e Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 17 Oct 2026 17:09:17 +0200 Subject: [PATCH 1/3] deprecate ReplaceArgumentDefaultValueRector in favor of custom rule --- phpstan.neon | 1 - .../Fixture/fixture2.php.inc | 29 ----- .../Fixture/from_other_base_class.php.inc | 31 ----- .../Fixture/param_with_any_values.php.inc | 47 -------- .../Fixture/param_with_null.php.inc | 31 ----- .../Fixture/replace_in_constructor.php.inc | 31 ----- ...lace_method_argument_with_constant.php.inc | 36 ------ .../replace_multiple_constructors.php.inc | 33 ------ .../Fixture/replace_named_arguments.php.inc | 32 ------ .../replace_self_constant_in_subclass.php.inc | 31 ----- ...orted_class_const_already_replaced.php.inc | 14 --- .../Fixture/skip_named_arguments.php.inc | 13 --- .../Fixture/skip_self.php.inc | 13 --- ...p_self_constant_in_unrelated_class.php.inc | 14 --- .../ReplaceArgumentDefaultValueRectorTest.php | 28 ----- .../Source/SomeClassWithAnyDefaultValue.php | 8 -- .../Source/SomeMultiArg.php | 16 --- .../Source/SomeSortableObject.php | 16 --- .../config/configured_rule.php | 106 ------------------ .../ReplaceArgumentDefaultValueRector.php | 99 +--------------- 20 files changed, 6 insertions(+), 623 deletions(-) delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/fixture2.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/from_other_base_class.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/param_with_any_values.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/param_with_null.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_in_constructor.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_method_argument_with_constant.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_multiple_constructors.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_named_arguments.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_self_constant_in_subclass.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_imported_class_const_already_replaced.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_named_arguments.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_self.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_self_constant_in_unrelated_class.php.inc delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/ReplaceArgumentDefaultValueRectorTest.php delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Source/SomeClassWithAnyDefaultValue.php delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Source/SomeMultiArg.php delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Source/SomeSortableObject.php delete mode 100644 rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/config/configured_rule.php diff --git a/phpstan.neon b/phpstan.neon index 6b12b4d71f5..93f003793aa 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -132,7 +132,6 @@ parameters: identifier: class.notFound message: '#Class (.*?) not found#' paths: - - rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/config - rules-tests/TypeDeclaration/Rector/ClassMethod/AddReturnTypeDeclarationRector/config - rules-tests/Renaming/Rector/Name/RenameClassRector/config - rules-tests/Renaming/Rector/MethodCall/RenameMethodRector/config diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/fixture2.php.inc b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/fixture2.php.inc deleted file mode 100644 index cee22ca907b..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/fixture2.php.inc +++ /dev/null @@ -1,29 +0,0 @@ - ------ - diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/from_other_base_class.php.inc b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/from_other_base_class.php.inc deleted file mode 100644 index 489db75f211..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/from_other_base_class.php.inc +++ /dev/null @@ -1,31 +0,0 @@ - ------ - \ No newline at end of file diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/param_with_any_values.php.inc b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/param_with_any_values.php.inc deleted file mode 100644 index d46373579d6..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/param_with_any_values.php.inc +++ /dev/null @@ -1,47 +0,0 @@ - ------ - diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/param_with_null.php.inc b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/param_with_null.php.inc deleted file mode 100644 index e02f23d0e98..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/param_with_null.php.inc +++ /dev/null @@ -1,31 +0,0 @@ - ------ - diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_in_constructor.php.inc b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_in_constructor.php.inc deleted file mode 100644 index 769eb07edd0..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_in_constructor.php.inc +++ /dev/null @@ -1,31 +0,0 @@ - ------ - diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_method_argument_with_constant.php.inc b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_method_argument_with_constant.php.inc deleted file mode 100644 index 20f1907efa2..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_method_argument_with_constant.php.inc +++ /dev/null @@ -1,36 +0,0 @@ -setSomeMethod('some value'); -$object->setSomeMethod('some extra value'); - -?> - ------ -setSomeMethod(\SomeClass::SOME_CONSTANT); -$object->setSomeMethod(\SomeClass::SOME_EXTRA_CONSTANT); - -?> diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_multiple_constructors.php.inc b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_multiple_constructors.php.inc deleted file mode 100644 index d329a65de03..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_multiple_constructors.php.inc +++ /dev/null @@ -1,33 +0,0 @@ - ------ - diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_named_arguments.php.inc b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_named_arguments.php.inc deleted file mode 100644 index 23c42ec1c40..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_named_arguments.php.inc +++ /dev/null @@ -1,32 +0,0 @@ -firstArgument(0, b: 1); -$object->firstArgument(a: 0); -$object->firstArgument(b: 1, a: 0); -$object->secondArgument(0, b: 1); -$object->secondArgument(b: 1); -$object->secondArgument(b: 1, a: 0); - -?> - ------ -firstArgument(3, b: 1); -$object->firstArgument(a: 3); -$object->firstArgument(b: 1, a: 3); -$object->secondArgument(0, b: 4); -$object->secondArgument(b: 4); -$object->secondArgument(b: 4, a: 0); - -?> diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_self_constant_in_subclass.php.inc b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_self_constant_in_subclass.php.inc deleted file mode 100644 index 4e523601c70..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/replace_self_constant_in_subclass.php.inc +++ /dev/null @@ -1,31 +0,0 @@ -sortBy(self::SORT_ORDER_ASC); - } -} - -?> ------ -sortBy(self::SORT_ORDER_DESC); - } -} - -?> diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_imported_class_const_already_replaced.php.inc b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_imported_class_const_already_replaced.php.inc deleted file mode 100644 index 3a7de21b915..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_imported_class_const_already_replaced.php.inc +++ /dev/null @@ -1,14 +0,0 @@ -sortBy(SomeSortableObject::SORT_ORDER_DESC); - } -} diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_named_arguments.php.inc b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_named_arguments.php.inc deleted file mode 100644 index e91280a69d3..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_named_arguments.php.inc +++ /dev/null @@ -1,13 +0,0 @@ -firstArgument(b: 1); -$object->secondArgument(a: 1); -$object->secondArgument(0, c: 2); -Yaml::parse('...', flags: false, other: false, another: true); diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_self.php.inc b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_self.php.inc deleted file mode 100644 index 5bdd4e5aac9..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Fixture/skip_self.php.inc +++ /dev/null @@ -1,13 +0,0 @@ -sortBy(SomeSortableObject::SORT_ORDER_ASC); - } -} diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/ReplaceArgumentDefaultValueRectorTest.php b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/ReplaceArgumentDefaultValueRectorTest.php deleted file mode 100644 index 1594497b716..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/ReplaceArgumentDefaultValueRectorTest.php +++ /dev/null @@ -1,28 +0,0 @@ -doTestFile($filePath); - } - - public static function provideData(): Iterator - { - return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); - } - - public function provideConfigFilePath(): string - { - return __DIR__ . '/config/configured_rule.php'; - } -} diff --git a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Source/SomeClassWithAnyDefaultValue.php b/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Source/SomeClassWithAnyDefaultValue.php deleted file mode 100644 index 0af454147a8..00000000000 --- a/rules-tests/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector/Source/SomeClassWithAnyDefaultValue.php +++ /dev/null @@ -1,8 +0,0 @@ -ruleWithConfiguration(ReplaceArgumentDefaultValueRector::class, [ - // special case for constructor - new ReplaceArgumentDefaultValue( - ReplaceInConstructor::class, - MethodName::CONSTRUCT, - 0, - 'some value', - 'SomeClass::SOME_CONSTANT' - ), - new ReplaceArgumentDefaultValue( - ReplaceInConstructor::class, - MethodName::CONSTRUCT, - 0, - 'some extra value', - 'SomeClass::SOME_EXTRA_CONSTANT' - ), - - new ReplaceArgumentDefaultValue( - ReplaceMethodArgumentWithConstant::class, - 'setSomeMethod', - 0, - 'some value', - 'SomeClass::SOME_CONSTANT' - ), - new ReplaceArgumentDefaultValue( - ReplaceMethodArgumentWithConstant::class, - 'setSomeMethod', - 0, - 'some extra value', - 'SomeClass::SOME_EXTRA_CONSTANT' - ), - - new ReplaceArgumentDefaultValue('Symfony\Component\Yaml\Yaml', 'parse', 1, [ - false, - false, - true, - ], 'Symfony\Component\Yaml\Yaml::PARSE_OBJECT_FOR_MAP'), - - new ReplaceArgumentDefaultValue( - 'Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\Source\SomeClassWithAnyDefaultValue', - 'someMethod', - 0, - ReplaceArgumentDefaultValue::ANY_VALUE_BEFORE, - [] - ), - new ReplaceArgumentDefaultValue( - 'Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\Source\SomeClassWithAnyDefaultValue', - 'paramWithNull', - 0, - null, - [] - ), - new ReplaceArgumentDefaultValue( - 'Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\Source\SomeMultiArg', - 'firstArgument', - 0, - 0, - 3 - ), - new ReplaceArgumentDefaultValue( - 'Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\Source\SomeMultiArg', - 'secondArgument', - 1, - 1, - 4 - ), - - new ReplaceArgumentDefaultValue( - Mage::class, - 'getStoreConfig', - 0, - 'path', - 'Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\Fixture\SomeBase::PATH' - ), - - new ReplaceArgumentDefaultValue( - SomeSortableObject::class, - 'sortBy', - 0, - 'ASC', - 'self::SORT_ORDER_DESC' - ), - - new ReplaceArgumentDefaultValue( - SomeSortableObject::class, - 'sortBy', - 0, - 'DESC', - SomeSortableObject::class . '::SORT_ORDER_DESC' - ), - ]); -}; diff --git a/rules/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector.php b/rules/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector.php index 422575634d4..c84bc8b8bbb 100644 --- a/rules/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector.php +++ b/rules/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector.php @@ -9,31 +9,18 @@ use PhpParser\Node\Expr\New_; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Stmt\ClassMethod; -use Rector\Arguments\ArgumentDefaultValueReplacer; use Rector\Arguments\ValueObject\ReplaceArgumentDefaultValue; -use Rector\Contract\Rector\ConfigurableRectorInterface; +use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; +use Rector\Exception\ShouldNotHappenException; use Rector\Rector\AbstractRector; use Rector\RuleDoc\CodeSample\ConfiguredCodeSample; use Rector\RuleDoc\RuleDefinition; -use Rector\ValueObject\MethodName; -use Webmozart\Assert\Assert; /** - * @api used in rector-symfony - * @see \Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\ReplaceArgumentDefaultValueRectorTest + * @deprecated This rule is deprecated. Its configuration is weak and relies on magic strings to reference constants. Write a dedicated custom Rector rule instead for type-safe argument replacement. */ -final class ReplaceArgumentDefaultValueRector extends AbstractRector implements ConfigurableRectorInterface +final class ReplaceArgumentDefaultValueRector extends AbstractRector implements DeprecatedInterface { - /** - * @var ReplaceArgumentDefaultValue[] - */ - private array $replaceArgumentDefaultValues = []; - - public function __construct( - private readonly ArgumentDefaultValueReplacer $argumentDefaultValueReplacer - ) { - } - public function getRuleDefinition(): RuleDefinition { return new RuleDefinition( @@ -72,82 +59,8 @@ public function getNodeTypes(): array return [MethodCall::class, StaticCall::class, ClassMethod::class, New_::class]; } - /** - * @param MethodCall|StaticCall|ClassMethod|New_ $node - */ - public function refactor(Node $node): MethodCall|StaticCall|ClassMethod|New_|null - { - if ($node instanceof New_) { - return $this->refactorNew($node); - } - - $nodeName = $this->getName($node->name); - if ($nodeName === null) { - return null; - } - - $hasChanged = false; - $currentNode = $node; - - foreach ($this->replaceArgumentDefaultValues as $replaceArgumentDefaultValue) { - if (! $this->nodeNameResolver->isStringName($nodeName, $replaceArgumentDefaultValue->getMethod())) { - continue; - } - - if (! $this->nodeTypeResolver->isMethodStaticCallOrClassMethodObjectType( - $currentNode, - $replaceArgumentDefaultValue->getObjectType() - )) { - continue; - } - - $replacedNode = $this->argumentDefaultValueReplacer->processReplaces( - $currentNode, - $replaceArgumentDefaultValue - ); - if ($replacedNode !== null) { - $currentNode = $replacedNode; - $hasChanged = true; - } - } - - return $hasChanged ? $currentNode : null; - } - - /** - * @param mixed[] $configuration - */ - public function configure(array $configuration): void + public function refactor(Node $node): ?Node { - Assert::allIsAOf($configuration, ReplaceArgumentDefaultValue::class); - - $this->replaceArgumentDefaultValues = $configuration; - } - - private function refactorNew(New_ $new): ?New_ - { - $hasChanged = false; - $currentNode = $new; - - foreach ($this->replaceArgumentDefaultValues as $replaceArgumentDefaultValue) { - if ($replaceArgumentDefaultValue->getMethod() !== MethodName::CONSTRUCT) { - continue; - } - - if (! $this->isObjectType($currentNode, $replaceArgumentDefaultValue->getObjectType())) { - continue; - } - - $replacedNode = $this->argumentDefaultValueReplacer->processReplaces( - $currentNode, - $replaceArgumentDefaultValue - ); - if ($replacedNode !== null) { - $currentNode = $replacedNode; - $hasChanged = true; - } - } - - return $hasChanged ? $currentNode : null; + throw new ShouldNotHappenException(sprintf('"%s" rule is deprecated, write a dedicated custom Rector rule instead', self::class)); } } From 091ca78e339bdd0306106993a5d44eafce03f013 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Sat, 17 Oct 2026 15:10:31 +0000 Subject: [PATCH 2/3] [ci-review] Rector Rectify --- .../Rector/ClassMethod/ReplaceArgumentDefaultValueRector.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rules/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector.php b/rules/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector.php index c84bc8b8bbb..4d9c2ecda61 100644 --- a/rules/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector.php +++ b/rules/Arguments/Rector/ClassMethod/ReplaceArgumentDefaultValueRector.php @@ -59,6 +59,9 @@ public function getNodeTypes(): array return [MethodCall::class, StaticCall::class, ClassMethod::class, New_::class]; } + /** + * @param MethodCall|StaticCall|ClassMethod|New_ $node + */ public function refactor(Node $node): ?Node { throw new ShouldNotHappenException(sprintf('"%s" rule is deprecated, write a dedicated custom Rector rule instead', self::class)); From 4dc7f9d0e3ef4f663df47ff483c987efc9d77ad0 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sat, 17 Oct 2026 17:23:05 +0200 Subject: [PATCH 3/3] mark ReplaceArgumentDefaultValue value object as @api for shared use --- rules/Arguments/ValueObject/ReplaceArgumentDefaultValue.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rules/Arguments/ValueObject/ReplaceArgumentDefaultValue.php b/rules/Arguments/ValueObject/ReplaceArgumentDefaultValue.php index 233669c03e7..4238f6f9f88 100644 --- a/rules/Arguments/ValueObject/ReplaceArgumentDefaultValue.php +++ b/rules/Arguments/ValueObject/ReplaceArgumentDefaultValue.php @@ -8,6 +8,9 @@ use Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface; use Rector\Validation\RectorAssert; +/** + * @api used in rector-symfony + */ final readonly class ReplaceArgumentDefaultValue implements ReplaceArgumentDefaultValueInterface { public const string ANY_VALUE_BEFORE = '*ANY_VALUE_BEFORE*';