Skip to content

Commit 183795c

Browse files
jorgsowasamsonasik
andauthored
[DowngradePhp84] Downgrade RoundingMode enum (#260)
* [DowngradePhp84] Downgrade RoundingMode enum * Review comments * Fixed description of rule * Registered rule to downgrade-php84 ruleset * Used FullyQualified for constant name * Fixed PHPStan issue * Formatting * run rector once more * ensure FullyQualified check * add no namespace fixture * from use --------- Co-authored-by: Abdul Malik Ikhsan <[email protected]>
1 parent 7b990bd commit 183795c

File tree

8 files changed

+219
-0
lines changed

8 files changed

+219
-0
lines changed

config/set/downgrade-php84.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
declare(strict_types=1);
44

55
use Rector\Config\RectorConfig;
6+
use Rector\DowngradePhp84\Rector\FuncCall\DowngradeRoundingModeEnumRector;
67
use Rector\DowngradePhp84\Rector\MethodCall\DowngradeNewMethodCallWithoutParenthesesRector;
78
use Rector\ValueObject\PhpVersion;
89

910
return static function (RectorConfig $rectorConfig): void {
1011
$rectorConfig->phpVersion(PhpVersion::PHP_83);
1112
$rectorConfig->rules([
1213
DowngradeNewMethodCallWithoutParenthesesRector::class,
14+
DowngradeRoundingModeEnumRector::class,
1315
]);
1416
};
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\DowngradePhp84\Rector\FuncCall\DowngradeRoundingModeEnumRector;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
11+
final class DowngradeRoundingModeEnumRectorTest 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: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php84\Rector\FuncCall\RoundingModeEnumRector;
4+
5+
round(1.5, 0);
6+
round(1.5);
7+
round(1.5, 0, \RoundingMode::HalfAwayFromZero);
8+
round(1.5, 0, \RoundingMode::HalfTowardsZero);
9+
round(1.5, 0, \RoundingMode::HalfEven);
10+
round(1.5, 0, \RoundingMode::HalfOdd);
11+
round(1.5, 0, \RoundingMode::TowardsZero);
12+
round(1.5, 0, \RoundingMode::AwayFromZero);
13+
round(1.5, 0, \RoundingMode::NegativeInfinity);
14+
round(1.5, 0, \RoundingMode::PositiveInfinity);
15+
round(1.5, 0, 'invalid');
16+
round(1.5, 0, PHP_INT_MAX);
17+
18+
?>
19+
-----
20+
<?php
21+
22+
namespace Rector\Tests\Php84\Rector\FuncCall\RoundingModeEnumRector;
23+
24+
round(1.5, 0);
25+
round(1.5);
26+
round(1.5, 0, \PHP_ROUND_HALF_UP);
27+
round(1.5, 0, \PHP_ROUND_HALF_DOWN);
28+
round(1.5, 0, \PHP_ROUND_HALF_EVEN);
29+
round(1.5, 0, \PHP_ROUND_HALF_ODD);
30+
round(1.5, 0, \RoundingMode::TowardsZero);
31+
round(1.5, 0, \RoundingMode::AwayFromZero);
32+
round(1.5, 0, \RoundingMode::NegativeInfinity);
33+
round(1.5, 0, \RoundingMode::PositiveInfinity);
34+
round(1.5, 0, 'invalid');
35+
round(1.5, 0, PHP_INT_MAX);
36+
37+
?>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php84\Rector\FuncCall\RoundingModeEnumRector;
4+
5+
use RoundingMode;
6+
7+
round(1.5, 0, RoundingMode::HalfAwayFromZero);
8+
9+
?>
10+
-----
11+
<?php
12+
13+
namespace Rector\Tests\Php84\Rector\FuncCall\RoundingModeEnumRector;
14+
15+
use RoundingMode;
16+
17+
round(1.5, 0, \PHP_ROUND_HALF_UP);
18+
19+
?>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
round(1.5, 0, RoundingMode::HalfAwayFromZero);
4+
5+
?>
6+
-----
7+
<?php
8+
9+
round(1.5, 0, \PHP_ROUND_HALF_UP);
10+
11+
?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php84\Rector\FuncCall\RoundingModeEnumRector;
4+
5+
6+
$mode = \RoundingMode::HalfTowardsZero;
7+
8+
round(1.5, 0, $mode);
9+
10+
?>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\Config\RectorConfig;
6+
use Rector\DowngradePhp84\Rector\FuncCall\DowngradeRoundingModeEnumRector;
7+
8+
return static function (RectorConfig $rectorConfig): void {
9+
$rectorConfig->rule(DowngradeRoundingModeEnumRector::class);
10+
};
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\DowngradePhp84\Rector\FuncCall;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Expr\ClassConstFetch;
9+
use PhpParser\Node\Expr\ConstFetch;
10+
use PhpParser\Node\Expr\FuncCall;
11+
use PhpParser\Node\Expr\MethodCall;
12+
use PhpParser\Node\Identifier;
13+
use PhpParser\Node\Name\FullyQualified;
14+
use Rector\Rector\AbstractRector;
15+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
16+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
17+
18+
/**
19+
* @changelog wiki.php.net/rfc/correctly_name_the_rounding_mode_and_make_it_an_enum
20+
*
21+
* @see \Rector\Tests\DowngradePhp84\Rector\FuncCall\DowngradeRoundingModeEnumRector\DowngradeRoundingModeEnumRectorTest
22+
*/
23+
final class DowngradeRoundingModeEnumRector extends AbstractRector
24+
{
25+
public function getNodeTypes(): array
26+
{
27+
return [FuncCall::class];
28+
}
29+
30+
public function getRuleDefinition(): RuleDefinition
31+
{
32+
return new RuleDefinition(
33+
'Replace RoundingMode enum to rounding mode constant in round()',
34+
[
35+
new CodeSample(
36+
<<<'CODE_SAMPLE'
37+
round(1.5, 0, RoundingMode::HalfAwayFromZero);
38+
CODE_SAMPLE
39+
,
40+
<<<'CODE_SAMPLE'
41+
round(1.5, 0, PHP_ROUND_HALF_UP);
42+
CODE_SAMPLE
43+
),
44+
]
45+
);
46+
}
47+
48+
/**
49+
* @param MethodCall $node
50+
*/
51+
public function refactor(Node $node): ?Node
52+
{
53+
if (! $this->isName($node, 'round')) {
54+
return null;
55+
}
56+
57+
if ($node->isFirstClassCallable()) {
58+
return null;
59+
}
60+
61+
$args = $node->getArgs();
62+
63+
if (count($args) !== 3) {
64+
return null;
65+
}
66+
67+
if (! isset($args[2])) {
68+
return null;
69+
}
70+
71+
$modeArg = $args[2]->value;
72+
$hasChanged = false;
73+
if ($modeArg instanceof ClassConstFetch && $modeArg->class instanceof FullyQualified && $this->isName(
74+
$modeArg->class,
75+
'RoundingMode'
76+
)) {
77+
if (! $modeArg->name instanceof Identifier) {
78+
return null;
79+
}
80+
81+
$constantName = match ($modeArg->name->name) {
82+
'HalfAwayFromZero' => 'PHP_ROUND_HALF_UP',
83+
'HalfTowardsZero' => 'PHP_ROUND_HALF_DOWN',
84+
'HalfEven' => 'PHP_ROUND_HALF_EVEN',
85+
'HalfOdd' => 'PHP_ROUND_HALF_ODD',
86+
default => null,
87+
};
88+
if ($constantName === null) {
89+
return null;
90+
}
91+
92+
$args[2]->value = new ConstFetch(new FullyQualified($constantName));
93+
$hasChanged = true;
94+
}
95+
96+
if ($hasChanged) {
97+
return $node;
98+
}
99+
100+
return null;
101+
}
102+
}

0 commit comments

Comments
 (0)