diff --git a/config/sets/symfony/configs.php b/config/sets/symfony/configs.php index de6e3d7d..d9d6f67b 100644 --- a/config/sets/symfony/configs.php +++ b/config/sets/symfony/configs.php @@ -7,7 +7,6 @@ use Rector\Symfony\Configs\Rector\Closure\ServiceSetStringNameToClassNameRector; use Rector\Symfony\Configs\Rector\Closure\ServiceSettersToSettersAutodiscoveryRector; use Rector\Symfony\Configs\Rector\Closure\ServicesSetNameToSetTypeRector; - use Rector\Symfony\Configs\Rector\Closure\ServiceTagsToDefaultsAutoconfigureRector; return static function (RectorConfig $rectorConfig): void { diff --git a/config/sets/symfony/symfony31.php b/config/sets/symfony/symfony31.php index e293a592..e59c2eb7 100644 --- a/config/sets/symfony/symfony31.php +++ b/config/sets/symfony/symfony31.php @@ -3,7 +3,6 @@ declare(strict_types=1); use Rector\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector; - use Rector\Arguments\ValueObject\ReplaceArgumentDefaultValue; use Rector\Config\RectorConfig; diff --git a/config/sets/symfony/symfony33.php b/config/sets/symfony/symfony33.php index dda0d063..0a8f08c4 100644 --- a/config/sets/symfony/symfony33.php +++ b/config/sets/symfony/symfony33.php @@ -3,7 +3,6 @@ declare(strict_types=1); use Rector\Arguments\Rector\ClassMethod\ArgumentAdderRector; - use Rector\Arguments\ValueObject\ArgumentAdder; use Rector\Config\RectorConfig; use Rector\Renaming\Rector\MethodCall\RenameMethodRector; diff --git a/config/sets/symfony/symfony42.php b/config/sets/symfony/symfony42.php index f2c805a0..5c6e6f54 100644 --- a/config/sets/symfony/symfony42.php +++ b/config/sets/symfony/symfony42.php @@ -3,7 +3,6 @@ declare(strict_types=1); use PHPStan\Type\IterableType; - use PHPStan\Type\MixedType; use Rector\Arguments\NodeAnalyzer\ArgumentAddingScope; use Rector\Arguments\Rector\ClassMethod\ArgumentAdderRector; diff --git a/config/sets/symfony/symfony51.php b/config/sets/symfony/symfony51.php index 73020333..31290453 100644 --- a/config/sets/symfony/symfony51.php +++ b/config/sets/symfony/symfony51.php @@ -3,7 +3,6 @@ declare(strict_types=1); use PHPStan\Type\ObjectType; - # https://github.com/symfony/symfony/blob/5.x/UPGRADE-5.1.md use Rector\Config\RectorConfig; use Rector\Renaming\Rector\ClassConstFetch\RenameClassConstFetchRector; diff --git a/phpstan.neon b/phpstan.neon index 462d2946..35d711b1 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -51,3 +51,8 @@ parameters: - '#Cognitive complexity for "Rector\\Symfony\\CodeQuality\\Rector\\Closure\\StringExtensionToConfigBuilderRector\:\:create(.*?)\(\)" is 13, keep it under 10#' - '#Access to an undefined property Rector\\Contract\\PhpParser\\Node\\StmtsAwareInterface\:\:\$stmts#' + + - + message: '#Cognitive complexity for "Rector\\Symfony\\DowngradeSymfony70\\Rector\\Class_\\DowngradeSymfonyCommandAttributeRector\:\:(resolveNameAndDescription|refactor)\(\)" is 13|15, keep it under 10#' + path: rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php + diff --git a/rules-tests/CodeQuality/Rector/MethodCall/AssertSameResponseCodeWithDebugContentsRector/config/configured_rule.php b/rules-tests/CodeQuality/Rector/MethodCall/AssertSameResponseCodeWithDebugContentsRector/config/configured_rule.php index 4b8f6cc9..a3210c02 100644 --- a/rules-tests/CodeQuality/Rector/MethodCall/AssertSameResponseCodeWithDebugContentsRector/config/configured_rule.php +++ b/rules-tests/CodeQuality/Rector/MethodCall/AssertSameResponseCodeWithDebugContentsRector/config/configured_rule.php @@ -3,7 +3,6 @@ declare(strict_types=1); use Rector\Config\RectorConfig; - use Rector\Symfony\CodeQuality\Rector\MethodCall\AssertSameResponseCodeWithDebugContentsRector; return static function (RectorConfig $rectorConfig): void { diff --git a/rules-tests/Configs/Rector/ClassMethod/AddRouteAnnotationRector/config/configured_rule.php b/rules-tests/Configs/Rector/ClassMethod/AddRouteAnnotationRector/config/configured_rule.php index 8dcf7fd9..1a44104c 100644 --- a/rules-tests/Configs/Rector/ClassMethod/AddRouteAnnotationRector/config/configured_rule.php +++ b/rules-tests/Configs/Rector/ClassMethod/AddRouteAnnotationRector/config/configured_rule.php @@ -3,7 +3,6 @@ declare(strict_types=1); use Rector\Config\RectorConfig; - use Rector\Symfony\Bridge\Symfony\Routing\SymfonyRoutesProvider; use Rector\Symfony\Configs\Rector\ClassMethod\AddRouteAnnotationRector; use Rector\Symfony\Contract\Bridge\Symfony\Routing\SymfonyRoutesProviderInterface; diff --git a/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/DowngradeSymfonyCommandAttributeRectorTest.php b/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/DowngradeSymfonyCommandAttributeRectorTest.php new file mode 100644 index 00000000..1b8f9388 --- /dev/null +++ b/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/DowngradeSymfonyCommandAttributeRectorTest.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/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/Fixture/skip_not_extends_command.php.inc b/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/Fixture/skip_not_extends_command.php.inc new file mode 100644 index 00000000..389f7d5b --- /dev/null +++ b/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/Fixture/skip_not_extends_command.php.inc @@ -0,0 +1,7 @@ +setName('app:create-user'); + } +} diff --git a/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/Fixture/with_existing_configure_method.php.inc b/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/Fixture/with_existing_configure_method.php.inc new file mode 100644 index 00000000..894917e2 --- /dev/null +++ b/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/Fixture/with_existing_configure_method.php.inc @@ -0,0 +1,35 @@ + +----- +setName('app:create-user'); + } +} + +?> diff --git a/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/Fixture/with_name.php.inc b/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/Fixture/with_name.php.inc new file mode 100644 index 00000000..e65c588b --- /dev/null +++ b/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/Fixture/with_name.php.inc @@ -0,0 +1,30 @@ + +----- +setName('app:create-user'); + } +} + +?> diff --git a/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/Fixture/with_name_and_description.php.inc b/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/Fixture/with_name_and_description.php.inc new file mode 100644 index 00000000..16d4d00c --- /dev/null +++ b/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/Fixture/with_name_and_description.php.inc @@ -0,0 +1,31 @@ + +----- +setName('app:create-user'); + $this->setDescription('some description'); + } +} + +?> diff --git a/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/config/configured_rule.php b/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/config/configured_rule.php new file mode 100644 index 00000000..9f443a21 --- /dev/null +++ b/rules-tests/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(DowngradeSymfonyCommandAttributeRector::class); +}; diff --git a/rules-tests/Symfony34/Rector/Closure/ContainerGetNameToTypeInTestsRector/config/configured_rule.php b/rules-tests/Symfony34/Rector/Closure/ContainerGetNameToTypeInTestsRector/config/configured_rule.php index fa13c102..9b3c2a8c 100644 --- a/rules-tests/Symfony34/Rector/Closure/ContainerGetNameToTypeInTestsRector/config/configured_rule.php +++ b/rules-tests/Symfony34/Rector/Closure/ContainerGetNameToTypeInTestsRector/config/configured_rule.php @@ -3,7 +3,6 @@ declare(strict_types=1); use Rector\Config\RectorConfig; - use Rector\Symfony\Symfony34\Rector\Closure\ContainerGetNameToTypeInTestsRector; return static function (RectorConfig $rectorConfig): void { diff --git a/rules-tests/Symfony43/Rector/StmtsAwareInterface/TwigBundleFilesystemLoaderToTwigRector/config/configured_rule.php b/rules-tests/Symfony43/Rector/StmtsAwareInterface/TwigBundleFilesystemLoaderToTwigRector/config/configured_rule.php index bb8d9a0a..f4c59252 100644 --- a/rules-tests/Symfony43/Rector/StmtsAwareInterface/TwigBundleFilesystemLoaderToTwigRector/config/configured_rule.php +++ b/rules-tests/Symfony43/Rector/StmtsAwareInterface/TwigBundleFilesystemLoaderToTwigRector/config/configured_rule.php @@ -3,7 +3,6 @@ declare(strict_types=1); use Rector\Config\RectorConfig; - use Rector\Symfony\Symfony43\Rector\StmtsAwareInterface\TwigBundleFilesystemLoaderToTwigRector; return static function (RectorConfig $rectorConfig): void { diff --git a/rules-tests/Symfony60/Rector/FuncCall/ReplaceServiceArgumentRector/config/configured_rule.php b/rules-tests/Symfony60/Rector/FuncCall/ReplaceServiceArgumentRector/config/configured_rule.php index 85588051..764c8a4d 100644 --- a/rules-tests/Symfony60/Rector/FuncCall/ReplaceServiceArgumentRector/config/configured_rule.php +++ b/rules-tests/Symfony60/Rector/FuncCall/ReplaceServiceArgumentRector/config/configured_rule.php @@ -3,9 +3,7 @@ declare(strict_types=1); use PhpParser\Node\Scalar\String_; - use Psr\Container\ContainerInterface; - use Rector\Config\RectorConfig; use Rector\Symfony\Symfony60\Rector\FuncCall\ReplaceServiceArgumentRector; use Rector\Symfony\ValueObject\ReplaceServiceArgument; diff --git a/rules/Configs/Rector/Closure/ServicesSetNameToSetTypeRector.php b/rules/Configs/Rector/Closure/ServicesSetNameToSetTypeRector.php index a753574e..eef278c9 100644 --- a/rules/Configs/Rector/Closure/ServicesSetNameToSetTypeRector.php +++ b/rules/Configs/Rector/Closure/ServicesSetNameToSetTypeRector.php @@ -29,7 +29,7 @@ final class ServicesSetNameToSetTypeRector extends AbstractRector */ private array $alreadyChangedServiceNamesToTypes = []; - private bool $hasChanged = false; + private bool $hasChanged = false; /** * @var array diff --git a/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php b/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php new file mode 100644 index 00000000..775dd936 --- /dev/null +++ b/rules/DowngradeSymfony70/Rector/Class_/DowngradeSymfonyCommandAttributeRector.php @@ -0,0 +1,161 @@ +setName('app:create-user'); + $this->setDescription('some description'); + } +} +CODE_SAMPLE + ), + ] + ); + } + + /** + * @return array> + */ + public function getNodeTypes(): array + { + return [Class_::class]; + } + + /** + * @param Class_ $node + */ + public function refactor(Node $node): ?Node + { + $classReflection = $this->reflectionResolver->resolveClassReflection($node); + if (! $classReflection instanceof ClassReflection) { + return null; + } + + if (! $classReflection->isSubClassOf('Symfony\Component\Console\Command\Command')) { + return null; + } + + $resolveNameAndDescription = $this->resolveNameAndDescription($node); + $name = $resolveNameAndDescription['name']; + $description = $resolveNameAndDescription['description']; + + if ($name === null && $description === null) { + return null; + } + + $configureClassMethod = $node->getMethod('configure'); + $stmts = []; + if ($name !== null) { + $stmts[] = new Expression(new MethodCall(new Variable('this'), 'setName', [new Arg($name)])); + } + + if ($description !== null) { + $stmts[] = new Expression(new MethodCall(new Variable('this'), 'setDescription', [new Arg($description)])); + } + + if ($configureClassMethod instanceof ClassMethod) { + $configureClassMethod->stmts = [...(array) $configureClassMethod->stmts, ...$stmts]; + } else { + $classMethod = new ClassMethod('configure'); + $classMethod->flags = Visibility::PROTECTED; + $classMethod->stmts = $stmts; + + $node->stmts[] = $classMethod; + } + + foreach ($node->attrGroups as $keyAttribute => $attrGroup) { + foreach ($attrGroup->attrs as $key => $attr) { + if ($attr->name->toString() === 'Symfony\Component\Console\Attribute\AsCommand') { + unset($attrGroup->attrs[$key]); + } + } + + if ($attrGroup->attrs === []) { + unset($node->attrGroups[$keyAttribute]); + } + } + + return $node; + } + + /** + * @return array{name: ?Expr, description: ?Expr} + */ + private function resolveNameAndDescription(Class_ $node): array + { + $name = null; + $description = null; + + foreach ($node->attrGroups as $attrGroup) { + foreach ($attrGroup->attrs as $attr) { + if ($attr->name->toString() !== 'Symfony\Component\Console\Attribute\AsCommand') { + continue; + } + + foreach ($attr->args as $arg) { + if (! $arg->name instanceof Identifier) { + continue; + } + + if ($arg->name->toString() === 'name') { + $name = $arg->value; + } + + if ($arg->name->toString() === 'description') { + $description = $arg->value; + } + } + } + } + + return [ + 'name' => $name, + 'description' => $description, + ]; + } +} diff --git a/rules/Symfony62/Rector/ClassMethod/ParamConverterAttributeToMapEntityAttributeRector.php b/rules/Symfony62/Rector/ClassMethod/ParamConverterAttributeToMapEntityAttributeRector.php index fc826d4b..2fb58b6e 100644 --- a/rules/Symfony62/Rector/ClassMethod/ParamConverterAttributeToMapEntityAttributeRector.php +++ b/rules/Symfony62/Rector/ClassMethod/ParamConverterAttributeToMapEntityAttributeRector.php @@ -17,9 +17,9 @@ use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt\ClassMethod; use Rector\Rector\AbstractRector; -use Rector\ValueObject\PhpVersionFeature; use Rector\Symfony\Enum\SensioAttribute; use Rector\Symfony\Enum\SymfonyAnnotation; +use Rector\ValueObject\PhpVersionFeature; use Rector\VersionBonding\Contract\MinPhpVersionInterface; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; diff --git a/src/TypeAnalyzer/ControllerAnalyzer.php b/src/TypeAnalyzer/ControllerAnalyzer.php index 64cfb4b2..1f772a47 100644 --- a/src/TypeAnalyzer/ControllerAnalyzer.php +++ b/src/TypeAnalyzer/ControllerAnalyzer.php @@ -12,8 +12,8 @@ use PHPStan\Type\ObjectType; use PHPStan\Type\ThisType; use PHPStan\Type\TypeWithClassName; -use Rector\Reflection\ReflectionResolver; use Rector\NodeTypeResolver\Node\AttributeKey; +use Rector\Reflection\ReflectionResolver; final class ControllerAnalyzer {