Skip to content

Commit

Permalink
[DowngradePhp84] Downgrade RoundingMode enum (#260)
Browse files Browse the repository at this point in the history
* [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]>
  • Loading branch information
jorgsowa and samsonasik authored Dec 20, 2024
1 parent 7b990bd commit 183795c
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 0 deletions.
2 changes: 2 additions & 0 deletions config/set/downgrade-php84.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\DowngradePhp84\Rector\FuncCall\DowngradeRoundingModeEnumRector;
use Rector\DowngradePhp84\Rector\MethodCall\DowngradeNewMethodCallWithoutParenthesesRector;
use Rector\ValueObject\PhpVersion;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->phpVersion(PhpVersion::PHP_83);
$rectorConfig->rules([
DowngradeNewMethodCallWithoutParenthesesRector::class,
DowngradeRoundingModeEnumRector::class,
]);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\DowngradePhp84\Rector\FuncCall\DowngradeRoundingModeEnumRector;

use Iterator;
use PHPUnit\Framework\Attributes\DataProvider;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;

final class DowngradeRoundingModeEnumRectorTest extends AbstractRectorTestCase
{
#[DataProvider('provideData')]
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}

public static function provideData(): Iterator
{
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
}

public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Rector\Tests\Php84\Rector\FuncCall\RoundingModeEnumRector;

round(1.5, 0);
round(1.5);
round(1.5, 0, \RoundingMode::HalfAwayFromZero);
round(1.5, 0, \RoundingMode::HalfTowardsZero);
round(1.5, 0, \RoundingMode::HalfEven);
round(1.5, 0, \RoundingMode::HalfOdd);
round(1.5, 0, \RoundingMode::TowardsZero);
round(1.5, 0, \RoundingMode::AwayFromZero);
round(1.5, 0, \RoundingMode::NegativeInfinity);
round(1.5, 0, \RoundingMode::PositiveInfinity);
round(1.5, 0, 'invalid');
round(1.5, 0, PHP_INT_MAX);

?>
-----
<?php

namespace Rector\Tests\Php84\Rector\FuncCall\RoundingModeEnumRector;

round(1.5, 0);
round(1.5);
round(1.5, 0, \PHP_ROUND_HALF_UP);
round(1.5, 0, \PHP_ROUND_HALF_DOWN);
round(1.5, 0, \PHP_ROUND_HALF_EVEN);
round(1.5, 0, \PHP_ROUND_HALF_ODD);
round(1.5, 0, \RoundingMode::TowardsZero);
round(1.5, 0, \RoundingMode::AwayFromZero);
round(1.5, 0, \RoundingMode::NegativeInfinity);
round(1.5, 0, \RoundingMode::PositiveInfinity);
round(1.5, 0, 'invalid');
round(1.5, 0, PHP_INT_MAX);

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Rector\Tests\Php84\Rector\FuncCall\RoundingModeEnumRector;

use RoundingMode;

round(1.5, 0, RoundingMode::HalfAwayFromZero);

?>
-----
<?php

namespace Rector\Tests\Php84\Rector\FuncCall\RoundingModeEnumRector;

use RoundingMode;

round(1.5, 0, \PHP_ROUND_HALF_UP);

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

round(1.5, 0, RoundingMode::HalfAwayFromZero);

?>
-----
<?php

round(1.5, 0, \PHP_ROUND_HALF_UP);

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Rector\Tests\Php84\Rector\FuncCall\RoundingModeEnumRector;


$mode = \RoundingMode::HalfTowardsZero;

round(1.5, 0, $mode);

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\DowngradePhp84\Rector\FuncCall\DowngradeRoundingModeEnumRector;

return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(DowngradeRoundingModeEnumRector::class);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

declare(strict_types=1);

namespace Rector\DowngradePhp84\Rector\FuncCall;

use PhpParser\Node;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name\FullyQualified;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @changelog wiki.php.net/rfc/correctly_name_the_rounding_mode_and_make_it_an_enum
*
* @see \Rector\Tests\DowngradePhp84\Rector\FuncCall\DowngradeRoundingModeEnumRector\DowngradeRoundingModeEnumRectorTest
*/
final class DowngradeRoundingModeEnumRector extends AbstractRector
{
public function getNodeTypes(): array
{
return [FuncCall::class];
}

public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Replace RoundingMode enum to rounding mode constant in round()',
[
new CodeSample(
<<<'CODE_SAMPLE'
round(1.5, 0, RoundingMode::HalfAwayFromZero);
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
round(1.5, 0, PHP_ROUND_HALF_UP);
CODE_SAMPLE
),
]
);
}

/**
* @param MethodCall $node
*/
public function refactor(Node $node): ?Node
{
if (! $this->isName($node, 'round')) {
return null;
}

if ($node->isFirstClassCallable()) {
return null;
}

$args = $node->getArgs();

if (count($args) !== 3) {
return null;
}

if (! isset($args[2])) {
return null;
}

$modeArg = $args[2]->value;
$hasChanged = false;
if ($modeArg instanceof ClassConstFetch && $modeArg->class instanceof FullyQualified && $this->isName(
$modeArg->class,
'RoundingMode'
)) {
if (! $modeArg->name instanceof Identifier) {
return null;
}

$constantName = match ($modeArg->name->name) {
'HalfAwayFromZero' => 'PHP_ROUND_HALF_UP',
'HalfTowardsZero' => 'PHP_ROUND_HALF_DOWN',
'HalfEven' => 'PHP_ROUND_HALF_EVEN',
'HalfOdd' => 'PHP_ROUND_HALF_ODD',
default => null,
};
if ($constantName === null) {
return null;
}

$args[2]->value = new ConstFetch(new FullyQualified($constantName));
$hasChanged = true;
}

if ($hasChanged) {
return $node;
}

return null;
}
}

0 comments on commit 183795c

Please sign in to comment.