diff --git a/config/set/php85.php b/config/set/php85.php index e860f28b587..d1928a153c5 100644 --- a/config/set/php85.php +++ b/config/set/php85.php @@ -11,7 +11,6 @@ use Rector\Php85\Rector\Class_\SleepToSerializeRector; use Rector\Php85\Rector\Class_\WakeupToUnserializeRector; use Rector\Php85\Rector\ClassMethod\NullDebugInfoReturnRector; -use Rector\Php85\Rector\Const_\ConstAndTraitDeprecatedAttributeRector; use Rector\Php85\Rector\FuncCall\ArrayKeyExistsNullToEmptyStringRector; use Rector\Php85\Rector\FuncCall\ChrArgModuloRector; use Rector\Php85\Rector\FuncCall\OrdSingleByteRector; @@ -36,7 +35,6 @@ ArrayFirstLastRector::class, RemoveFinfoBufferContextArgRector::class, NullDebugInfoReturnRector::class, - ConstAndTraitDeprecatedAttributeRector::class, ColonAfterSwitchCaseRector::class, ArrayKeyExistsNullToEmptyStringRector::class, ChrArgModuloRector::class, diff --git a/phpstan.neon b/phpstan.neon index 62e24c39aed..08501a16a7e 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -122,12 +122,15 @@ parameters: identifier: rector.upgradeDowngradeRegisteredInSet path: rules/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector.php - # deliberately kept out of the php84 set, as it turns a doc annotation into a runtime deprecation; - # it stays available to register directly with withRules() + # deprecated rules, kept out of the php sets, as they turn a doc annotation into a runtime deprecation - identifier: rector.upgradeDowngradeRegisteredInSet path: rules/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector.php + - + identifier: rector.upgradeDowngradeRegisteredInSet + path: rules/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector.php + # is nested expr - message: '#Access to an undefined property PhpParser\\Node\\Expr\:\:\$expr#' @@ -472,6 +475,8 @@ parameters: - '#Class "Rector\\Transform\\Rector\\Scalar\\ScalarValueToConstFetchRector" is missing @see annotation with test case class reference#' - '#Class "Rector\\DeadCode\\Rector\\ClassLike\\RemoveAnnotationRector" is missing @see annotation with test case class reference#' - '#Class "Rector\\Transform\\Rector\\Class_\\AddInterfaceByTraitRector" is missing @see annotation with test case class reference#' + - '#Class "Rector\\Php84\\Rector\\Class_\\DeprecatedAnnotationToDeprecatedAttributeRector" is missing @see annotation with test case class reference#' + - '#Class "Rector\\Php85\\Rector\\Const_\\ConstAndTraitDeprecatedAttributeRector" is missing @see annotation with test case class reference#' # @todo fix in phpstan-rules - diff --git a/rector.php b/rector.php index 1cde3342073..fda67e23fa8 100644 --- a/rector.php +++ b/rector.php @@ -7,7 +7,6 @@ use Rector\DeadCode\Rector\ClassMethod\RemoveUnusedPublicMethodParameterRector; use Rector\DeadCode\Rector\ConstFetch\RemovePhpVersionIdCheckRector; use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; -use Rector\Php84\Rector\Class_\DeprecatedAnnotationToDeprecatedAttributeRector; use Rector\Symfony\Symfony61\Rector\Class_\CommandConfigureToAttributeRector; return RectorConfig::configure() @@ -64,7 +63,4 @@ __DIR__ . '/src/Configuration/RectorConfigBuilder.php', __DIR__ . '/src/Console/Notifier.php', ], - - // keep @deprecated annotation, as readable in IDE and tooling - DeprecatedAnnotationToDeprecatedAttributeRector::class => [__DIR__ . '/src/Set/ValueObject/SetList.php'], ]); diff --git a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/DeprecatedAnnotationToDeprecatedAttributeRectorTest.php b/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/DeprecatedAnnotationToDeprecatedAttributeRectorTest.php deleted file mode 100644 index 4f96d80c260..00000000000 --- a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/DeprecatedAnnotationToDeprecatedAttributeRectorTest.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/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/fixture.php.inc b/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/fixture.php.inc deleted file mode 100644 index c256555cdea..00000000000 --- a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/fixture.php.inc +++ /dev/null @@ -1,37 +0,0 @@ - ------ - diff --git a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/gracefully_removes_annotation.php.inc b/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/gracefully_removes_annotation.php.inc deleted file mode 100644 index f0708b2d7ed..00000000000 --- a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/gracefully_removes_annotation.php.inc +++ /dev/null @@ -1,29 +0,0 @@ - ------ - diff --git a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/multiline_text.php.inc b/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/multiline_text.php.inc deleted file mode 100644 index c16527a22fa..00000000000 --- a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/multiline_text.php.inc +++ /dev/null @@ -1,33 +0,0 @@ - ------ - diff --git a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/single_line_text.php.inc b/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/single_line_text.php.inc deleted file mode 100644 index 50990bdd1e5..00000000000 --- a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/single_line_text.php.inc +++ /dev/null @@ -1,29 +0,0 @@ - ------ - diff --git a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/with_quote.php.inc b/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/with_quote.php.inc deleted file mode 100644 index 4fc44e382ed..00000000000 --- a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/with_quote.php.inc +++ /dev/null @@ -1,30 +0,0 @@ - ------ - diff --git a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/works_with_functions.php.inc b/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/works_with_functions.php.inc deleted file mode 100644 index 4a7becf5ab5..00000000000 --- a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/Fixture/works_with_functions.php.inc +++ /dev/null @@ -1,23 +0,0 @@ - ------ - diff --git a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/config/configured_rule.php b/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/config/configured_rule.php deleted file mode 100644 index 236335dd794..00000000000 --- a/rules-tests/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector/config/configured_rule.php +++ /dev/null @@ -1,13 +0,0 @@ -rule(DeprecatedAnnotationToDeprecatedAttributeRector::class); - - $rectorConfig->phpVersion(PhpVersion::PHP_84); -}; diff --git a/rules-tests/Php84/Rector/Foreach_/ForeachToArrayAllRector/config/configured_rule.php b/rules-tests/Php84/Rector/Foreach_/ForeachToArrayAllRector/config/configured_rule.php index 043d63ae465..ed494acc888 100644 --- a/rules-tests/Php84/Rector/Foreach_/ForeachToArrayAllRector/config/configured_rule.php +++ b/rules-tests/Php84/Rector/Foreach_/ForeachToArrayAllRector/config/configured_rule.php @@ -4,7 +4,10 @@ use Rector\Config\RectorConfig; use Rector\Php84\Rector\Foreach_\ForeachToArrayAllRector; +use Rector\ValueObject\PhpVersion; return static function (RectorConfig $rectorConfig): void { $rectorConfig->rule(ForeachToArrayAllRector::class); + + $rectorConfig->phpVersion(PhpVersion::PHP_84); }; diff --git a/rules-tests/Php84/Rector/Foreach_/ForeachToArrayAnyRector/config/configured_rule.php b/rules-tests/Php84/Rector/Foreach_/ForeachToArrayAnyRector/config/configured_rule.php index aef591ab108..9d603af77c0 100644 --- a/rules-tests/Php84/Rector/Foreach_/ForeachToArrayAnyRector/config/configured_rule.php +++ b/rules-tests/Php84/Rector/Foreach_/ForeachToArrayAnyRector/config/configured_rule.php @@ -4,7 +4,10 @@ use Rector\Config\RectorConfig; use Rector\Php84\Rector\Foreach_\ForeachToArrayAnyRector; +use Rector\ValueObject\PhpVersion; return static function (RectorConfig $rectorConfig): void { $rectorConfig->rule(ForeachToArrayAnyRector::class); + + $rectorConfig->phpVersion(PhpVersion::PHP_84); }; diff --git a/rules-tests/Php84/Rector/Foreach_/ForeachToArrayFindKeyRector/config/configured_rule.php b/rules-tests/Php84/Rector/Foreach_/ForeachToArrayFindKeyRector/config/configured_rule.php index fe83f386ac0..90e13796fda 100644 --- a/rules-tests/Php84/Rector/Foreach_/ForeachToArrayFindKeyRector/config/configured_rule.php +++ b/rules-tests/Php84/Rector/Foreach_/ForeachToArrayFindKeyRector/config/configured_rule.php @@ -4,6 +4,8 @@ use Rector\Config\RectorConfig; use Rector\Php84\Rector\Foreach_\ForeachToArrayFindKeyRector; +use Rector\ValueObject\PhpVersion; return RectorConfig::configure() - ->withRules([ForeachToArrayFindKeyRector::class]); + ->withRules([ForeachToArrayFindKeyRector::class]) + ->withPhpVersion(PhpVersion::PHP_84); diff --git a/rules-tests/Php84/Rector/Foreach_/ForeachToArrayFindRector/config/configured_rule.php b/rules-tests/Php84/Rector/Foreach_/ForeachToArrayFindRector/config/configured_rule.php index c650631700b..63b9c4fcc40 100644 --- a/rules-tests/Php84/Rector/Foreach_/ForeachToArrayFindRector/config/configured_rule.php +++ b/rules-tests/Php84/Rector/Foreach_/ForeachToArrayFindRector/config/configured_rule.php @@ -4,6 +4,8 @@ use Rector\Config\RectorConfig; use Rector\Php84\Rector\Foreach_\ForeachToArrayFindRector; +use Rector\ValueObject\PhpVersion; return RectorConfig::configure() - ->withRules([ForeachToArrayFindRector::class]); + ->withRules([ForeachToArrayFindRector::class]) + ->withPhpVersion(PhpVersion::PHP_84); diff --git a/rules-tests/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector/ConstAndTraitDeprecatedAttributeRectorTest.php b/rules-tests/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector/ConstAndTraitDeprecatedAttributeRectorTest.php deleted file mode 100644 index 2b8d76deaf3..00000000000 --- a/rules-tests/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector/ConstAndTraitDeprecatedAttributeRectorTest.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/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector/Fixture/basic.php.inc b/rules-tests/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector/Fixture/basic.php.inc deleted file mode 100644 index a8c27ca64ef..00000000000 --- a/rules-tests/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector/Fixture/basic.php.inc +++ /dev/null @@ -1,27 +0,0 @@ - ------ - diff --git a/rules-tests/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector/Fixture/handle_trait.php.inc b/rules-tests/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector/Fixture/handle_trait.php.inc deleted file mode 100644 index 9acfc944786..00000000000 --- a/rules-tests/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector/Fixture/handle_trait.php.inc +++ /dev/null @@ -1,23 +0,0 @@ - ------ - diff --git a/rules-tests/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector/Fixture/skip_on_class_const.php.inc b/rules-tests/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector/Fixture/skip_on_class_const.php.inc deleted file mode 100644 index 162b9de3c62..00000000000 --- a/rules-tests/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector/Fixture/skip_on_class_const.php.inc +++ /dev/null @@ -1,16 +0,0 @@ -rule(ConstAndTraitDeprecatedAttributeRector::class); - $rectorConfig->phpVersion(PhpVersion::PHP_85); -}; diff --git a/rules/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector.php b/rules/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector.php index 182c8b789dc..21d4b7ab005 100644 --- a/rules/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector.php +++ b/rules/Php84/Rector/Class_/DeprecatedAnnotationToDeprecatedAttributeRector.php @@ -8,24 +8,19 @@ use PhpParser\Node\Stmt\ClassConst; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Function_; -use Rector\PhpAttribute\DeprecatedAnnotationToDeprecatedAttributeConverter; +use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; +use Rector\Exception\ShouldNotHappenException; use Rector\Rector\AbstractRector; use Rector\ValueObject\PhpVersionFeature; -use Rector\ValueObject\PolyfillPackage; use Rector\VersionBonding\Contract\MinPhpVersionInterface; use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** - * @see \Rector\Tests\Php84\Rector\Class_\DeprecatedAnnotationToDeprecatedAttributeRector\DeprecatedAnnotationToDeprecatedAttributeRectorTest + * @deprecated This rule is deprecated, as the #[Deprecated] attribute triggers a runtime deprecation, while the @deprecated annotation is a static hint only. Those have a different purpose and are not interchangeable. Use "phpstan/phpstan-deprecation-rules" to report the annotation instead. */ -final class DeprecatedAnnotationToDeprecatedAttributeRector extends AbstractRector implements MinPhpVersionInterface +final class DeprecatedAnnotationToDeprecatedAttributeRector extends AbstractRector implements MinPhpVersionInterface, DeprecatedInterface { - public function __construct( - private readonly DeprecatedAnnotationToDeprecatedAttributeConverter $deprecatedAnnotationToDeprecatedAttributeConverter, - ) { - } - public function getRuleDefinition(): RuleDefinition { return new RuleDefinition('Change @deprecated annotation to Deprecated attribute', [ @@ -59,7 +54,10 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - return $this->deprecatedAnnotationToDeprecatedAttributeConverter->convert($node); + throw new ShouldNotHappenException(sprintf( + '"%s" rule is deprecated, as the #[Deprecated] attribute triggers a runtime deprecation, unlike the @deprecated annotation; use "phpstan/phpstan-deprecation-rules" to report the annotation instead', + self::class + )); } public function provideMinPhpVersion(): int diff --git a/rules/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector.php b/rules/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector.php index 079de99d966..8fd793aebe8 100644 --- a/rules/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector.php +++ b/rules/Php85/Rector/Const_/ConstAndTraitDeprecatedAttributeRector.php @@ -7,7 +7,8 @@ use PhpParser\Node; use PhpParser\Node\Stmt\Const_; use PhpParser\Node\Stmt\Trait_; -use Rector\PhpAttribute\DeprecatedAnnotationToDeprecatedAttributeConverter; +use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; +use Rector\Exception\ShouldNotHappenException; use Rector\Rector\AbstractRector; use Rector\ValueObject\PhpVersion; use Rector\VersionBonding\Contract\MinPhpVersionInterface; @@ -15,18 +16,10 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; /** - * @see https://wiki.php.net/rfc/attributes-on-constants - * @see https://wiki.php.net/rfc/deprecated_traits - * - * @see \Rector\Tests\Php85\Rector\Const_\ConstAndTraitDeprecatedAttributeRector\ConstAndTraitDeprecatedAttributeRectorTest + * @deprecated This rule is deprecated, as the #[Deprecated] attribute triggers a runtime deprecation, while the @deprecated annotation is a static hint only. Those have a different purpose and are not interchangeable. Use "phpstan/phpstan-deprecation-rules" to report the annotation instead. */ -final class ConstAndTraitDeprecatedAttributeRector extends AbstractRector implements MinPhpVersionInterface +final class ConstAndTraitDeprecatedAttributeRector extends AbstractRector implements MinPhpVersionInterface, DeprecatedInterface { - public function __construct( - private readonly DeprecatedAnnotationToDeprecatedAttributeConverter $deprecatedAnnotationToDeprecatedAttributeConverter, - ) { - } - public function getRuleDefinition(): RuleDefinition { return new RuleDefinition('Change @deprecated annotation to #[Deprecated] attribute for constants', [ @@ -56,7 +49,10 @@ public function getNodeTypes(): array */ public function refactor(Node $node): ?Node { - return $this->deprecatedAnnotationToDeprecatedAttributeConverter->convert($node); + throw new ShouldNotHappenException(sprintf( + '"%s" rule is deprecated, as the #[Deprecated] attribute triggers a runtime deprecation, unlike the @deprecated annotation; use "phpstan/phpstan-deprecation-rules" to report the annotation instead', + self::class + )); } public function provideMinPhpVersion(): int diff --git a/src/PhpAttribute/DeprecatedAnnotationToDeprecatedAttributeConverter.php b/src/PhpAttribute/DeprecatedAnnotationToDeprecatedAttributeConverter.php deleted file mode 100644 index 7fbf2b22448..00000000000 --- a/src/PhpAttribute/DeprecatedAnnotationToDeprecatedAttributeConverter.php +++ /dev/null @@ -1,130 +0,0 @@ -phpDocInfoFactory->createFromNode($node); - if ($phpDocInfo instanceof PhpDocInfo) { - $deprecatedAttributeGroup = $this->handleDeprecated($phpDocInfo); - if ($deprecatedAttributeGroup instanceof AttributeGroup) { - $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node); - $node->attrGroups = array_merge($node->attrGroups, [$deprecatedAttributeGroup]); - $this->removeDeprecatedAnnotations($phpDocInfo); - $hasChanged = true; - } - } - - return $hasChanged ? $node : null; - } - - private function handleDeprecated(PhpDocInfo $phpDocInfo): ?AttributeGroup - { - $attributeGroup = null; - $desiredTagValueNodes = $phpDocInfo->getTagsByName('deprecated'); - foreach ($desiredTagValueNodes as $desiredTagValueNode) { - if (! $desiredTagValueNode->value instanceof DeprecatedTagValueNode) { - continue; - } - - $attributeGroup = $this->createAttributeGroup($desiredTagValueNode->value->description); - $this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $desiredTagValueNode); - - break; - } - - return $attributeGroup; - } - - private function createAttributeGroup(string $annotationValue): AttributeGroup - { - $matches = Strings::match($annotationValue, self::VERSION_MATCH_REGEX); - - if ($matches === null) { - $annotationValue = Strings::replace($annotationValue, self::START_STAR_SPACED_REGEX, ''); - - return new AttributeGroup([ - new Attribute( - new FullyQualified('Deprecated'), - [new Arg( - value: new String_($annotationValue, [ - AttributeKey::KIND => String_::KIND_NOWDOC, - AttributeKey::DOC_LABEL => 'TXT', - ]), - name: new Identifier('message') - )] - ), - ]); - } - - $since = $matches[1] ?? null; - $message = $matches[2] ?? null; - - return $this->phpAttributeGroupFactory->createFromClassWithItems('Deprecated', array_filter([ - 'message' => $message, - 'since' => $since, - ])); - } - - private function removeDeprecatedAnnotations(PhpDocInfo $phpDocInfo): bool - { - $hasChanged = false; - - $desiredTagValueNodes = $phpDocInfo->getTagsByName('deprecated'); - foreach ($desiredTagValueNodes as $desiredTagValueNode) { - if (! $desiredTagValueNode->value instanceof GenericTagValueNode) { - continue; - } - - $this->phpDocTagRemover->removeTagValueFromNode($phpDocInfo, $desiredTagValueNode); - $hasChanged = true; - } - - return $hasChanged; - } -}