Skip to content

Commit 5f00ac7

Browse files
committed
[DeadCode] Add RemoveUselessTernaryRector
1 parent ffbf103 commit 5f00ac7

File tree

11 files changed

+263
-0
lines changed

11 files changed

+263
-0
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\Ternary\RemoveUselessTernaryRector\Fixture;
4+
5+
class Fixture
6+
{
7+
public function go(bool $value)
8+
{
9+
return $value ?: false;
10+
}
11+
}
12+
13+
?>
14+
-----
15+
<?php
16+
17+
namespace Rector\Tests\DeadCode\Rector\Ternary\RemoveUselessTernaryRector\Fixture;
18+
19+
class Fixture
20+
{
21+
public function go(bool $value)
22+
{
23+
return $value;
24+
}
25+
}
26+
27+
?>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\Ternary\RemoveUselessTernaryRector\Fixture;
4+
5+
class SkipDifferentType
6+
{
7+
public function go(bool $value)
8+
{
9+
return $value ?: 0;
10+
}
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\Ternary\RemoveUselessTernaryRector\Fixture;
4+
5+
class SkipUnion
6+
{
7+
public function go(bool|string $value)
8+
{
9+
return $value ?: false;
10+
}
11+
}
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\Ternary\RemoveUselessTernaryRector\Fixture;
4+
5+
class WithArrayEmpty
6+
{
7+
public function go(array $value)
8+
{
9+
return $value ?: [];
10+
}
11+
}
12+
13+
?>
14+
-----
15+
<?php
16+
17+
namespace Rector\Tests\DeadCode\Rector\Ternary\RemoveUselessTernaryRector\Fixture;
18+
19+
class WithArrayEmpty
20+
{
21+
public function go(array $value)
22+
{
23+
return $value;
24+
}
25+
}
26+
27+
?>
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\Ternary\RemoveUselessTernaryRector\Fixture;
4+
5+
class WithIfEqual
6+
{
7+
public function go(bool $value)
8+
{
9+
return $value ? $value : false;
10+
}
11+
}
12+
13+
?>
14+
-----
15+
<?php
16+
17+
namespace Rector\Tests\DeadCode\Rector\Ternary\RemoveUselessTernaryRector\Fixture;
18+
19+
class WithIfEqual
20+
{
21+
public function go(bool $value)
22+
{
23+
return $value;
24+
}
25+
}
26+
27+
?>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Rector\Tests\DeadCode\Rector\Ternary\RemoveUselessTernaryRector\Fixture;
4+
5+
class WithIfNotEqual
6+
{
7+
public function go(bool $value)
8+
{
9+
return $value ? 1 : false;
10+
}
11+
}
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\Ternary\RemoveUselessTernaryRector\Fixture;
4+
5+
class WithIntegerZero
6+
{
7+
public function go(int $value)
8+
{
9+
return $value ?: 0;
10+
}
11+
}
12+
13+
?>
14+
-----
15+
<?php
16+
17+
namespace Rector\Tests\DeadCode\Rector\Ternary\RemoveUselessTernaryRector\Fixture;
18+
19+
class WithIntegerZero
20+
{
21+
public function go(int $value)
22+
{
23+
return $value;
24+
}
25+
}
26+
27+
?>
Lines changed: 28 additions & 0 deletions
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\Ternary\RemoveUselessTernaryRector;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
11+
final class RemoveUselessTernaryRectorTest 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\Ternary\RemoveUselessTernaryRector;
7+
8+
return RectorConfig::configure()
9+
->withRules([RemoveUselessTernaryRector::class]);
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\DeadCode\Rector\Ternary;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Expr;
9+
use PhpParser\Node\Expr\Array_;
10+
use PhpParser\Node\Expr\Ternary;
11+
use PhpParser\Node\Scalar\Int_;
12+
use PHPStan\Type\ArrayType;
13+
use PHPStan\Type\BooleanType;
14+
use PHPStan\Type\IntegerType;
15+
use Rector\PhpParser\Node\Value\ValueResolver;
16+
use Rector\Rector\AbstractRector;
17+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
18+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
19+
20+
/**
21+
* @see \Rector\Tests\DeadCode\Rector\Ternary\RemoveUselessTernaryRector\RemoveUselessTernaryRectorTest
22+
*/
23+
final class RemoveUselessTernaryRector extends AbstractRector
24+
{
25+
public function __construct(
26+
private readonly ValueResolver $valueResolver
27+
) {
28+
}
29+
30+
public function getRuleDefinition(): RuleDefinition
31+
{
32+
return new RuleDefinition('Remove useless ternary if fallback is falsey of left code', [
33+
new CodeSample(
34+
<<<'CODE_SAMPLE'
35+
function go(bool $value)
36+
{
37+
return $value ?: false;
38+
}
39+
CODE_SAMPLE
40+
,
41+
<<<'CODE_SAMPLE'
42+
function go(bool $value)
43+
{
44+
return $value;
45+
}
46+
CODE_SAMPLE
47+
),
48+
]);
49+
}
50+
51+
/**
52+
* @return array<class-string<Node>>
53+
*/
54+
public function getNodeTypes(): array
55+
{
56+
return [Ternary::class];
57+
}
58+
59+
/**
60+
* @param Ternary $node
61+
*/
62+
public function refactor(Node $node): ?Node
63+
{
64+
if ($node->if instanceof Expr && ! $this->nodeComparator->areNodesEqual($node->if, $node->cond)) {
65+
return null;
66+
}
67+
68+
$nativeType = $this->nodeTypeResolver->getNativeType($node->cond);
69+
if ($nativeType instanceof BooleanType && $this->valueResolver->isFalse($node->else)) {
70+
return $node->cond;
71+
}
72+
73+
if ($nativeType instanceof ArrayType && $node->else instanceof Array_ && $node->else->items === []) {
74+
return $node->cond;
75+
}
76+
77+
if ($nativeType instanceof IntegerType && $node->else instanceof Int_ && $node->else->value === 0) {
78+
return $node->cond;
79+
}
80+
81+
return null;
82+
}
83+
}

0 commit comments

Comments
 (0)