diff --git a/docs/rector_rules_overview.md b/docs/rector_rules_overview.md
index a39279ad1d8..fdacc54a1a0 100644
--- a/docs/rector_rules_overview.md
+++ b/docs/rector_rules_overview.md
@@ -1,4 +1,4 @@
-# 369 Rules Overview
+# 370 Rules Overview
@@ -10,7 +10,7 @@
- [CodingStyle](#codingstyle) (28)
-- [DeadCode](#deadcode) (43)
+- [DeadCode](#deadcode) (44)
- [EarlyReturn](#earlyreturn) (9)
@@ -2886,6 +2886,29 @@ Remove `@param` docblock with same type as parameter type
+### RemoveUselessReadOnlyTagRector
+
+Remove useless `@readonly` annotation on native readonly type
+
+- class: [`Rector\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector`](../rules/DeadCode/Rector/Property/RemoveUselessReadOnlyTagRector.php)
+
+```diff
+ final class SomeClass
+ {
+- /**
+- * @readonly
+- */
+ private readonly string $name;
+
+ public function __construct(string $name)
+ {
+ $this->name = $name;
+ }
+ }
+```
+
+
+
### RemoveUselessReturnExprInConstructRector
Remove useless return Expr in `__construct()`
diff --git a/rules/DeadCode/Rector/Property/RemoveUselessReadOnlyTagRector.php b/rules/DeadCode/Rector/Property/RemoveUselessReadOnlyTagRector.php
new file mode 100644
index 00000000000..005664bffcd
--- /dev/null
+++ b/rules/DeadCode/Rector/Property/RemoveUselessReadOnlyTagRector.php
@@ -0,0 +1,107 @@
+visibilityManipulator = $visibilityManipulator;
+ $this->phpDocInfoFactory = $phpDocInfoFactory;
+ $this->docBlockUpdater = $docBlockUpdater;
+ }
+ public function getRuleDefinition() : RuleDefinition
+ {
+ return new RuleDefinition('Remove useless @readonly annotation on native readonly type', [new CodeSample(<<<'CODE_SAMPLE'
+final class SomeClass
+{
+ /**
+ * @readonly
+ */
+ private readonly string $name;
+
+ public function __construct(string $name)
+ {
+ $this->name = $name;
+ }
+}
+CODE_SAMPLE
+, <<<'CODE_SAMPLE'
+final class SomeClass
+{
+ private readonly string $name;
+
+ public function __construct(string $name)
+ {
+ $this->name = $name;
+ }
+}
+CODE_SAMPLE
+)]);
+ }
+ /**
+ * @return array>
+ */
+ public function getNodeTypes() : array
+ {
+ return [Class_::class, Property::class, Param::class];
+ }
+ /**
+ * @param Class_|Property|Param $node
+ */
+ public function refactor(Node $node) : ?Node
+ {
+ // for param, only on property promotion
+ if ($node instanceof Param && $node->flags === 0) {
+ return null;
+ }
+ if (!$this->visibilityManipulator->isReadonly($node)) {
+ return null;
+ }
+ $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
+ $readonlyDoc = $phpDocInfo->getByName('readonly');
+ if (!$readonlyDoc instanceof PhpDocTagNode) {
+ return null;
+ }
+ if (!$readonlyDoc->value instanceof GenericTagValueNode) {
+ return null;
+ }
+ if ($readonlyDoc->value->value !== '') {
+ return null;
+ }
+ $phpDocInfo->removeByName('readonly');
+ $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node);
+ return $node;
+ }
+}
diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php
index 3581a2f1e83..35184c22da5 100644
--- a/src/Application/VersionResolver.php
+++ b/src/Application/VersionResolver.php
@@ -19,12 +19,12 @@ final class VersionResolver
* @api
* @var string
*/
- public const PACKAGE_VERSION = '717e3e00ca93c371f8633f6ea17ea1b5e686657a';
+ public const PACKAGE_VERSION = 'ef333de3d58a4649558971b19f4814fd92823abe';
/**
* @api
* @var string
*/
- public const RELEASE_DATE = '2024-04-03 07:35:59';
+ public const RELEASE_DATE = '2024-04-03 07:36:10';
/**
* @var int
*/
diff --git a/src/Config/Level/DeadCodeLevel.php b/src/Config/Level/DeadCodeLevel.php
index 35fa43e2356..d9bf0c0caa4 100644
--- a/src/Config/Level/DeadCodeLevel.php
+++ b/src/Config/Level/DeadCodeLevel.php
@@ -38,6 +38,7 @@ use Rector\DeadCode\Rector\If_\UnwrapFutureCompatibleIfPhpVersionRector;
use Rector\DeadCode\Rector\Node\RemoveNonExistingVarAnnotationRector;
use Rector\DeadCode\Rector\Plus\RemoveDeadZeroAndOneOperationRector;
use Rector\DeadCode\Rector\Property\RemoveUnusedPrivatePropertyRector;
+use Rector\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector;
use Rector\DeadCode\Rector\Property\RemoveUselessVarTagRector;
use Rector\DeadCode\Rector\PropertyProperty\RemoveNullPropertyInitializationRector;
use Rector\DeadCode\Rector\Return_\RemoveDeadConditionAboveReturnRector;
@@ -86,6 +87,7 @@ final class DeadCodeLevel
// docblock
RemoveUselessParamTagRector::class,
RemoveUselessReturnTagRector::class,
+ RemoveUselessReadOnlyTagRector::class,
RemoveNonExistingVarAnnotationRector::class,
RemoveUselessVarTagRector::class,
RemovePhpVersionIdCheckRector::class,
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index c18d599f36d..e79eb8af97d 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -1288,6 +1288,7 @@ return array(
'Rector\\DeadCode\\Rector\\Plus\\RemoveDeadZeroAndOneOperationRector' => $baseDir . '/rules/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector.php',
'Rector\\DeadCode\\Rector\\PropertyProperty\\RemoveNullPropertyInitializationRector' => $baseDir . '/rules/DeadCode/Rector/PropertyProperty/RemoveNullPropertyInitializationRector.php',
'Rector\\DeadCode\\Rector\\Property\\RemoveUnusedPrivatePropertyRector' => $baseDir . '/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php',
+ 'Rector\\DeadCode\\Rector\\Property\\RemoveUselessReadOnlyTagRector' => $baseDir . '/rules/DeadCode/Rector/Property/RemoveUselessReadOnlyTagRector.php',
'Rector\\DeadCode\\Rector\\Property\\RemoveUselessVarTagRector' => $baseDir . '/rules/DeadCode/Rector/Property/RemoveUselessVarTagRector.php',
'Rector\\DeadCode\\Rector\\Return_\\RemoveDeadConditionAboveReturnRector' => $baseDir . '/rules/DeadCode/Rector/Return_/RemoveDeadConditionAboveReturnRector.php',
'Rector\\DeadCode\\Rector\\StaticCall\\RemoveParentCallWithoutParentRector' => $baseDir . '/rules/DeadCode/Rector/StaticCall/RemoveParentCallWithoutParentRector.php',
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index ac1ccbdb36f..f042e90871d 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -1507,6 +1507,7 @@ class ComposerStaticInit67be42e0079886f0083b7116ae1de531
'Rector\\DeadCode\\Rector\\Plus\\RemoveDeadZeroAndOneOperationRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector.php',
'Rector\\DeadCode\\Rector\\PropertyProperty\\RemoveNullPropertyInitializationRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/PropertyProperty/RemoveNullPropertyInitializationRector.php',
'Rector\\DeadCode\\Rector\\Property\\RemoveUnusedPrivatePropertyRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/Property/RemoveUnusedPrivatePropertyRector.php',
+ 'Rector\\DeadCode\\Rector\\Property\\RemoveUselessReadOnlyTagRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/Property/RemoveUselessReadOnlyTagRector.php',
'Rector\\DeadCode\\Rector\\Property\\RemoveUselessVarTagRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/Property/RemoveUselessVarTagRector.php',
'Rector\\DeadCode\\Rector\\Return_\\RemoveDeadConditionAboveReturnRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/Return_/RemoveDeadConditionAboveReturnRector.php',
'Rector\\DeadCode\\Rector\\StaticCall\\RemoveParentCallWithoutParentRector' => __DIR__ . '/../..' . '/rules/DeadCode/Rector/StaticCall/RemoveParentCallWithoutParentRector.php',