diff --git a/config/set/downgrade-php82.php b/config/set/downgrade-php82.php index e7e81dbe..18138f6e 100644 --- a/config/set/downgrade-php82.php +++ b/config/set/downgrade-php82.php @@ -3,11 +3,12 @@ declare(strict_types=1); use Rector\Config\RectorConfig; -use Rector\ValueObject\PhpVersion; use Rector\DowngradePhp82\Rector\Class_\DowngradeReadonlyClassRector; use Rector\DowngradePhp82\Rector\Class_\DowngradeUnionIntersectionRector; use Rector\DowngradePhp82\Rector\FuncCall\DowngradeIteratorCountToArrayRector; use Rector\DowngradePhp82\Rector\FunctionLike\DowngradeStandaloneNullTrueFalseReturnTypeRector; +use Rector\DowngradePhp82\Rector\MethodCall\DowngradeReflectionMethodHasPrototypeRector; +use Rector\ValueObject\PhpVersion; return static function (RectorConfig $rectorConfig): void { $rectorConfig->phpVersion(PhpVersion::PHP_81); @@ -16,5 +17,6 @@ DowngradeStandaloneNullTrueFalseReturnTypeRector::class, DowngradeIteratorCountToArrayRector::class, DowngradeUnionIntersectionRector::class, + DowngradeReflectionMethodHasPrototypeRector::class, ]); }; diff --git a/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/DowngradeReflectionMethodHasPrototypeRectorTest.php b/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/DowngradeReflectionMethodHasPrototypeRectorTest.php new file mode 100644 index 00000000..5792323f --- /dev/null +++ b/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/DowngradeReflectionMethodHasPrototypeRectorTest.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/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/Fixture/if_condition.php.inc b/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/Fixture/if_condition.php.inc new file mode 100644 index 00000000..9ee1beee --- /dev/null +++ b/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/Fixture/if_condition.php.inc @@ -0,0 +1,40 @@ +hasPrototype()) { + $reflectionMethod = $reflectionMethod->getPrototype(); + } + + return $reflectionMethod; +} + +?> +----- +getPrototype(); + return true; + } catch (\ReflectionException) { + return false; + } + })($reflectionMethod)) { + $reflectionMethod = $reflectionMethod->getPrototype(); + } + + return $reflectionMethod; +} + +?> diff --git a/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/Fixture/skip_first_class_callable.php.inc b/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/Fixture/skip_first_class_callable.php.inc new file mode 100644 index 00000000..fd2e7c28 --- /dev/null +++ b/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/Fixture/skip_first_class_callable.php.inc @@ -0,0 +1,10 @@ +hasPrototype(...); +} diff --git a/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/Fixture/skip_other_type.php.inc b/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/Fixture/skip_other_type.php.inc new file mode 100644 index 00000000..eb9ea655 --- /dev/null +++ b/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/Fixture/skip_other_type.php.inc @@ -0,0 +1,16 @@ +hasPrototype(); +} diff --git a/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/Fixture/some_class.php.inc b/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/Fixture/some_class.php.inc new file mode 100644 index 00000000..c4f543ad --- /dev/null +++ b/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/Fixture/some_class.php.inc @@ -0,0 +1,32 @@ +hasPrototype(); +} + +?> +----- +getPrototype(); + return true; + } catch (\ReflectionException) { + return false; + } + })($reflectionMethod); +} + +?> diff --git a/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/config/configured_rule.php b/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/config/configured_rule.php new file mode 100644 index 00000000..8b62fc70 --- /dev/null +++ b/rules-tests/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(DowngradeReflectionMethodHasPrototypeRector::class); +}; diff --git a/rules/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector.php b/rules/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector.php new file mode 100644 index 00000000..19e6cb54 --- /dev/null +++ b/rules/DowngradePhp82/Rector/MethodCall/DowngradeReflectionMethodHasPrototypeRector.php @@ -0,0 +1,128 @@ +hasPrototype(); + } +} +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +class SomeClass +{ + public function run(ReflectionMethod $reflectionMethod): bool + { + return (function (\ReflectionMethod $reflectionMethod2): bool { + try { + $reflectionMethod2->getPrototype(); + return true; + } catch (\ReflectionException) { + return false; + } + })($reflectionMethod); + } +} +CODE_SAMPLE + ), + ]); + } + + /** + * @return array> + */ + public function getNodeTypes(): array + { + return [MethodCall::class]; + } + + /** + * @param MethodCall $node + */ + public function refactor(Node $node): ?Node + { + if ($node->isFirstClassCallable()) { + return null; + } + + if (! $this->isName($node->name, 'hasPrototype')) { + return null; + } + + if (! $this->isObjectType($node->var, new ObjectType('ReflectionMethod'))) { + return null; + } + + $scope = ScopeFetcher::fetch($node); + $parameterName = $this->variableNaming->createCountedValueName('reflectionMethod', $scope); + + return new FuncCall($this->createClosure($parameterName), [new Arg($node->var)]); + } + + private function createClosure(string $parameterName): Closure + { + $reflectionMethodVariable = new Variable($parameterName); + + $tryCatch = new TryCatch( + [ + new Expression(new MethodCall($reflectionMethodVariable, 'getPrototype')), + new Return_(new ConstFetch(new Name('true'))), + ], + [ + new Catch_( + [new FullyQualified('ReflectionException')], + null, + [new Return_(new ConstFetch(new Name('false')))] + ), + ] + ); + + return new Closure([ + 'params' => [new Param($reflectionMethodVariable, null, new FullyQualified('ReflectionMethod'))], + 'returnType' => new Identifier('bool'), + 'stmts' => [$tryCatch], + ]); + } +}