Skip to content

Commit 4b9d483

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

File tree

7 files changed

+245
-0
lines changed

7 files changed

+245
-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,30 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector\Fixture;
4+
5+
class RemoveReturnClone
6+
{
7+
/**
8+
* @return void
9+
*/
10+
function __clone()
11+
{
12+
//
13+
}
14+
}
15+
16+
?>
17+
-----
18+
<?php
19+
20+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessReturnTagRector\Fixture;
21+
22+
class RemoveReturnClone
23+
{
24+
function __clone()
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 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: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
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 Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
10+
use Rector\Comments\NodeDocBlock\DocBlockUpdater;
11+
use Rector\Rector\AbstractRector;
12+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
13+
14+
/**
15+
* @see \Rector\Tests\DeadCode\Rector\ClassMethod\RemoveUselessVoidReturnFromDocblockOnVoidMagicMethodsRector\RemoveUselessVoidReturnFromDocblockVoidMagicMethodsRectorTest
16+
*/
17+
class RemoveUselessVoidReturnFromDocblockVoidMagicMethodsRector extends AbstractRector
18+
{
19+
public function __construct(
20+
private readonly DocBlockUpdater $docBlockUpdater,
21+
private readonly PhpDocInfoFactory $phpDocInfoFactory,
22+
) {
23+
}
24+
25+
public function getRuleDefinition(): RuleDefinition
26+
{
27+
return new RuleDefinition(
28+
'Remove useless @return void docblock from magic methods __construct, __destruct, and __clone',
29+
[
30+
new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(
31+
<<<'CODE_SAMPLE'
32+
class SomeClass
33+
{
34+
/**
35+
* @return void
36+
*/
37+
public function __construct() {}
38+
39+
/**
40+
* @return void
41+
*/
42+
public function __destruct() {}
43+
44+
/**
45+
* @return void
46+
*/
47+
public function __clone() {}
48+
}
49+
CODE_SAMPLE
50+
,
51+
<<<'CODE_SAMPLE'
52+
class SomeClass
53+
{
54+
public function __construct() {}
55+
56+
public function __destruct() {}
57+
58+
public function __clone() {}
59+
}
60+
CODE_SAMPLE
61+
),
62+
]
63+
);
64+
}
65+
66+
public function getNodeTypes(): array
67+
{
68+
return [ClassMethod::class];
69+
}
70+
71+
/**
72+
* @param ClassMethod $node
73+
*/
74+
public function refactor(Node $node): ?Node
75+
{
76+
if (! $node instanceof ClassMethod) {
77+
return null;
78+
}
79+
80+
$magicMethodNames = ['__construct', '__destruct', '__clone'];
81+
$methodName = $this->getName($node);
82+
if (! in_array($methodName, $magicMethodNames, true)) {
83+
return null;
84+
}
85+
86+
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
87+
88+
$returnTagValueNode = $phpDocInfo->getReturnTagValue();
89+
if ($returnTagValueNode === null) {
90+
return null;
91+
}
92+
93+
// Remove only if it's exactly @return void
94+
$returnType = (string) $returnTagValueNode->type;
95+
if (strtolower($returnType) !== 'void') {
96+
return null;
97+
}
98+
99+
$phpDocInfo->removeByType(get_class($returnTagValueNode));
100+
$this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($node);
101+
return $node;
102+
}
103+
}

0 commit comments

Comments
 (0)