Skip to content

Commit 14635ae

Browse files
committed
feature: add handling for void magic methods
1 parent 6535bab commit 14635ae

File tree

7 files changed

+262
-0
lines changed

7 files changed

+262
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector\Fixture;
4+
5+
class RemoveReturnConstruct
6+
{
7+
/**
8+
* @return void
9+
*/
10+
function __construct()
11+
{
12+
//
13+
}
14+
}
15+
16+
?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector\Fixture;
4+
5+
class RemoveReturnClone
6+
{
7+
/**
8+
* Other comments
9+
*
10+
* @return void
11+
*/
12+
function __clone()
13+
{
14+
//
15+
}
16+
}
17+
18+
?>
19+
-----
20+
<?php
21+
22+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector\Fixture;
23+
24+
class RemoveReturnClone
25+
{
26+
/**
27+
* Other comments
28+
*/
29+
function __clone()
30+
{
31+
//
32+
}
33+
}
34+
35+
?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector\Fixture;
4+
5+
class RemoveReturnConstruct
6+
{
7+
/**
8+
* @return void
9+
*/
10+
function __construct()
11+
{
12+
//
13+
}
14+
}
15+
16+
?>
17+
-----
18+
<?php
19+
20+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector\Fixture;
21+
22+
class RemoveReturnConstruct
23+
{
24+
function __construct()
25+
{
26+
//
27+
}
28+
}
29+
30+
?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector\Fixture;
4+
5+
class RemoveReturnDestruct
6+
{
7+
/**
8+
* @return void
9+
*/
10+
function __destruct()
11+
{
12+
//
13+
}
14+
}
15+
16+
?>
17+
-----
18+
<?php
19+
20+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector\Fixture;
21+
22+
class RemoveReturnDestruct
23+
{
24+
function __destruct()
25+
{
26+
//
27+
}
28+
}
29+
30+
?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessVoidReturnFromDocblockOnVoidMagicMethodsRector;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
11+
final class RemoveUselessVoidReturnFromDocblockVoidMagicMethodsRectorTest extends AbstractRectorTestCase
12+
{
13+
#[DataProvider('provideData')]
14+
public function test(string $filePath): void
15+
{
16+
$this->doTestFile($filePath);
17+
}
18+
19+
public static function provideData(): Iterator
20+
{
21+
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
22+
}
23+
24+
public function provideConfigFilePath(): string
25+
{
26+
return __DIR__ . '/config/configured_rule.php';
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\Config\RectorConfig;
6+
7+
return RectorConfig::configure()
8+
->withRules([\Rector\DeadCode\Rector\ClassMethod\RemoveUselessVoidReturnFromDocblockVoidMagicMethodsRector::class]);
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\DeadCode\Rector\ClassMethod;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Stmt\ClassMethod;
9+
use PHPStan\PhpDocParser\Ast\Node as AstNode;
10+
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
11+
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
12+
use Rector\Comments\NodeDocBlock\DocBlockUpdater;
13+
use Rector\PhpDocParser\PhpDocParser\PhpDocNodeTraverser;
14+
use Rector\Rector\AbstractRector;
15+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
16+
17+
/**
18+
* @see \Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessVoidReturnFromDocblockOnVoidMagicMethodsRector\RemoveUselessVoidReturnFromDocblockVoidMagicMethodsRectorTest
19+
*/
20+
class RemoveUselessVoidReturnFromDocblockVoidMagicMethodsRector extends AbstractRector
21+
{
22+
public function __construct(
23+
private readonly DocBlockUpdater $docBlockUpdater,
24+
private readonly PhpDocInfoFactory $phpDocInfoFactory,
25+
) {
26+
}
27+
28+
public function getRuleDefinition(): RuleDefinition
29+
{
30+
return new RuleDefinition(
31+
'Remove useless @return void docblock from magic methods __construct, __destruct, and __clone',
32+
[
33+
new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(
34+
<<<'CODE_SAMPLE'
35+
class SomeClass
36+
{
37+
/**
38+
* @return void
39+
*/
40+
public function __construct() {}
41+
42+
/**
43+
* @return void
44+
*/
45+
public function __destruct() {}
46+
47+
/**
48+
* @return void
49+
*/
50+
public function __clone() {}
51+
}
52+
CODE_SAMPLE
53+
,
54+
<<<'CODE_SAMPLE'
55+
class SomeClass
56+
{
57+
public function __construct() {}
58+
59+
public function __destruct() {}
60+
61+
public function __clone() {}
62+
}
63+
CODE_SAMPLE
64+
),
65+
]
66+
);
67+
}
68+
69+
public function getNodeTypes(): array
70+
{
71+
return [ClassMethod::class];
72+
}
73+
74+
/**
75+
* @param ClassMethod $node
76+
*/
77+
public function refactor(Node $node): ?Node
78+
{
79+
if (! $node instanceof ClassMethod) {
80+
return null;
81+
}
82+
83+
$magicMethodNames = ['__construct', '__destruct', '__clone'];
84+
85+
$methodName = $this->getName($node);
86+
87+
if (! in_array($methodName, $magicMethodNames, true)) {
88+
return null;
89+
}
90+
91+
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
92+
93+
$returnTagValueNode = $phpDocInfo->getReturnTagValue();
94+
95+
$phpDocNodeTraverser = new PhpDocNodeTraverser();
96+
$phpDocNodeTraverser->traverseWithCallable(
97+
$phpDocInfo->getPhpDocNode(),
98+
'',
99+
function (AstNode $node) use ($returnTagValueNode): ?int {
100+
if (! $node instanceof PhpDocTagNode) {
101+
return null;
102+
}
103+
104+
if ($node->value === $returnTagValueNode) {
105+
return PhpDocNodeTraverser::NODE_REMOVE;
106+
}
107+
108+
return null;
109+
}
110+
);
111+
112+
$this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node);
113+
return $node;
114+
}
115+
}

0 commit comments

Comments
 (0)