diff --git a/config/level/coding-style/coding-style.yml b/config/level/coding-style/coding-style.yml index 0dd7a9adb4a..6ca81442326 100644 --- a/config/level/coding-style/coding-style.yml +++ b/config/level/coding-style/coding-style.yml @@ -4,3 +4,5 @@ services: Rector\CodingStyle\Rector\FuncCall\SimpleArrayCallableToStringRector: ~ Rector\CodingStyle\Rector\Identical\IdenticalFalseToBooleanNotRector: ~ Rector\CodingStyle\Rector\Switch_\BinarySwitchToIfElseRector: ~ + Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector: ~ + Rector\CodingStyle\Rector\FuncCall\SetTypeToCastRector: ~ diff --git a/packages/CodingStyle/src/Rector/FuncCall/SetTypeToCastRector.php b/packages/CodingStyle/src/Rector/FuncCall/SetTypeToCastRector.php new file mode 100644 index 00000000000..a42fee2da21 --- /dev/null +++ b/packages/CodingStyle/src/Rector/FuncCall/SetTypeToCastRector.php @@ -0,0 +1,124 @@ + Array_::class, + 'bool' => Bool_::class, + 'boolean' => Bool_::class, + 'double' => Double::class, + 'float' => Double::class, + 'int' => Int_::class, + 'integer' => Int_::class, + 'object' => Object_::class, + 'string' => String_::class, + ]; + + public function getDefinition(): RectorDefinition + { + return new RectorDefinition('Changes settype() to (type) where possible', [ + new CodeSample( + <<<'CODE_SAMPLE' +class SomeClass +{ + public function run($foo) + { + settype($foo, 'string'); + + return settype($foo, 'integer'); + } +} +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +class SomeClass +{ + public function run(array $items) + { + $foo = (string) $foo; + + return (int) $foo; + } +} +CODE_SAMPLE + ), + ]); + } + + /** + * @return string[] + */ + public function getNodeTypes(): array + { + return [FuncCall::class]; + } + + /** + * @param FuncCall $node + */ + public function refactor(Node $node): ?Node + { + if (! $this->isName($node, 'settype')) { + return null; + } + + $typeNode = $this->getValue($node->args[1]->value); + if ($typeNode === null) { + return null; + } + + $typeNode = strtolower($typeNode); + + $varNode = $node->args[0]->value; + $parentNode = $node->getAttribute(Attribute::PARENT_NODE); + + // result of function or probably used + if ($parentNode instanceof Expr || $parentNode instanceof Arg) { + return null; + } + + if (isset(self::TYPE_TO_CAST[$typeNode])) { + $castClass = self::TYPE_TO_CAST[$typeNode]; + $castNode = new $castClass($varNode); + + if ($parentNode instanceof Expression) { + // bare expression? → assign + return new Assign($varNode, $castNode); + } + + return $castNode; + } + + if ($typeNode === 'null') { + return new Assign($varNode, $this->createNull()); + } + + return $node; + } +} diff --git a/packages/CodingStyle/tests/Rector/FuncCall/SetTypeToCastRector/Fixture/assign.php.inc b/packages/CodingStyle/tests/Rector/FuncCall/SetTypeToCastRector/Fixture/assign.php.inc new file mode 100644 index 00000000000..e08322e2f70 --- /dev/null +++ b/packages/CodingStyle/tests/Rector/FuncCall/SetTypeToCastRector/Fixture/assign.php.inc @@ -0,0 +1,19 @@ + settype($foo, 'string')]; + + settype($foo, settype($foo, 'string')); + } +} diff --git a/packages/CodingStyle/tests/Rector/FuncCall/SetTypeToCastRector/Fixture/fixture.php.inc b/packages/CodingStyle/tests/Rector/FuncCall/SetTypeToCastRector/Fixture/fixture.php.inc new file mode 100644 index 00000000000..08d2080cb57 --- /dev/null +++ b/packages/CodingStyle/tests/Rector/FuncCall/SetTypeToCastRector/Fixture/fixture.php.inc @@ -0,0 +1,53 @@ + +----- + diff --git a/packages/CodingStyle/tests/Rector/FuncCall/SetTypeToCastRector/SetTypeToCastRectorTest.php b/packages/CodingStyle/tests/Rector/FuncCall/SetTypeToCastRector/SetTypeToCastRectorTest.php new file mode 100644 index 00000000000..00e8593ad84 --- /dev/null +++ b/packages/CodingStyle/tests/Rector/FuncCall/SetTypeToCastRector/SetTypeToCastRectorTest.php @@ -0,0 +1,19 @@ +doTestFiles([__DIR__ . '/Fixture/fixture.php.inc', __DIR__ . '/Fixture/assign.php.inc']); + } + + protected function getRectorClass(): string + { + return SetTypeToCastRector::class; + } +}