Skip to content

Commit 140f74b

Browse files
committed
[type-declarations] Add KnownMagicClassMethodTypeRector
1 parent 97e546d commit 140f74b

File tree

5 files changed

+158
-0
lines changed

5 files changed

+158
-0
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 CallMethod
6+
{
7+
public function __call($method, $args)
8+
{
9+
}
10+
}
11+
12+
?>
13+
-----
14+
<?php
15+
16+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\Fixture;
17+
18+
final class CallMethod
19+
{
20+
public function __call(string $method, array $args)
21+
{
22+
}
23+
}
24+
25+
?>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
11+
final class KnownMagicClassMethodTypeRectorTest extends AbstractRectorTestCase
12+
{
13+
#[DataProvider('provideData')]
14+
public function test(string $filePath): void
15+
{
16+
$this->doTestFile($filePath);
17+
}
18+
19+
public static function provideData(): Iterator
20+
{
21+
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
22+
}
23+
24+
public function provideConfigFilePath(): string
25+
{
26+
return __DIR__ . '/config/configured_rule.php';
27+
}
28+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Rector\Config\RectorConfig;
6+
use Rector\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector;
7+
8+
return RectorConfig::configure()
9+
->withRules([KnownMagicClassMethodTypeRector::class]);
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\TypeDeclaration\Rector\ClassMethod;
6+
7+
use PhpParser\Node;
8+
use PhpParser\Node\Identifier;
9+
use PhpParser\Node\Name;
10+
use PhpParser\Node\Stmt\Class_;
11+
use Rector\Rector\AbstractRector;
12+
use Rector\ValueObject\MethodName;
13+
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
14+
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
15+
16+
/**
17+
* @see \Rector\Tests\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector\KnownMagicClassMethodTypeRectorTest
18+
*
19+
* @see https://www.php.net/manual/en/language.oop5.overloading.php#object.call
20+
*/
21+
final class KnownMagicClassMethodTypeRector extends AbstractRector
22+
{
23+
public function getRuleDefinition(): RuleDefinition
24+
{
25+
return new RuleDefinition(
26+
'Add known magic methods parameter and return type declarations',
27+
[
28+
new CodeSample(
29+
<<<'CODE_SAMPLE'
30+
final class SomeClass
31+
{
32+
public function __call($method, $args)
33+
{
34+
}
35+
}
36+
CODE_SAMPLE
37+
,
38+
<<<'CODE_SAMPLE'
39+
final class SomeClass
40+
{
41+
public function __call(string $method, array $args)
42+
{
43+
}
44+
}
45+
CODE_SAMPLE
46+
),
47+
]
48+
);
49+
}
50+
51+
/**
52+
* @return array<class-string<Node>>
53+
*/
54+
public function getNodeTypes(): array
55+
{
56+
return [Class_::class];
57+
}
58+
59+
/**
60+
* @param Class_ $node
61+
*/
62+
public function refactor(Node $node): ?Node
63+
{
64+
$hasChanged = false;
65+
66+
foreach ($node->getMethods() as $classMethod) {
67+
if (! $classMethod->isMagic()) {
68+
continue;
69+
}
70+
71+
if ($this->isName($classMethod, MethodName::CALL)) {
72+
$firstParam = $classMethod->getParams()[0];
73+
if (! $firstParam->type instanceof Node) {
74+
$firstParam->type = new Identifier('string');
75+
$hasChanged = true;
76+
}
77+
78+
$secondParam = $classMethod->getParams()[1];
79+
if (! $secondParam->type instanceof Node) {
80+
$secondParam->type = new Name('array');
81+
$hasChanged = true;
82+
}
83+
}
84+
}
85+
86+
if ($hasChanged) {
87+
return $node;
88+
}
89+
90+
return null;
91+
}
92+
}

src/Config/Level/TypeDeclarationLevel.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Rector\TypeDeclaration\Rector\ClassMethod\AddVoidReturnTypeWhereNoReturnRector;
2424
use Rector\TypeDeclaration\Rector\ClassMethod\BoolReturnTypeFromBooleanConstReturnsRector;
2525
use Rector\TypeDeclaration\Rector\ClassMethod\BoolReturnTypeFromBooleanStrictReturnsRector;
26+
use Rector\TypeDeclaration\Rector\ClassMethod\KnownMagicClassMethodTypeRector;
2627
use Rector\TypeDeclaration\Rector\ClassMethod\NumericReturnTypeFromStrictReturnsRector;
2728
use Rector\TypeDeclaration\Rector\ClassMethod\NumericReturnTypeFromStrictScalarReturnsRector;
2829
use Rector\TypeDeclaration\Rector\ClassMethod\ParamTypeByMethodCallTypeRector;
@@ -115,6 +116,9 @@ final class TypeDeclarationLevel
115116
ReturnTypeFromStrictTypedCallRector::class,
116117
ChildDoctrineRepositoryClassTypeRector::class,
117118

119+
// php native types
120+
KnownMagicClassMethodTypeRector::class,
121+
118122
// param
119123
AddMethodCallBasedStrictParamTypeRector::class,
120124
ParamTypeByParentCallTypeRector::class,

0 commit comments

Comments
 (0)