diff --git a/rules-tests/Renaming/Rector/Cast/RenameCastRector/Fixture/fixture.php.inc b/rules-tests/Renaming/Rector/Cast/RenameCastRector/Fixture/fixture.php.inc new file mode 100644 index 00000000000..a8c1e9a4925 --- /dev/null +++ b/rules-tests/Renaming/Rector/Cast/RenameCastRector/Fixture/fixture.php.inc @@ -0,0 +1,17 @@ + +----- + diff --git a/rules-tests/Renaming/Rector/Cast/RenameCastRector/RenameCastRectorTest.php b/rules-tests/Renaming/Rector/Cast/RenameCastRector/RenameCastRectorTest.php new file mode 100644 index 00000000000..4bd7bbf3d58 --- /dev/null +++ b/rules-tests/Renaming/Rector/Cast/RenameCastRector/RenameCastRectorTest.php @@ -0,0 +1,26 @@ +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/Renaming/Rector/Cast/RenameCastRector/config/configured_rule.php b/rules-tests/Renaming/Rector/Cast/RenameCastRector/config/configured_rule.php new file mode 100644 index 00000000000..3babfc452cc --- /dev/null +++ b/rules-tests/Renaming/Rector/Cast/RenameCastRector/config/configured_rule.php @@ -0,0 +1,16 @@ +ruleWithConfiguration(RenameCastRector::class, [ + new RenameCast(Double::class, Double::KIND_REAL, Double::KIND_FLOAT), + new RenameCast(Double::class, Double::KIND_DOUBLE, Double::KIND_FLOAT), + ]); +}; diff --git a/rules/Renaming/Rector/Cast/RenameCastRector.php b/rules/Renaming/Rector/Cast/RenameCastRector.php new file mode 100644 index 00000000000..eb977fa53cf --- /dev/null +++ b/rules/Renaming/Rector/Cast/RenameCastRector.php @@ -0,0 +1,79 @@ + + */ + private array $renameCasts = []; + + public function getRuleDefinition(): RuleDefinition + { + return new RuleDefinition('Renames casts', [ + new ConfiguredCodeSample( + '$real = (real) $real;', + '$real = (float) $real;', + [new RenameCast(Double::class, Double::KIND_REAL, Double::KIND_FLOAT)] + ), + ]); + } + + /** + * @return array> + */ + public function getNodeTypes(): array + { + return [Cast::class]; + } + + /** + * @param Cast $node + */ + public function refactor(Node $node): ?Node + { + foreach ($this->renameCasts as $renameCast) { + $expectedClassName = $renameCast->getFromCastExprClass(); + if ( + ! $node instanceof $expectedClassName + || $node->getAttribute(AttributeKey::KIND) !== $renameCast->getFromCastKind() + ) { + continue; + } + + $node->setAttribute(AttributeKey::KIND, $renameCast->getToCastKind()); + $node->setAttribute(AttributeKey::ORIGINAL_NODE, null); + + return $node; + } + + return null; + } + + /** + * @param mixed[] $configuration + */ + public function configure(array $configuration): void + { + Assert::allIsInstanceOf($configuration, RenameCast::class); + + $this->renameCasts = $configuration; + } +} diff --git a/rules/Renaming/ValueObject/RenameCast.php b/rules/Renaming/ValueObject/RenameCast.php new file mode 100644 index 00000000000..fd03c9bd023 --- /dev/null +++ b/rules/Renaming/ValueObject/RenameCast.php @@ -0,0 +1,40 @@ + */ + private string $fromCastExprClass, + private int $fromCastKind, + private int $toCastKind, + ) { + RectorAssert::className($fromCastExprClass); + Assert::subclassOf($fromCastExprClass, Cast::class); + } + + /** + * @return class-string + */ + public function getFromCastExprClass(): string + { + return $this->fromCastExprClass; + } + + public function getFromCastKind(): int + { + return $this->fromCastKind; + } + + public function getToCastKind(): int + { + return $this->toCastKind; + } +}