diff --git a/config/set/php81.php b/config/set/php81.php index 17cbdcee746..b87051387c8 100644 --- a/config/set/php81.php +++ b/config/set/php81.php @@ -8,6 +8,7 @@ use Rector\Php81\Rector\Class_\SpatieEnumClassToEnumRector; use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector; use Rector\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector; +use Rector\Php81\Rector\MethodCall\RemoveReflectionSetAccessibleCallsRector; use Rector\Php81\Rector\MethodCall\SpatieEnumMethodCallToEnumConstRector; use Rector\Php81\Rector\New_\MyCLabsConstructorCallToEnumFromRector; use Rector\Php81\Rector\Property\ReadOnlyPropertyRector; @@ -24,5 +25,6 @@ SpatieEnumMethodCallToEnumConstRector::class, NullToStrictStringFuncCallArgRector::class, FirstClassCallableRector::class, + RemoveReflectionSetAccessibleCallsRector::class, ]); }; diff --git a/rules-tests/Php81/Rector/MethodCall/RemoveReflectionSetAccessibleCallsRector/Fixture/fixture.php.inc b/rules-tests/Php81/Rector/MethodCall/RemoveReflectionSetAccessibleCallsRector/Fixture/fixture.php.inc new file mode 100644 index 00000000000..c5ed1800193 --- /dev/null +++ b/rules-tests/Php81/Rector/MethodCall/RemoveReflectionSetAccessibleCallsRector/Fixture/fixture.php.inc @@ -0,0 +1,43 @@ +setAccessible(true); + $value = $reflectionProperty->getValue($this); + + $reflectionMethod = new ReflectionMethod($this, 'privateMethod'); + $reflectionMethod->setAccessible(false); + $reflectionMethod->invoke($this); + } +} + +?> +----- +getValue($this); + + $reflectionMethod = new ReflectionMethod($this, 'privateMethod'); + $reflectionMethod->invoke($this); + } +} + +?> diff --git a/rules-tests/Php81/Rector/MethodCall/RemoveReflectionSetAccessibleCallsRector/RemoveReflectionSetAccessibleCallsRectorTest.php b/rules-tests/Php81/Rector/MethodCall/RemoveReflectionSetAccessibleCallsRector/RemoveReflectionSetAccessibleCallsRectorTest.php new file mode 100644 index 00000000000..b41e85eda5c --- /dev/null +++ b/rules-tests/Php81/Rector/MethodCall/RemoveReflectionSetAccessibleCallsRector/RemoveReflectionSetAccessibleCallsRectorTest.php @@ -0,0 +1,31 @@ +doTestFile($filePath); + } + + /** + * @return Iterator> + */ + 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/Php81/Rector/MethodCall/RemoveReflectionSetAccessibleCallsRector/config/configured_rule.php b/rules-tests/Php81/Rector/MethodCall/RemoveReflectionSetAccessibleCallsRector/config/configured_rule.php new file mode 100644 index 00000000000..c15b8139eea --- /dev/null +++ b/rules-tests/Php81/Rector/MethodCall/RemoveReflectionSetAccessibleCallsRector/config/configured_rule.php @@ -0,0 +1,13 @@ +rule(RemoveReflectionSetAccessibleCallsRector::class); + + $rectorConfig->phpVersion(PhpVersion::PHP_85); +}; diff --git a/rules/Php81/Rector/MethodCall/RemoveReflectionSetAccessibleCallsRector.php b/rules/Php81/Rector/MethodCall/RemoveReflectionSetAccessibleCallsRector.php new file mode 100644 index 00000000000..a8d5e05abe4 --- /dev/null +++ b/rules/Php81/Rector/MethodCall/RemoveReflectionSetAccessibleCallsRector.php @@ -0,0 +1,88 @@ +> + */ + public function getNodeTypes(): array + { + return [Expression::class]; + } + + /** + * @param Expression $node + */ + public function refactor(Node $node): ?int + { + if ($node->expr instanceof MethodCall === false) { + return null; + } + + $methodCall = $node->expr; + + if ($this->isName($methodCall->name, 'setAccessible') === false) { + return null; + } + + if ($this->isObjectType($methodCall->var, new ObjectType('ReflectionProperty')) + || $this->isObjectType($methodCall->var, new ObjectType('ReflectionMethod')) + ) { + return NodeVisitor::REMOVE_NODE; + } + + return null; + } + + public function getRuleDefinition(): RuleDefinition + { + return new RuleDefinition('Remove Reflection::setAccessible() calls', [ + new CodeSample( + <<<'CODE_SAMPLE' +$reflectionProperty = new ReflectionProperty($object, 'property'); +$reflectionProperty->setAccessible(true); +$value = $reflectionProperty->getValue($object); + +$reflectionMethod = new ReflectionMethod($object, 'method'); +$reflectionMethod->setAccessible(false); +$reflectionMethod->invoke($object); +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +$reflectionProperty = new ReflectionProperty($object, 'property'); +$value = $reflectionProperty->getValue($object); + +$reflectionMethod = new ReflectionMethod($object, 'method'); +$reflectionMethod->invoke($object); +CODE_SAMPLE + ), + ]); + } + + public function provideMinPhpVersion(): int + { + return PhpVersion::PHP_81; + } +} diff --git a/src/Util/Reflection/PrivatesAccessor.php b/src/Util/Reflection/PrivatesAccessor.php index 0a67594c557..3d7512277ce 100644 --- a/src/Util/Reflection/PrivatesAccessor.php +++ b/src/Util/Reflection/PrivatesAccessor.php @@ -47,7 +47,6 @@ public function callPrivateMethod(object|string $object, string $methodName, arr public function getPrivateProperty(object $object, string $propertyName): mixed { $reflectionProperty = $this->resolvePropertyReflection($object, $propertyName); - $reflectionProperty->setAccessible(true); return $reflectionProperty->getValue($object); } @@ -55,17 +54,13 @@ public function getPrivateProperty(object $object, string $propertyName): mixed public function setPrivateProperty(object $object, string $propertyName, mixed $value): void { $reflectionProperty = $this->resolvePropertyReflection($object, $propertyName); - $reflectionProperty->setAccessible(true); $reflectionProperty->setValue($object, $value); } private function createAccessibleMethodReflection(object $object, string $methodName): ReflectionMethod { - $reflectionMethod = new ReflectionMethod($object, $methodName); - $reflectionMethod->setAccessible(true); - - return $reflectionMethod; + return new ReflectionMethod($object, $methodName); } private function resolvePropertyReflection(object $object, string $propertyName): ReflectionProperty