Skip to content

Commit 434f1db

Browse files
committed
[php 8.3] exclude test case setup from override attribute, as not helpful
1 parent a65318b commit 434f1db

File tree

4 files changed

+103
-3
lines changed

4 files changed

+103
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php83\Rector\ClassMethod\AddOverrideAttributeToOverriddenMethodsRector\Fixture;
4+
5+
use Rector\Tests\Php83\Rector\ClassMethod\AddOverrideAttributeToOverriddenMethodsRector\Source\SomeAbstractTest;
6+
7+
final class SkipSetupPHPUnitAsClutter extends SomeAbstractTest
8+
{
9+
protected function setUp(): void
10+
{
11+
parent::setUp();
12+
13+
$someValue = 1;
14+
}
15+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php83\Rector\ClassMethod\AddOverrideAttributeToOverriddenMethodsRector\Source;
4+
5+
use PHPUnit\Framework\TestCase;
6+
7+
abstract class SomeAbstractTest extends TestCase
8+
{
9+
protected function setUp(): void
10+
{
11+
$value = 1000;
12+
}
13+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\DeadCode\NodeAnalyzer;
6+
7+
use PhpParser\Node\Expr\StaticCall;
8+
use PhpParser\Node\Stmt\ClassMethod;
9+
use PhpParser\Node\Stmt\Expression;
10+
use Rector\NodeNameResolver\NodeNameResolver;
11+
12+
final readonly class ParentClassAnalyzer
13+
{
14+
public function __construct(
15+
private NodeNameResolver $nodeNameResolver,
16+
) {
17+
18+
}
19+
20+
public function hasParentCall(ClassMethod $classMethod): bool
21+
{
22+
if ($classMethod->isAbstract()) {
23+
return false;
24+
}
25+
26+
if ($classMethod->isPrivate()) {
27+
return false;
28+
}
29+
30+
$classMethodName = $classMethod->name->name;
31+
32+
foreach ($classMethod->stmts as $stmt) {
33+
if (! $stmt instanceof Expression) {
34+
continue;
35+
}
36+
37+
$expr = $stmt->expr;
38+
if (! $expr instanceof StaticCall) {
39+
continue;
40+
}
41+
42+
if (! $this->nodeNameResolver->isName($expr->class, 'parent')) {
43+
continue;
44+
}
45+
46+
if ($this->nodeNameResolver->isName($expr->name, $classMethodName)) {
47+
return true;
48+
}
49+
}
50+
51+
return false;
52+
}
53+
}

rules/Php83/Rector/ClassMethod/AddOverrideAttributeToOverriddenMethodsRector.php

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use PHPStan\Reflection\ClassReflection;
2020
use PHPStan\Reflection\ReflectionProvider;
2121
use Rector\Contract\Rector\ConfigurableRectorInterface;
22+
use Rector\DeadCode\NodeAnalyzer\ParentClassAnalyzer;
2223
use Rector\NodeAnalyzer\ClassAnalyzer;
2324
use Rector\Php80\NodeAnalyzer\PhpAttributeAnalyzer;
2425
use Rector\PhpParser\AstResolver;
@@ -54,6 +55,7 @@ public function __construct(
5455
private readonly PhpAttributeAnalyzer $phpAttributeAnalyzer,
5556
private readonly AstResolver $astResolver,
5657
private readonly ValueResolver $valueResolver,
58+
private readonly ParentClassAnalyzer $parentClassAnalyzer,
5759
) {
5860
}
5961

@@ -135,8 +137,8 @@ public function refactor(Node $node): ?Node
135137
return null;
136138
}
137139

138-
// skip if no parents are involved
139-
if ($node->extends === null) {
140+
// skip if no parents, nor traits, nor strinables are involved
141+
if ($node->extends === null && $node->getTraitUses() === [] && ! $this->implementsStringable($node)) {
140142
return null;
141143
}
142144

@@ -232,12 +234,18 @@ private function shouldSkipClassMethod(ClassMethod $classMethod): bool
232234
return true;
233235
}
234236

237+
// nothing to override
235238
if ($classMethod->isPrivate()) {
236239
return true;
237240
}
238241

239242
// ignore if it already uses the attribute
240-
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);
241249
}
242250

243251
private function shouldSkipParentClassMethod(ClassReflection $parentClassReflection, ClassMethod $classMethod): bool
@@ -289,4 +297,15 @@ private function shouldSkipParentClassMethod(ClassReflection $parentClassReflect
289297

290298
return false;
291299
}
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+
}
292311
}

0 commit comments

Comments
 (0)