Skip to content

Commit

Permalink
[DeadCode] Add RemoveUselessReadOnlyTagRector (#5790)
Browse files Browse the repository at this point in the history
* [DeadCode] Add RemoveUselessReadOnlyDocRector

* roll

* final touch: rename to RemoveUselessReadOnlyTagRector

* final touch: doc
  • Loading branch information
samsonasik committed Apr 3, 2024
1 parent 717e3e0 commit ef333de
Show file tree
Hide file tree
Showing 10 changed files with 299 additions and 2 deletions.
27 changes: 25 additions & 2 deletions build/target-repository/docs/rector_rules_overview.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 369 Rules Overview
# 370 Rules Overview

<br>

Expand All @@ -10,7 +10,7 @@

- [CodingStyle](#codingstyle) (28)

- [DeadCode](#deadcode) (43)
- [DeadCode](#deadcode) (44)

- [EarlyReturn](#earlyreturn) (9)

Expand Down Expand Up @@ -2886,6 +2886,29 @@ Remove `@param` docblock with same type as parameter type

<br>

### 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;
}
}
```

<br>

### RemoveUselessReturnExprInConstructRector

Remove useless return Expr in `__construct()`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Rector\Tests\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector\Fixture;

/**
* @readonly
*/
final readonly class RemoveOnClass
{
public function __construct(
private string $name
)
{
}
}

?>
-----
<?php

namespace Rector\Tests\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector\Fixture;

final readonly class RemoveOnClass
{
public function __construct(
private string $name
)
{
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Rector\Tests\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector\Fixture;

final class RemoveOnParamConstruct
{
public function __construct(
/**
* @readonly
*/
private readonly string $name
)
{
}
}

?>
-----
<?php

namespace Rector\Tests\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector\Fixture;

final class RemoveOnParamConstruct
{
public function __construct(
private readonly string $name
)
{
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Rector\Tests\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector\Fixture;

final class RemoveOnProperty
{
/**
* @readonly
*/
private readonly string $name;

public function __construct(string $name)
{
$this->name = $name;
}
}

?>
-----
<?php

namespace Rector\Tests\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector\Fixture;

final class RemoveOnProperty
{
private readonly string $name;

public function __construct(string $name)
{
$this->name = $name;
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Rector\Tests\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector\Fixture;

class SkipNoReadonlyDoc
{
private readonly string $name;

public function __construct(string $name)
{
$this->name = $name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Rector\Tests\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector\Fixture;

class SkipHasDescription
{
/**
* @readonly some desc
*/
private readonly string $name;

public function __construct(string $name)
{
$this->name = $name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector;

use Iterator;
use PHPUnit\Framework\Attributes\DataProvider;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class RemoveUselessReadOnlyTagRectorTest extends AbstractRectorTestCase
{
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

public static function provideData(): Iterator
{
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector;

return RectorConfig::configure()
->withRules([RemoveUselessReadOnlyTagRector::class]);
108 changes: 108 additions & 0 deletions rules/DeadCode/Rector/Property/RemoveUselessReadOnlyTagRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

declare(strict_types=1);

namespace Rector\DeadCode\Rector\Property;

use PhpParser\Node;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Comments\NodeDocBlock\DocBlockUpdater;
use Rector\Privatization\NodeManipulator\VisibilityManipulator;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @see \Rector\Tests\DeadCode\Rector\Property\RemoveUselessReadOnlyTagRector\RemoveUselessReadOnlyTagRectorTest
*/
final class RemoveUselessReadOnlyTagRector extends AbstractRector
{
public function __construct(
private readonly VisibilityManipulator $visibilityManipulator,
private readonly PhpDocInfoFactory $phpDocInfoFactory,
private readonly 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<class-string<Node>>
*/
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;
}
}
2 changes: 2 additions & 0 deletions src/Config/Level/DeadCodeLevel.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
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;
Expand Down Expand Up @@ -90,6 +91,7 @@ final class DeadCodeLevel
// docblock
RemoveUselessParamTagRector::class,
RemoveUselessReturnTagRector::class,
RemoveUselessReadOnlyTagRector::class,
RemoveNonExistingVarAnnotationRector::class,
RemoveUselessVarTagRector::class,
RemovePhpVersionIdCheckRector::class,
Expand Down

0 comments on commit ef333de

Please sign in to comment.