|
19 | 19 | use PHPStan\Reflection\ClassReflection; |
20 | 20 | use PHPStan\Reflection\ReflectionProvider; |
21 | 21 | use Rector\Contract\Rector\ConfigurableRectorInterface; |
| 22 | +use Rector\DeadCode\NodeAnalyzer\ParentClassAnalyzer; |
22 | 23 | use Rector\NodeAnalyzer\ClassAnalyzer; |
23 | 24 | use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer; |
24 | 25 | use Rector\PhpParser\AstResolver; |
@@ -54,6 +55,7 @@ public function __construct( |
54 | 55 | private readonly PhpAttributeAnalyzer $phpAttributeAnalyzer, |
55 | 56 | private readonly AstResolver $astResolver, |
56 | 57 | private readonly ValueResolver $valueResolver, |
| 58 | + private readonly ParentClassAnalyzer $parentClassAnalyzer, |
57 | 59 | ) { |
58 | 60 | } |
59 | 61 |
|
@@ -135,6 +137,11 @@ public function refactor(Node $node): ?Node |
135 | 137 | return null; |
136 | 138 | } |
137 | 139 |
|
| 140 | + // skip if no parents, nor traits, nor strinables are involved |
| 141 | + if ($node->extends === null && $node->getTraitUses() === [] && ! $this->implementsStringable($node)) { |
| 142 | + return null; |
| 143 | + } |
| 144 | + |
138 | 145 | $className = (string) $this->getName($node); |
139 | 146 | if (! $this->reflectionProvider->hasClass($className)) { |
140 | 147 | return null; |
@@ -227,12 +234,18 @@ private function shouldSkipClassMethod(ClassMethod $classMethod): bool |
227 | 234 | return true; |
228 | 235 | } |
229 | 236 |
|
| 237 | + // nothing to override |
230 | 238 | if ($classMethod->isPrivate()) { |
231 | 239 | return true; |
232 | 240 | } |
233 | 241 |
|
234 | 242 | // ignore if it already uses the attribute |
235 | | - return $this->phpAttributeAnalyzer->hasPhpAttribute($classMethod, self::OVERRIDE_CLASS); |
| 243 | + if ($this->phpAttributeAnalyzer->hasPhpAttribute($classMethod, self::OVERRIDE_CLASS)) { |
| 244 | + return true; |
| 245 | + } |
| 246 | + |
| 247 | + // skip test setup method override, as rather clutters the code than helps |
| 248 | + return $this->isName($classMethod, 'setUp') && $this->parentClassAnalyzer->hasParentCall($classMethod); |
236 | 249 | } |
237 | 250 |
|
238 | 251 | private function shouldSkipParentClassMethod(ClassReflection $parentClassReflection, ClassMethod $classMethod): bool |
@@ -284,4 +297,15 @@ private function shouldSkipParentClassMethod(ClassReflection $parentClassReflect |
284 | 297 |
|
285 | 298 | return false; |
286 | 299 | } |
| 300 | + |
| 301 | + private function implementsStringable(Class_ $class): bool |
| 302 | + { |
| 303 | + foreach ($class->implements as $implement) { |
| 304 | + if ($this->isName($implement, 'Stringable')) { |
| 305 | + return true; |
| 306 | + } |
| 307 | + } |
| 308 | + |
| 309 | + return false; |
| 310 | + } |
287 | 311 | } |
0 commit comments