Skip to content

Commit 6d046c1

Browse files
NickSdotsamsonasik
andauthored
[Php81] added RemoveReflectionSetAccessibleCallsRector (#7085)
* feat: added `RemoveDeprecatedReflectionSetAccessibleCallsRector` * chore: ran rector in preparation for downgrade testing --------- Co-authored-by: Abdul Malik Ikhsan <samsonasik@gmail.com>
1 parent fe319d7 commit 6d046c1

File tree

6 files changed

+178
-6
lines changed

6 files changed

+178
-6
lines changed

config/set/php81.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Rector\Php81\Rector\Class_\SpatieEnumClassToEnumRector;
99
use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
1010
use Rector\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector;
11+
use Rector\Php81\Rector\MethodCall\RemoveReflectionSetAccessibleCallsRector;
1112
use Rector\Php81\Rector\MethodCall\SpatieEnumMethodCallToEnumConstRector;
1213
use Rector\Php81\Rector\New_\MyCLabsConstructorCallToEnumFromRector;
1314
use Rector\Php81\Rector\Property\ReadOnlyPropertyRector;
@@ -24,5 +25,6 @@
2425
SpatieEnumMethodCallToEnumConstRector::class,
2526
NullToStrictStringFuncCallArgRector::class,
2627
FirstClassCallableRector::class,
28+
RemoveReflectionSetAccessibleCallsRector::class,
2729
]);
2830
};
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Rector\Tests\Php81\Rector\MethodCall\RemoveReflectionSetAccessibleCallsRector\Fixture;
4+
5+
use ReflectionMethod;
6+
use ReflectionProperty;
7+
8+
final class Fixture
9+
{
10+
public function run(): void
11+
{
12+
$reflectionProperty = new ReflectionProperty($this, 'privateProperty');
13+
$reflectionProperty->setAccessible(true);
14+
$value = $reflectionProperty->getValue($this);
15+
16+
$reflectionMethod = new ReflectionMethod($this, 'privateMethod');
17+
$reflectionMethod->setAccessible(false);
18+
$reflectionMethod->invoke($this);
19+
}
20+
}
21+
22+
?>
23+
-----
24+
<?php
25+
26+
namespace Rector\Tests\Php81\Rector\MethodCall\RemoveReflectionSetAccessibleCallsRector\Fixture;
27+
28+
use ReflectionMethod;
29+
use ReflectionProperty;
30+
31+
final class Fixture
32+
{
33+
public function run(): void
34+
{
35+
$reflectionProperty = new ReflectionProperty($this, 'privateProperty');
36+
$value = $reflectionProperty->getValue($this);
37+
38+
$reflectionMethod = new ReflectionMethod($this, 'privateMethod');
39+
$reflectionMethod->invoke($this);
40+
}
41+
}
42+
43+
?>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\Php81\Rector\MethodCall\RemoveReflectionSetAccessibleCallsRector;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
11+
final class RemoveReflectionSetAccessibleCallsRectorTest extends AbstractRectorTestCase
12+
{
13+
#[DataProvider('provideData')]
14+
public function testRule(string $filePath): void
15+
{
16+
$this->doTestFile($filePath);
17+
}
18+
19+
/**
20+
* @return Iterator<array<string>>
21+
*/
22+
public static function provideData(): Iterator
23+
{
24+
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
25+
}
26+
27+
public function provideConfigFilePath(): string
28+
{
29+
return __DIR__ . '/config/configured_rule.php';
30+
}
31+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\Config\RectorConfig;
6+
use Rector\Php81\Rector\MethodCall\RemoveReflectionSetAccessibleCallsRector;
7+
use Rector\ValueObject\PhpVersion;
8+
9+
return static function (RectorConfig $rectorConfig): void {
10+
$rectorConfig->rule(RemoveReflectionSetAccessibleCallsRector::class);
11+
12+
$rectorConfig->phpVersion(PhpVersion::PHP_85);
13+
};
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Php81\Rector\MethodCall;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Expr\MethodCall;
9+
use PhpParser\Node\Stmt\Expression;
10+
use PhpParser\NodeVisitor;
11+
use PHPStan\Type\ObjectType;
12+
use Rector\Rector\AbstractRector;
13+
use Rector\ValueObject\PhpVersion;
14+
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
15+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
16+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
17+
18+
/**
19+
* As of PHP 8.1.0, calling `Reflection*::setAccessible()` has no effect.
20+
*
21+
* @see https://www.php.net/manual/en/reflectionmethod.setaccessible.php
22+
* @see https://www.php.net/manual/en/reflectionproperty.setaccessible.php
23+
* @see \Rector\Tests\Php81\Rector\MethodCall\RemoveReflectionSetAccessibleCallsRector\RemoveReflectionSetAccessibleCallsRectorTest
24+
*/
25+
final class RemoveReflectionSetAccessibleCallsRector extends AbstractRector implements MinPhpVersionInterface
26+
{
27+
/**
28+
* @return array<class-string<Node>>
29+
*/
30+
public function getNodeTypes(): array
31+
{
32+
return [Expression::class];
33+
}
34+
35+
/**
36+
* @param Expression $node
37+
*/
38+
public function refactor(Node $node): ?int
39+
{
40+
if ($node->expr instanceof MethodCall === false) {
41+
return null;
42+
}
43+
44+
$methodCall = $node->expr;
45+
46+
if ($this->isName($methodCall->name, 'setAccessible') === false) {
47+
return null;
48+
}
49+
50+
if ($this->isObjectType($methodCall->var, new ObjectType('ReflectionProperty'))
51+
|| $this->isObjectType($methodCall->var, new ObjectType('ReflectionMethod'))
52+
) {
53+
return NodeVisitor::REMOVE_NODE;
54+
}
55+
56+
return null;
57+
}
58+
59+
public function getRuleDefinition(): RuleDefinition
60+
{
61+
return new RuleDefinition('Remove Reflection::setAccessible() calls', [
62+
new CodeSample(
63+
<<<'CODE_SAMPLE'
64+
$reflectionProperty = new ReflectionProperty($object, 'property');
65+
$reflectionProperty->setAccessible(true);
66+
$value = $reflectionProperty->getValue($object);
67+
68+
$reflectionMethod = new ReflectionMethod($object, 'method');
69+
$reflectionMethod->setAccessible(false);
70+
$reflectionMethod->invoke($object);
71+
CODE_SAMPLE
72+
,
73+
<<<'CODE_SAMPLE'
74+
$reflectionProperty = new ReflectionProperty($object, 'property');
75+
$value = $reflectionProperty->getValue($object);
76+
77+
$reflectionMethod = new ReflectionMethod($object, 'method');
78+
$reflectionMethod->invoke($object);
79+
CODE_SAMPLE
80+
),
81+
]);
82+
}
83+
84+
public function provideMinPhpVersion(): int
85+
{
86+
return PhpVersion::PHP_81;
87+
}
88+
}

src/Util/Reflection/PrivatesAccessor.php

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,25 +47,20 @@ public function callPrivateMethod(object|string $object, string $methodName, arr
4747
public function getPrivateProperty(object $object, string $propertyName): mixed
4848
{
4949
$reflectionProperty = $this->resolvePropertyReflection($object, $propertyName);
50-
$reflectionProperty->setAccessible(true);
5150

5251
return $reflectionProperty->getValue($object);
5352
}
5453

5554
public function setPrivateProperty(object $object, string $propertyName, mixed $value): void
5655
{
5756
$reflectionProperty = $this->resolvePropertyReflection($object, $propertyName);
58-
$reflectionProperty->setAccessible(true);
5957

6058
$reflectionProperty->setValue($object, $value);
6159
}
6260

6361
private function createAccessibleMethodReflection(object $object, string $methodName): ReflectionMethod
6462
{
65-
$reflectionMethod = new ReflectionMethod($object, $methodName);
66-
$reflectionMethod->setAccessible(true);
67-
68-
return $reflectionMethod;
63+
return new ReflectionMethod($object, $methodName);
6964
}
7065

7166
private function resolvePropertyReflection(object $object, string $propertyName): ReflectionProperty

0 commit comments

Comments
 (0)