From a72a02188ab22b7beeb94dd1ffda79bdfffd64c4 Mon Sep 17 00:00:00 2001 From: Jorg Adam Sowa Date: Fri, 20 Dec 2024 01:14:41 +0100 Subject: [PATCH] [Php84] Add rule for RoundingMode enum (#6369) * Add new rule for rounding modes in PHP 8.4 * Added namespace to test * Improve tests * Fixed namespace * Skip first class callable * Used FullyQualified instead of name * Added RoundingModeEnumRector to php84.php * Removed constructor * Return null for no change * cs * cs --------- Co-authored-by: Abdul Malik Ikhsan --- config/set/php84.php | 3 +- .../Fixture/rounding_constants.php.inc | 29 ++++++ .../skip_indirect_use_of_constants.php.inc | 10 ++ .../RoundingModeEnumRectorTest.php | 28 ++++++ .../config/configured_rule.php | 13 +++ .../FuncCall/RoundingModeEnumRector.php | 99 +++++++++++++++++++ src/ValueObject/PhpVersionFeature.php | 6 ++ 7 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/Fixture/rounding_constants.php.inc create mode 100644 rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/Fixture/skip_indirect_use_of_constants.php.inc create mode 100644 rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/RoundingModeEnumRectorTest.php create mode 100644 rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/config/configured_rule.php create mode 100644 rules/Php84/Rector/FuncCall/RoundingModeEnumRector.php diff --git a/config/set/php84.php b/config/set/php84.php index 8a015ad0d4c..3231419d58a 100644 --- a/config/set/php84.php +++ b/config/set/php84.php @@ -3,8 +3,9 @@ declare(strict_types=1); use Rector\Config\RectorConfig; +use Rector\Php84\Rector\FuncCall\RoundingModeEnumRector; use Rector\Php84\Rector\Param\ExplicitNullableParamTypeRector; return static function (RectorConfig $rectorConfig): void { - $rectorConfig->rules([ExplicitNullableParamTypeRector::class]); + $rectorConfig->rules([ExplicitNullableParamTypeRector::class, RoundingModeEnumRector::class]); }; diff --git a/rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/Fixture/rounding_constants.php.inc b/rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/Fixture/rounding_constants.php.inc new file mode 100644 index 00000000000..2a70b9d247d --- /dev/null +++ b/rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/Fixture/rounding_constants.php.inc @@ -0,0 +1,29 @@ + +----- + diff --git a/rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/Fixture/skip_indirect_use_of_constants.php.inc b/rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/Fixture/skip_indirect_use_of_constants.php.inc new file mode 100644 index 00000000000..be3441a4fa3 --- /dev/null +++ b/rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/Fixture/skip_indirect_use_of_constants.php.inc @@ -0,0 +1,10 @@ + diff --git a/rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/RoundingModeEnumRectorTest.php b/rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/RoundingModeEnumRectorTest.php new file mode 100644 index 00000000000..51c2e48eb1f --- /dev/null +++ b/rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/RoundingModeEnumRectorTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFilesFromDirectory(__DIR__ . '/Fixture'); + } + + public function provideConfigFilePath(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/config/configured_rule.php b/rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/config/configured_rule.php new file mode 100644 index 00000000000..68ca3b74849 --- /dev/null +++ b/rules-tests/Php84/Rector/FuncCall/RoundingModeEnumRector/config/configured_rule.php @@ -0,0 +1,13 @@ +rule(RoundingModeEnumRector::class); + + $rectorConfig->phpVersion(PhpVersion::PHP_84); +}; diff --git a/rules/Php84/Rector/FuncCall/RoundingModeEnumRector.php b/rules/Php84/Rector/FuncCall/RoundingModeEnumRector.php new file mode 100644 index 00000000000..fac429f4a55 --- /dev/null +++ b/rules/Php84/Rector/FuncCall/RoundingModeEnumRector.php @@ -0,0 +1,99 @@ +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 ConstFetch) { + $enumCase = match ($modeArg->name->toString()) { + 'PHP_ROUND_HALF_UP' => 'HalfAwayFromZero', + 'PHP_ROUND_HALF_DOWN' => 'HalfTowardsZero', + 'PHP_ROUND_HALF_EVEN' => 'HalfEven', + 'PHP_ROUND_HALF_ODD' => 'HalfOdd', + default => null, + }; + + if ($enumCase === null) { + return null; + } + + $args[2]->value = new ClassConstFetch(new FullyQualified('RoundingMode'), $enumCase); + $hasChanged = true; + } + + if ($hasChanged) { + return $node; + } + + return null; + } + + public function provideMinPhpVersion(): int + { + return PhpVersionFeature::ROUNDING_MODES; + } +} diff --git a/src/ValueObject/PhpVersionFeature.php b/src/ValueObject/PhpVersionFeature.php index 9940a51c135..eff2e23cd07 100644 --- a/src/ValueObject/PhpVersionFeature.php +++ b/src/ValueObject/PhpVersionFeature.php @@ -684,6 +684,12 @@ final class PhpVersionFeature */ public const DEPRECATE_IMPLICIT_NULLABLE_PARAM_TYPE = PhpVersion::PHP_84; + /** + * @see https://wiki.php.net/rfc/correctly_name_the_rounding_mode_and_make_it_an_enum + * @var int + */ + public const ROUNDING_MODES = PhpVersion::PHP_84; + /** * @see https://www.php.net/manual/en/migration83.deprecated.php#migration83.deprecated.ldap * @var int