Skip to content

Commit ce32d57

Browse files
committed
[dead-code] Add RemoveParentDelegatingConstructorRector
1 parent 083c728 commit ce32d57

File tree

5 files changed

+201
-1
lines changed

5 files changed

+201
-1
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveParentDelegatingConstructorRector\Fixture;
4+
5+
use PhpParser\Node\Scalar\String_;
6+
7+
final class SomeClass extends String_
8+
{
9+
public function __construct($value, $attributes)
10+
{
11+
parent::__construct($value, $attributes);
12+
}
13+
}
14+
15+
?>
16+
-----
17+
<?php
18+
19+
namespace Rector\Tests\DeadCode\Rector\ClassMethod\RemoveParentDelegatingConstructorRector\Fixture;
20+
21+
use PhpParser\Node\Scalar\String_;
22+
23+
final class SomeClass extends String_
24+
{
25+
}
26+
27+
?>
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\RemoveParentDelegatingConstructorRector;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
11+
final class RemoveParentDelegatingConstructorRectorTest 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+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\Config\RectorConfig;
6+
use Rector\DeadCode\Rector\ClassMethod\RemoveParentDelegatingConstructorRector;
7+
8+
return RectorConfig::configure()
9+
->withRules([RemoveParentDelegatingConstructorRector::class]);
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
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 PhpParser\NodeVisitor;
10+
use PHPStan\Reflection\ClassReflection;
11+
use Rector\Enum\ObjectReference;
12+
use Rector\NodeAnalyzer\ArgsAnalyzer;
13+
use Rector\NodeAnalyzer\ExprAnalyzer;
14+
use Rector\PhpParser\Node\Value\ValueResolver;
15+
use Rector\PHPStan\ScopeFetcher;
16+
use Rector\Rector\AbstractRector;
17+
use Rector\Reflection\ReflectionResolver;
18+
use Rector\ValueObject\MethodName;
19+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
20+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
21+
22+
/**
23+
* @see \Rector\Tests\DeadCode\Rector\ClassMethod\RemoveParentDelegatingConstructorRector\RemoveParentDelegatingConstructorRectorTest
24+
*/
25+
final class RemoveParentDelegatingConstructorRector extends AbstractRector
26+
{
27+
public function __construct(
28+
private readonly ReflectionResolver $reflectionResolver,
29+
private readonly ArgsAnalyzer $argsAnalyzer,
30+
private readonly ValueResolver $valueResolver,
31+
private readonly ExprAnalyzer $exprAnalyzer
32+
) {
33+
}
34+
35+
public function getRuleDefinition(): RuleDefinition
36+
{
37+
return new RuleDefinition(
38+
'Remove constructor that only delegates call to parent class with same values',
39+
[
40+
new CodeSample(
41+
<<<'CODE_SAMPLE'
42+
class Node
43+
{
44+
public function __construct(array $attributes)
45+
{
46+
}
47+
}
48+
49+
class SomeParent extends Node
50+
{
51+
public function __construct(array $attributes)
52+
{
53+
parent::__construct($attributes);
54+
}
55+
}
56+
CODE_SAMPLE
57+
,
58+
<<<'CODE_SAMPLE'
59+
class Node
60+
{
61+
public function __construct(array $attributes)
62+
{
63+
}
64+
}
65+
66+
class SomeParent extends Node
67+
{
68+
}
69+
CODE_SAMPLE
70+
),
71+
]
72+
);
73+
}
74+
75+
/**
76+
* @return array<class-string<Node>>
77+
*/
78+
public function getNodeTypes(): array
79+
{
80+
return [ClassMethod::class];
81+
}
82+
83+
/**
84+
* @param ClassMethod $node
85+
*/
86+
public function refactor(Node $node): ?int
87+
{
88+
if (! $this->isName($node, MethodName::CONSTRUCT)) {
89+
return null;
90+
}
91+
92+
if (count($node->stmts) !== 1) {
93+
return null;
94+
}
95+
96+
$scope = ScopeFetcher::fetch($node);
97+
$classReflection = $scope->getClassReflection();
98+
if (! $classReflection->getParentClass() instanceof ClassReflection) {
99+
return null;
100+
}
101+
102+
$parentClassReflection = $classReflection->getParentClass();
103+
if (! $parentClassReflection->hasConstructor()) {
104+
return null;
105+
}
106+
107+
// $parentClassReflectionConstructor = $parentClassReflection->getConstructor();
108+
109+
$soleStmt = $node->stmts[0];
110+
if (! $soleStmt instanceof Node\Stmt\Expression) {
111+
return null;
112+
}
113+
114+
if (! $soleStmt->expr instanceof Node\Expr\StaticCall) {
115+
return null;
116+
}
117+
118+
$staticCall = $soleStmt->expr;
119+
if (! $this->isName($staticCall->class, ObjectReference::PARENT)) {
120+
return null;
121+
}
122+
123+
if (! $this->isName($staticCall->name, MethodName::CONSTRUCT)) {
124+
return null;
125+
}
126+
127+
$constructorParams = $node->getParams();
128+
$parentCallArgs = $staticCall->getArgs();
129+
130+
if (count($constructorParams) !== count($parentCallArgs)) {
131+
return null;
132+
}
133+
134+
return NodeVisitor::REMOVE_NODE;
135+
}
136+
}

src/Reporting/DeprecatedRulesReporter.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55
namespace Rector\Reporting;
66

7-
use Rector\PhpParserNode\FileNode;
87
use Rector\Configuration\Deprecation\Contract\DeprecatedInterface;
98
use Rector\Configuration\Option;
109
use Rector\Configuration\Parameter\SimpleParameterProvider;
1110
use Rector\Contract\PhpParser\Node\StmtsAwareInterface;
1211
use Rector\Contract\Rector\RectorInterface;
1312
use Rector\PhpParser\Enum\NodeGroup;
13+
use Rector\PhpParserNode\FileNode;
1414
use ReflectionMethod;
1515
use Symfony\Component\Console\Style\SymfonyStyle;
1616

0 commit comments

Comments
 (0)