From 5a868ec22b40349132cfb72980f1dabf02a29840 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 22 Jul 2026 12:11:25 +0200 Subject: [PATCH 1/2] [Privatization] Add fixture for skipping Symfony Command protected static property in PrivatizeFinalClassPropertyRector --- .../skip_symfony_command_default_description.php.inc | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 rules-tests/Privatization/Rector/Property/PrivatizeFinalClassPropertyRector/Fixture/skip_symfony_command_default_description.php.inc diff --git a/rules-tests/Privatization/Rector/Property/PrivatizeFinalClassPropertyRector/Fixture/skip_symfony_command_default_description.php.inc b/rules-tests/Privatization/Rector/Property/PrivatizeFinalClassPropertyRector/Fixture/skip_symfony_command_default_description.php.inc new file mode 100644 index 00000000000..3f93e8d27a6 --- /dev/null +++ b/rules-tests/Privatization/Rector/Property/PrivatizeFinalClassPropertyRector/Fixture/skip_symfony_command_default_description.php.inc @@ -0,0 +1,10 @@ + Date: Wed, 22 Jul 2026 12:14:48 +0200 Subject: [PATCH 2/2] [Privatization] Hardcode skip of Symfony Command reserved static properties even when parent no longer declares them --- .../Guard/ParentPropertyLookupGuard.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/rules/Privatization/Guard/ParentPropertyLookupGuard.php b/rules/Privatization/Guard/ParentPropertyLookupGuard.php index d45a508d8ca..c6279f68fee 100644 --- a/rules/Privatization/Guard/ParentPropertyLookupGuard.php +++ b/rules/Privatization/Guard/ParentPropertyLookupGuard.php @@ -21,6 +21,15 @@ final readonly class ParentPropertyLookupGuard { + /** + * Symfony Console Command reserved static properties, read by the parent class via reflection + * even when not declared on the parent class itself + * @see https://github.com/symfony/console/blob/7.1/Command/Command.php + * + * @var string[] + */ + private const SYMFONY_COMMAND_RESERVED_PROPERTY_NAMES = ['defaultName', 'defaultDescription']; + public function __construct( private BetterNodeFinder $betterNodeFinder, private NodeNameResolver $nodeNameResolver, @@ -49,6 +58,10 @@ public function isLegal(Property|string $property, ?ClassReflection $classReflec return false; } + if ($this->isSymfonyCommandReservedProperty($classReflection, $propertyName)) { + return false; + } + $parentClassName = $this->classReflectionAnalyzer->resolveParentClassName($classReflection); if ($parentClassName === null) { return true; @@ -65,6 +78,15 @@ public function isLegal(Property|string $property, ?ClassReflection $classReflec return $this->isGuardedByParents($parentClassReflections, $propertyName, $className); } + private function isSymfonyCommandReservedProperty(ClassReflection $classReflection, string $propertyName): bool + { + if (! in_array($propertyName, self::SYMFONY_COMMAND_RESERVED_PROPERTY_NAMES, true)) { + return false; + } + + return $classReflection->is('Symfony\Component\Console\Command\Command'); + } + private function isFoundInParentClassMethods( ClassReflection $parentClassReflection, string $propertyName,