From c0b2cd74268f9a0e7dbc308914914a1e2305cae8 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 24 Oct 2025 22:14:16 +0200 Subject: [PATCH 1/2] [depre] Deprecate AddAllowDynamicPropertiesAttributeRector, as not in PHP sets and does not help by adding attribute everywhere --- ...owDynamicPropertiesAttributeRectorTest.php | 28 ------------------- .../add_allow_dynamic_properties.php.inc | 22 --------------- .../add_allow_dynamic_properties.php.inc | 22 --------------- ...ppend_add_allow_dynamic_properties.php.inc | 24 ---------------- ..._adding_to_descendants_of_stdclass.php.inc | 22 --------------- ...ding_to_descendants_with_magic_set.php.inc | 28 ------------------- ...allow_dynamic_properties_attribute.php.inc | 19 ------------- ...sting_class_outside_transform_list.php.inc | 10 ------- .../add_allow_dynamic_properties.php.inc | 22 --------------- ...ppend_add_allow_dynamic_properties.php.inc | 24 ---------------- ..._adding_to_descendants_of_stdclass.php.inc | 22 --------------- ...ding_to_descendants_with_magic_set.php.inc | 28 ------------------- ...allow_dynamic_properties_attribute.php.inc | 19 ------------- ...owDynamicPropertiesAttributeRectorTest.php | 28 ------------------- .../config/configured_rule.php | 16 ----------- .../config/unconfigured_rule.php | 13 --------- ...dAllowDynamicPropertiesAttributeRector.php | 15 +++++----- 17 files changed, 8 insertions(+), 354 deletions(-) delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/AddAllowDynamicPropertiesAttributeRectorTest.php delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/DefinedClass/add_allow_dynamic_properties.php.inc delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/add_allow_dynamic_properties.php.inc delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/append_add_allow_dynamic_properties.php.inc delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/skip_adding_to_descendants_of_stdclass.php.inc delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/skip_adding_to_descendants_with_magic_set.php.inc delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/skip_already_has_allow_dynamic_properties_attribute.php.inc delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Skip/skips_adjusting_class_outside_transform_list.php.inc delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/add_allow_dynamic_properties.php.inc delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/append_add_allow_dynamic_properties.php.inc delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/skip_adding_to_descendants_of_stdclass.php.inc delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/skip_adding_to_descendants_with_magic_set.php.inc delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/skip_already_has_allow_dynamic_properties_attribute.php.inc delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/UnconfiguredAddAllowDynamicPropertiesAttributeRectorTest.php delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/config/configured_rule.php delete mode 100644 rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/config/unconfigured_rule.php diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/AddAllowDynamicPropertiesAttributeRectorTest.php b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/AddAllowDynamicPropertiesAttributeRectorTest.php deleted file mode 100644 index 5e9d8925d89..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/AddAllowDynamicPropertiesAttributeRectorTest.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/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/DefinedClass/add_allow_dynamic_properties.php.inc b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/DefinedClass/add_allow_dynamic_properties.php.inc deleted file mode 100644 index 3dc368e26ff..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/DefinedClass/add_allow_dynamic_properties.php.inc +++ /dev/null @@ -1,22 +0,0 @@ - ------ - diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/add_allow_dynamic_properties.php.inc b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/add_allow_dynamic_properties.php.inc deleted file mode 100644 index 18669766988..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/add_allow_dynamic_properties.php.inc +++ /dev/null @@ -1,22 +0,0 @@ - ------ - diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/append_add_allow_dynamic_properties.php.inc b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/append_add_allow_dynamic_properties.php.inc deleted file mode 100644 index f96e9fd40e8..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/append_add_allow_dynamic_properties.php.inc +++ /dev/null @@ -1,24 +0,0 @@ - ------ - diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/skip_adding_to_descendants_of_stdclass.php.inc b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/skip_adding_to_descendants_of_stdclass.php.inc deleted file mode 100644 index b0e1c3a14c0..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/skip_adding_to_descendants_of_stdclass.php.inc +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/skip_adding_to_descendants_with_magic_set.php.inc b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/skip_adding_to_descendants_with_magic_set.php.inc deleted file mode 100644 index c3da6890e03..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/skip_adding_to_descendants_with_magic_set.php.inc +++ /dev/null @@ -1,28 +0,0 @@ -props[$name] = $value; - } - - public function __get(string $name) { - return $this->props[$name]; - } -} - -class AnotherMagicObject extends MagicSetObjects -{ - public string $data = 'hello world'; -} - -class YetAnotherMagic extends AnotherMagicObject -{ - public string $data = 'hello space'; -} - -?> diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/skip_already_has_allow_dynamic_properties_attribute.php.inc b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/skip_already_has_allow_dynamic_properties_attribute.php.inc deleted file mode 100644 index 48d7cb34fc5..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Process/skip_already_has_allow_dynamic_properties_attribute.php.inc +++ /dev/null @@ -1,19 +0,0 @@ - diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Skip/skips_adjusting_class_outside_transform_list.php.inc b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Skip/skips_adjusting_class_outside_transform_list.php.inc deleted file mode 100644 index b99fd7a458b..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/Fixture/Skip/skips_adjusting_class_outside_transform_list.php.inc +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/add_allow_dynamic_properties.php.inc b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/add_allow_dynamic_properties.php.inc deleted file mode 100644 index fc897a63fb2..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/add_allow_dynamic_properties.php.inc +++ /dev/null @@ -1,22 +0,0 @@ - ------ - diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/append_add_allow_dynamic_properties.php.inc b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/append_add_allow_dynamic_properties.php.inc deleted file mode 100644 index 15f95d78dd8..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/append_add_allow_dynamic_properties.php.inc +++ /dev/null @@ -1,24 +0,0 @@ - ------ - diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/skip_adding_to_descendants_of_stdclass.php.inc b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/skip_adding_to_descendants_of_stdclass.php.inc deleted file mode 100644 index 2d3bfe037cd..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/skip_adding_to_descendants_of_stdclass.php.inc +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/skip_adding_to_descendants_with_magic_set.php.inc b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/skip_adding_to_descendants_with_magic_set.php.inc deleted file mode 100644 index 484cccca085..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/skip_adding_to_descendants_with_magic_set.php.inc +++ /dev/null @@ -1,28 +0,0 @@ -props[$name] = $value; - } - - public function __get(string $name) { - return $this->props[$name]; - } -} - -class AnotherMagicObject extends MagicSetObjects -{ - public string $data = 'hello world'; -} - -class YetAnotherMagic extends AnotherMagicObject -{ - public string $data = 'hello space'; -} - -?> diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/skip_already_has_allow_dynamic_properties_attribute.php.inc b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/skip_already_has_allow_dynamic_properties_attribute.php.inc deleted file mode 100644 index 8291452d298..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/FixtureAllClasses/skip_already_has_allow_dynamic_properties_attribute.php.inc +++ /dev/null @@ -1,19 +0,0 @@ - diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/UnconfiguredAddAllowDynamicPropertiesAttributeRectorTest.php b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/UnconfiguredAddAllowDynamicPropertiesAttributeRectorTest.php deleted file mode 100644 index 6b571f3d1a6..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/UnconfiguredAddAllowDynamicPropertiesAttributeRectorTest.php +++ /dev/null @@ -1,28 +0,0 @@ -doTestFile($filePath); - } - - public static function provideData(): Iterator - { - return self::yieldFilesFromDirectory(__DIR__ . '/FixtureAllClasses'); - } - - public function provideConfigFilePath(): string - { - return __DIR__ . '/config/unconfigured_rule.php'; - } -} diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/config/configured_rule.php b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/config/configured_rule.php deleted file mode 100644 index 3d6128eed25..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/config/configured_rule.php +++ /dev/null @@ -1,16 +0,0 @@ -phpVersion(PhpVersionFeature::DEPRECATE_DYNAMIC_PROPERTIES); - - $rectorConfig->ruleWithConfiguration(AddAllowDynamicPropertiesAttributeRector::class, [ - '*\Fixture\Process\*', - 'Rector\Tests\Transform\Rector\Class_\AddAllowDynamicPropertiesAttributeRector\Fixture\DefinedClass\AddAllowDynamicProperties', - ]); -}; diff --git a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/config/unconfigured_rule.php b/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/config/unconfigured_rule.php deleted file mode 100644 index 2363761f48d..00000000000 --- a/rules-tests/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector/config/unconfigured_rule.php +++ /dev/null @@ -1,13 +0,0 @@ -phpVersion(PhpVersionFeature::DEPRECATE_DYNAMIC_PROPERTIES); - - $rectorConfig->rule(AddAllowDynamicPropertiesAttributeRector::class); -}; diff --git a/rules/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector.php b/rules/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector.php index 9684bdb7e41..dadb3a6e6cf 100644 --- a/rules/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector.php +++ b/rules/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector.php @@ -8,7 +8,9 @@ use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Stmt\Class_; use PHPStan\Reflection\ReflectionProvider; +use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; use Rector\Contract\Rector\ConfigurableRectorInterface; +use Rector\Exception\ShouldNotHappenException; use Rector\FamilyTree\Reflection\FamilyRelationsAnalyzer; use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer; use Rector\Php81\Enum\AttributeName; @@ -22,9 +24,9 @@ use Webmozart\Assert\Assert; /** - * @see \Rector\Tests\Transform\Rector\Class_\AddAllowDynamicPropertiesAttributeRector\AddAllowDynamicPropertiesAttributeRectorTest + * @deprecated as adds dynamic attribute everywhere blindly or by name (blindly without checking need). Instead, aim at objects without dynamic properties, or use custom rule. */ -final class AddAllowDynamicPropertiesAttributeRector extends AbstractRector implements MinPhpVersionInterface, ConfigurableRectorInterface +final class AddAllowDynamicPropertiesAttributeRector extends AbstractRector implements MinPhpVersionInterface, ConfigurableRectorInterface, DeprecatedInterface { /** * @var array @@ -87,11 +89,10 @@ public function configure(array $configuration): void */ public function refactor(Node $node): ?Node { - if ($this->shouldSkip($node)) { - return null; - } - - return $this->addAllowDynamicPropertiesAttribute($node); + throw new ShouldNotHappenException(sprintf( + '%s is deprecated as it adds dynamic attribute everywhere blindly or by name (blindly without checking need). Instead, aim at objects without dynamic properties, or use custom rule.', + self::class + )); } public function provideMinPhpVersion(): int From 8c7109f88bb4d11ebe3c2a963be4d2b155a47cc8 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 24 Oct 2025 22:17:25 +0200 Subject: [PATCH 2/2] cleanup --- ...dAllowDynamicPropertiesAttributeRector.php | 125 ------------------ 1 file changed, 125 deletions(-) diff --git a/rules/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector.php b/rules/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector.php index dadb3a6e6cf..2e863569bb0 100644 --- a/rules/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector.php +++ b/rules/Transform/Rector/Class_/AddAllowDynamicPropertiesAttributeRector.php @@ -5,42 +5,21 @@ namespace Rector\Transform\Rector\Class_; use PhpParser\Node; -use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Stmt\Class_; -use PHPStan\Reflection\ReflectionProvider; use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; use Rector\Contract\Rector\ConfigurableRectorInterface; use Rector\Exception\ShouldNotHappenException; -use Rector\FamilyTree\Reflection\FamilyRelationsAnalyzer; -use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer; -use Rector\Php81\Enum\AttributeName; -use Rector\PhpAttribute\NodeFactory\PhpAttributeGroupFactory; use Rector\Rector\AbstractRector; -use Rector\ValueObject\MethodName; use Rector\ValueObject\PhpVersionFeature; use Rector\VersionBonding\Contract\MinPhpVersionInterface; use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; -use Webmozart\Assert\Assert; /** * @deprecated as adds dynamic attribute everywhere blindly or by name (blindly without checking need). Instead, aim at objects without dynamic properties, or use custom rule. */ final class AddAllowDynamicPropertiesAttributeRector extends AbstractRector implements MinPhpVersionInterface, ConfigurableRectorInterface, DeprecatedInterface { - /** - * @var array - */ - private array $transformOnNamespaces = []; - - public function __construct( - private readonly FamilyRelationsAnalyzer $familyRelationsAnalyzer, - private readonly PhpAttributeAnalyzer $phpAttributeAnalyzer, - private readonly PhpAttributeGroupFactory $phpAttributeGroupFactory, - private readonly ReflectionProvider $reflectionProvider, - ) { - } - public function getRuleDefinition(): RuleDefinition { return new RuleDefinition('Add the `AllowDynamicProperties` attribute to all classes', [ @@ -77,11 +56,6 @@ public function getNodeTypes(): array public function configure(array $configuration): void { - $transformOnNamespaces = $configuration; - - Assert::allString($transformOnNamespaces); - - $this->transformOnNamespaces = $transformOnNamespaces; } /** @@ -99,103 +73,4 @@ public function provideMinPhpVersion(): int { return PhpVersionFeature::DEPRECATE_DYNAMIC_PROPERTIES; } - - private function isDescendantOfStdclass(Class_ $class): bool - { - if (! $class->extends instanceof FullyQualified) { - return false; - } - - $ancestorClassNames = $this->familyRelationsAnalyzer->getClassLikeAncestorNames($class); - return in_array('stdClass', $ancestorClassNames, true); - } - - private function hasNeededAttributeAlready(Class_ $class): bool - { - $nodeHasAttribute = $this->phpAttributeAnalyzer->hasPhpAttribute( - $class, - AttributeName::ALLOW_DYNAMIC_PROPERTIES - ); - if ($nodeHasAttribute) { - return true; - } - - if (! $class->extends instanceof FullyQualified) { - return false; - } - - return $this->phpAttributeAnalyzer->hasInheritedPhpAttribute($class, AttributeName::ALLOW_DYNAMIC_PROPERTIES); - } - - private function addAllowDynamicPropertiesAttribute(Class_ $class): Class_ - { - $class->attrGroups[] = $this->phpAttributeGroupFactory->createFromClass( - AttributeName::ALLOW_DYNAMIC_PROPERTIES - ); - - return $class; - } - - private function shouldSkip(Class_ $class): bool - { - if ($this->isDescendantOfStdclass($class)) { - return true; - } - - if ($this->hasNeededAttributeAlready($class)) { - return true; - } - - if ($this->hasMagicSetMethod($class)) { - return true; - } - - if ($this->transformOnNamespaces !== []) { - $className = (string) $this->getName($class); - return ! $this->isExistsWithWildCards($className) && ! $this->isExistsWithClassName($className); - } - - return false; - } - - private function isExistsWithWildCards(string $className): bool - { - $wildcardTransformOnNamespaces = array_filter( - $this->transformOnNamespaces, - static fn (string $transformOnNamespace): bool => str_contains($transformOnNamespace, '*') - ); - foreach ($wildcardTransformOnNamespaces as $wildcardTransformOnNamespace) { - if (! fnmatch($wildcardTransformOnNamespace, $className, FNM_NOESCAPE)) { - continue; - } - - return true; - } - - return false; - } - - private function isExistsWithClassName(string $className): bool - { - $transformedClassNames = array_filter( - $this->transformOnNamespaces, - static fn (string $transformOnNamespace): bool => ! str_contains($transformOnNamespace, '*') - ); - foreach ($transformedClassNames as $transformedClassName) { - if (! $this->nodeNameResolver->isStringName($className, $transformedClassName)) { - continue; - } - - return true; - } - - return false; - } - - private function hasMagicSetMethod(Class_ $class): bool - { - $className = (string) $this->getName($class); - $classReflection = $this->reflectionProvider->getClass($className); - return $classReflection->hasMethod(MethodName::__SET); - } }