Skip to content

Commit 6016355

Browse files
[type-declaration] Add set, get and static call to KnownMagicClassMethodTypeRector (#7422)
* add scalar types condition * add call static support, set and get * add isset/unset keys * [ci-review] Rector Rectify --------- Co-authored-by: GitHub Action <actions@github.com>
1 parent a3d2df1 commit 6016355

File tree

6 files changed

+153
-16
lines changed

6 files changed

+153
-16
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;
4+
5+
final class CallStaticMethod
6+
{
7+
public function __callStatic($method, $args)
8+
{
9+
}
10+
}
11+
12+
?>
13+
-----
14+
<?php
15+
16+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;
17+
18+
final class CallStaticMethod
19+
{
20+
public function __callStatic(string $method, array $args)
21+
{
22+
}
23+
}
24+
25+
?>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;
4+
5+
final class GetAndSet
6+
{
7+
public function __get($method)
8+
{
9+
}
10+
11+
public function __set($method, $args)
12+
{
13+
}
14+
}
15+
16+
?>
17+
-----
18+
<?php
19+
20+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;
21+
22+
final class GetAndSet
23+
{
24+
public function __get(string $method)
25+
{
26+
}
27+
28+
public function __set(string $method, mixed $args)
29+
{
30+
}
31+
}
32+
33+
?>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;
4+
5+
final class IssetUnset
6+
{
7+
public function __isset($key): bool
8+
{
9+
return true;
10+
}
11+
12+
public function __unset($key): void
13+
{
14+
}
15+
}
16+
17+
?>
18+
-----
19+
<?php
20+
21+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;
22+
23+
final class IssetUnset
24+
{
25+
public function __isset(string $key): bool
26+
{
27+
return true;
28+
}
29+
30+
public function __unset(string $key): void
31+
{
32+
}
33+
}
34+
35+
?>

rules-tests/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector/config/configured_rule.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
declare(strict_types=1);
44

5+
use Rector\ValueObject\PhpVersionFeature;
56
use Rector\Config\RectorConfig;
67
use Rector\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector;
78

89
return RectorConfig::configure()
9-
->withRules([KnownMagicClassMethodTypeRector::class]);
10+
->withRules([KnownMagicClassMethodTypeRector::class])
11+
->withPhpVersion(PhpVersionFeature::MIXED_TYPE);

rules/TypeDeclaration/Rector/ClassMethod/KnownMagicClassMethodTypeRector.php

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
use PhpParser\Node\Identifier;
99
use PhpParser\Node\Name;
1010
use PhpParser\Node\Stmt\Class_;
11+
use Rector\Php\PhpVersionProvider;
1112
use Rector\Rector\AbstractRector;
1213
use Rector\ValueObject\MethodName;
14+
use Rector\ValueObject\PhpVersionFeature;
1315
use Rector\VendorLocker\ParentClassMethodTypeOverrideGuard;
16+
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
1417
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
1518
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
1619

@@ -19,12 +22,15 @@
1922
*
2023
* @see https://www.php.net/manual/en/language.oop5.overloading.php#object.call
2124
*/
22-
final class KnownMagicClassMethodTypeRector extends AbstractRector
25+
final class KnownMagicClassMethodTypeRector extends AbstractRector implements MinPhpVersionInterface
2326
{
2427
public function __construct(
25-
private readonly ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard
26-
){
28+
private readonly ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard,
29+
private readonly PhpVersionProvider $phpVersionProvider,
30+
) {
31+
2732
}
33+
2834
public function getRuleDefinition(): RuleDefinition
2935
{
3036
return new RuleDefinition(
@@ -73,24 +79,45 @@ public function refactor(Node $node): ?Node
7379
continue;
7480
}
7581

76-
if (! $this->isName($classMethod, MethodName::CALL)) {
77-
continue;
78-
}
79-
8082
if ($this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($classMethod)) {
8183
return null;
8284
}
8385

84-
$firstParam = $classMethod->getParams()[0];
85-
if (! $firstParam->type instanceof Node) {
86-
$firstParam->type = new Identifier('string');
87-
$hasChanged = true;
86+
if ($this->isNames($classMethod, [MethodName::CALL, MethodName::CALL_STATIC])) {
87+
$secondParam = $classMethod->getParams()[1];
88+
if (! $secondParam->type instanceof Node) {
89+
$secondParam->type = new Name('array');
90+
$hasChanged = true;
91+
}
8892
}
8993

90-
$secondParam = $classMethod->getParams()[1];
91-
if (! $secondParam->type instanceof Node) {
92-
$secondParam->type = new Name('array');
93-
$hasChanged = true;
94+
// first arg string
95+
if ($this->isNames(
96+
$classMethod,
97+
[
98+
MethodName::CALL,
99+
MethodName::CALL_STATIC,
100+
MethodName::__SET,
101+
MethodName::__GET,
102+
MethodName::ISSET,
103+
MethodName::UNSET,
104+
]
105+
)) {
106+
$firstParam = $classMethod->getParams()[0];
107+
if (! $firstParam->type instanceof Node) {
108+
$firstParam->type = new Identifier('string');
109+
$hasChanged = true;
110+
}
111+
}
112+
113+
if ($this->isName($classMethod, MethodName::__SET) && $this->phpVersionProvider->isAtLeastPhpVersion(
114+
PhpVersionFeature::MIXED_TYPE
115+
)) {
116+
$secondParam = $classMethod->getParams()[1];
117+
if (! $secondParam->type instanceof Node) {
118+
$secondParam->type = new Identifier('mixed');
119+
$hasChanged = true;
120+
}
94121
}
95122
}
96123

@@ -100,4 +127,9 @@ public function refactor(Node $node): ?Node
100127

101128
return null;
102129
}
130+
131+
public function provideMinPhpVersion(): int
132+
{
133+
return PhpVersionFeature::SCALAR_TYPES;
134+
}
103135
}

src/ValueObject/MethodName.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ final class MethodName
5858
*/
5959
public const CALL = '__call';
6060

61+
/**
62+
* @var string
63+
*/
64+
public const CALL_STATIC = '__callStatic';
65+
6166
/**
6267
* @var string
6368
*/
@@ -72,4 +77,9 @@ final class MethodName
7277
* @var string
7378
*/
7479
public const ISSET = '__isset';
80+
81+
/**
82+
* @var string
83+
*/
84+
public const UNSET = '__unset';
7585
}

0 commit comments

Comments
 (0)