diff --git a/config/sets/symfony/symfony7/symfony73/symfony73-console.php b/config/sets/symfony/symfony7/symfony73/symfony73-console.php index 2b5c6dff8..13edea13c 100644 --- a/config/sets/symfony/symfony7/symfony73/symfony73-console.php +++ b/config/sets/symfony/symfony7/symfony73/symfony73-console.php @@ -3,9 +3,14 @@ declare(strict_types=1); use Rector\Config\RectorConfig; +use Rector\Symfony\Symfony73\Rector\Class_\CommandDefaultNameAndDescriptionToAsCommandAttributeRector; use Rector\Symfony\Symfony73\Rector\Class_\CommandHelpToAttributeRector; use Rector\Symfony\Symfony73\Rector\Class_\InvokableCommandInputAttributeRector; return static function (RectorConfig $rectorConfig): void { - $rectorConfig->rules([CommandHelpToAttributeRector::class, InvokableCommandInputAttributeRector::class]); + $rectorConfig->rules([ + CommandHelpToAttributeRector::class, + InvokableCommandInputAttributeRector::class, + CommandDefaultNameAndDescriptionToAsCommandAttributeRector::class, + ]); }; diff --git a/rules-tests/Symfony73/Rector/Class_/CommandDefaultNameAndDescriptionToAsCommandAttributeRector/CommandDefaultNameAndDescriptionToAsCommandAttributeRectorTest.php b/rules-tests/Symfony73/Rector/Class_/CommandDefaultNameAndDescriptionToAsCommandAttributeRector/CommandDefaultNameAndDescriptionToAsCommandAttributeRectorTest.php new file mode 100644 index 000000000..9e41e3ddb --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/CommandDefaultNameAndDescriptionToAsCommandAttributeRector/CommandDefaultNameAndDescriptionToAsCommandAttributeRectorTest.php @@ -0,0 +1,28 @@ +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/Symfony73/Rector/Class_/CommandDefaultNameAndDescriptionToAsCommandAttributeRector/Fixture/some_command_with_defaults.php.inc b/rules-tests/Symfony73/Rector/Class_/CommandDefaultNameAndDescriptionToAsCommandAttributeRector/Fixture/some_command_with_defaults.php.inc new file mode 100644 index 000000000..0a54a3c61 --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/CommandDefaultNameAndDescriptionToAsCommandAttributeRector/Fixture/some_command_with_defaults.php.inc @@ -0,0 +1,33 @@ + +----- + diff --git a/rules-tests/Symfony73/Rector/Class_/CommandDefaultNameAndDescriptionToAsCommandAttributeRector/config/configured_rule.php b/rules-tests/Symfony73/Rector/Class_/CommandDefaultNameAndDescriptionToAsCommandAttributeRector/config/configured_rule.php new file mode 100644 index 000000000..294af316e --- /dev/null +++ b/rules-tests/Symfony73/Rector/Class_/CommandDefaultNameAndDescriptionToAsCommandAttributeRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(CommandDefaultNameAndDescriptionToAsCommandAttributeRector::class); +}; diff --git a/rules/CodeQuality/Rector/Class_/ControllerMethodInjectionToConstructorRector.php b/rules/CodeQuality/Rector/Class_/ControllerMethodInjectionToConstructorRector.php index c045fdbf5..1defa3717 100644 --- a/rules/CodeQuality/Rector/Class_/ControllerMethodInjectionToConstructorRector.php +++ b/rules/CodeQuality/Rector/Class_/ControllerMethodInjectionToConstructorRector.php @@ -46,7 +46,7 @@ public function __construct( private readonly StaticTypeMapper $staticTypeMapper, private readonly AttributeFinder $attributeFinder, private readonly ValueResolver $valueResolver, - private readonly ParentClassMethodTypeOverrideGuard $parentClassMethodOverrideGuard + private readonly ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard ) { } @@ -228,9 +228,7 @@ private function shouldSkipClassMethod(ClassMethod $classMethod): bool return true; } - return $this->parentClassMethodOverrideGuard->hasParentClassMethod( - $classMethod - ); + return $this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($classMethod); } /** diff --git a/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php b/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php index d0753f951..d44bdf5d8 100644 --- a/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php +++ b/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php @@ -16,6 +16,7 @@ use PHPStan\Reflection\ClassReflection; use Rector\Rector\AbstractRector; use Rector\Reflection\ReflectionResolver; +use Rector\Symfony\Enum\SymfonyAttribute; use Rector\ValueObject\Visibility; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; @@ -111,7 +112,7 @@ public function refactor(Node $node): ?Node foreach ($node->attrGroups as $keyAttribute => $attrGroup) { foreach ($attrGroup->attrs as $key => $attr) { - if ($attr->name->toString() === 'Symfony\Component\Console\Attribute\AsCommand') { + if ($this->isName($attr->name, SymfonyAttribute::AS_COMMAND)) { unset($attrGroup->attrs[$key]); } } @@ -134,7 +135,7 @@ private function resolveNameAndDescription(Class_ $class): array foreach ($class->attrGroups as $attrGroup) { foreach ($attrGroup->attrs as $attr) { - if ($attr->name->toString() !== 'Symfony\Component\Console\Attribute\AsCommand') { + if (! $this->isName($attr->name, SymfonyAttribute::AS_COMMAND)) { continue; } diff --git a/rules/Symfony73/Rector/Class_/CommandDefaultNameAndDescriptionToAsCommandAttributeRector.php b/rules/Symfony73/Rector/Class_/CommandDefaultNameAndDescriptionToAsCommandAttributeRector.php new file mode 100644 index 000000000..944e6934a --- /dev/null +++ b/rules/Symfony73/Rector/Class_/CommandDefaultNameAndDescriptionToAsCommandAttributeRector.php @@ -0,0 +1,137 @@ +> + */ + public function getNodeTypes(): array + { + return [Class_::class]; + } + + /** + * @param Class_ $node + */ + public function refactor(Node $node): ?Class_ + { + if (! $this->isObjectType($node, new ObjectType(SymfonyClass::COMMAND))) { + return null; + } + + $defaultName = null; + $defaultDescription = null; + + foreach ($node->stmts as $key => $classStmt) { + if (! $classStmt instanceof ClassMethod) { + continue; + } + + if ($classStmt->stmts === null) { + continue; + } + + if ($this->isName($classStmt, 'getDefaultName')) { + $soleStmt = $classStmt->stmts[0]; + if ($soleStmt instanceof Return_) { + $defaultName = $soleStmt->expr; + unset($node->stmts[$key]); + } + } + + if ($this->isName($classStmt, 'getDefaultDescription')) { + $soleStmt = $classStmt->stmts[0]; + if ($soleStmt instanceof Return_) { + $defaultDescription = $soleStmt->expr; + unset($node->stmts[$key]); + } + } + } + + if (! $defaultName instanceof Expr && ! $defaultDescription instanceof Expr) { + return null; + } + + $args = []; + if ($defaultName instanceof Expr) { + $args[] = new Arg($defaultName, false, false, [], new Identifier('name')); + } + + if ($defaultDescription instanceof Expr) { + $args[] = new Arg($defaultDescription, false, false, [], new Identifier('description')); + } + + $node->attrGroups[] = new AttributeGroup([ + new Attribute(new FullyQualified(SymfonyAttribute::AS_COMMAND), $args), + ]); + + return $node; + } +}