|
5 | 5 | namespace Rector\DeadCode\Rector\ClassMethod; |
6 | 6 |
|
7 | 7 | use PhpParser\Node; |
| 8 | +use PhpParser\Node\Arg; |
| 9 | +use PhpParser\Node\Expr\StaticCall; |
| 10 | +use PhpParser\Node\Stmt; |
8 | 11 | use PhpParser\Node\Stmt\ClassMethod; |
| 12 | +use PhpParser\Node\Stmt\Expression; |
9 | 13 | use PhpParser\NodeVisitor; |
10 | 14 | use PHPStan\Reflection\ClassReflection; |
11 | 15 | use Rector\Enum\ObjectReference; |
12 | | -use Rector\NodeAnalyzer\ArgsAnalyzer; |
13 | | -use Rector\NodeAnalyzer\ExprAnalyzer; |
14 | | -use Rector\PhpParser\Node\Value\ValueResolver; |
15 | 16 | use Rector\PHPStan\ScopeFetcher; |
16 | 17 | use Rector\Rector\AbstractRector; |
17 | | -use Rector\Reflection\ReflectionResolver; |
18 | 18 | use Rector\ValueObject\MethodName; |
19 | 19 | use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; |
20 | 20 | use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; |
|
24 | 24 | */ |
25 | 25 | final class RemoveParentDelegatingConstructorRector extends AbstractRector |
26 | 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 | 27 | public function getRuleDefinition(): RuleDefinition |
36 | 28 | { |
37 | 29 | return new RuleDefinition( |
@@ -93,44 +85,82 @@ public function refactor(Node $node): ?int |
93 | 85 | return null; |
94 | 86 | } |
95 | 87 |
|
96 | | - $scope = ScopeFetcher::fetch($node); |
97 | | - $classReflection = $scope->getClassReflection(); |
98 | | - if (! $classReflection->getParentClass() instanceof ClassReflection) { |
| 88 | + if (! $this->hasParentClassWithConstructor($node)) { |
99 | 89 | return null; |
100 | 90 | } |
101 | 91 |
|
102 | | - $parentClassReflection = $classReflection->getParentClass(); |
103 | | - if (! $parentClassReflection->hasConstructor()) { |
| 92 | + $soleStmt = $node->stmts[0]; |
| 93 | + $parentCallArgs = $this->matchParentConstructorCallArgs($soleStmt); |
| 94 | + if ($parentCallArgs === null) { |
104 | 95 | return null; |
105 | 96 | } |
106 | 97 |
|
107 | | - // $parentClassReflectionConstructor = $parentClassReflection->getConstructor(); |
108 | | - |
109 | | - $soleStmt = $node->stmts[0]; |
110 | | - if (! $soleStmt instanceof Node\Stmt\Expression) { |
| 98 | + $constructorParams = $node->getParams(); |
| 99 | + if (count($constructorParams) !== count($parentCallArgs)) { |
111 | 100 | return null; |
112 | 101 | } |
113 | 102 |
|
114 | | - if (! $soleStmt->expr instanceof Node\Expr\StaticCall) { |
| 103 | + // match passed names in the same order |
| 104 | + $paramNames = []; |
| 105 | + foreach ($constructorParams as $param) { |
| 106 | + $paramNames[] = $this->getName($param->var); |
| 107 | + } |
| 108 | + |
| 109 | + $argNames = []; |
| 110 | + foreach ($parentCallArgs as $parentCallArg) { |
| 111 | + $argValue = $parentCallArg->value; |
| 112 | + if (! $argValue instanceof Node\Expr\Variable) { |
| 113 | + return null; |
| 114 | + } |
| 115 | + |
| 116 | + $argNames[] = $this->getName($argValue); |
| 117 | + } |
| 118 | + |
| 119 | + if ($paramNames !== $argNames) { |
115 | 120 | return null; |
116 | 121 | } |
117 | 122 |
|
118 | | - $staticCall = $soleStmt->expr; |
119 | | - if (! $this->isName($staticCall->class, ObjectReference::PARENT)) { |
| 123 | + return NodeVisitor::REMOVE_NODE; |
| 124 | + } |
| 125 | + |
| 126 | + private function hasParentClassWithConstructor(ClassMethod $classMethod): bool |
| 127 | + { |
| 128 | + $scope = ScopeFetcher::fetch($classMethod); |
| 129 | + |
| 130 | + $classReflection = $scope->getClassReflection(); |
| 131 | + |
| 132 | + if (! $classReflection->getParentClass() instanceof ClassReflection) { |
| 133 | + return false; |
| 134 | + } |
| 135 | + |
| 136 | + $parentClassReflection = $classReflection->getParentClass(); |
| 137 | + return $parentClassReflection->hasConstructor(); |
| 138 | + } |
| 139 | + |
| 140 | + /** |
| 141 | + * Looking for parent::__construct() |
| 142 | + * |
| 143 | + * @return Arg[]|null |
| 144 | + */ |
| 145 | + private function matchParentConstructorCallArgs(Stmt $stmt): ?array |
| 146 | + { |
| 147 | + if (! $stmt instanceof Expression) { |
120 | 148 | return null; |
121 | 149 | } |
122 | 150 |
|
123 | | - if (! $this->isName($staticCall->name, MethodName::CONSTRUCT)) { |
| 151 | + if (! $stmt->expr instanceof StaticCall) { |
124 | 152 | return null; |
125 | 153 | } |
126 | 154 |
|
127 | | - $constructorParams = $node->getParams(); |
128 | | - $parentCallArgs = $staticCall->getArgs(); |
| 155 | + $staticCall = $stmt->expr; |
| 156 | + if (! $this->isName($staticCall->class, ObjectReference::PARENT)) { |
| 157 | + return null; |
| 158 | + } |
129 | 159 |
|
130 | | - if (count($constructorParams) !== count($parentCallArgs)) { |
| 160 | + if (! $this->isName($staticCall->name, MethodName::CONSTRUCT)) { |
131 | 161 | return null; |
132 | 162 | } |
133 | 163 |
|
134 | | - return NodeVisitor::REMOVE_NODE; |
| 164 | + return $staticCall->getArgs(); |
135 | 165 | } |
136 | 166 | } |
0 commit comments