Skip to content

Commit 9704b6f

Browse files
authored
[deprecation] Add RenameDeprecatedMethodCallRector inferring rename from @deprecated docblock (#8015)
* [Renaming] Add RenameDeprecatedMethodCallRector inferring rename from @deprecated docblock * extract DeprecatedMethodCallReplacementResolver * cover with test
1 parent 9e4dc59 commit 9704b6f

15 files changed

Lines changed: 538 additions & 0 deletions
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\Renaming\NodeAnalyzer;
6+
7+
use Iterator;
8+
use PHPStan\Reflection\ReflectionProvider;
9+
use PHPUnit\Framework\Attributes\DataProvider;
10+
use Rector\Renaming\NodeAnalyzer\DeprecatedMethodCallReplacementResolver;
11+
use Rector\Testing\PHPUnit\AbstractLazyTestCase;
12+
use Rector\Tests\Renaming\NodeAnalyzer\Source\DeprecatedMethodsClient;
13+
14+
final class DeprecatedMethodCallReplacementResolverTest extends AbstractLazyTestCase
15+
{
16+
private DeprecatedMethodCallReplacementResolver $deprecatedMethodCallReplacementResolver;
17+
18+
private ReflectionProvider $reflectionProvider;
19+
20+
protected function setUp(): void
21+
{
22+
parent::setUp();
23+
24+
$this->deprecatedMethodCallReplacementResolver = $this->make(DeprecatedMethodCallReplacementResolver::class);
25+
$this->reflectionProvider = $this->make(ReflectionProvider::class);
26+
}
27+
28+
#[DataProvider('provideData')]
29+
public function test(string $methodName, ?string $expectedReplacement): void
30+
{
31+
$classReflection = $this->reflectionProvider->getClass(DeprecatedMethodsClient::class);
32+
$extendedMethodReflection = $classReflection->getNativeMethod($methodName);
33+
34+
$resolvedReplacement = $this->deprecatedMethodCallReplacementResolver->resolve($extendedMethodReflection);
35+
$this->assertSame($expectedReplacement, $resolvedReplacement);
36+
}
37+
38+
/**
39+
* @return Iterator<string, array{string, (string | null)}>
40+
*/
41+
public static function provideData(): Iterator
42+
{
43+
yield 'use ...() instead' => ['getData', 'fetchData'];
44+
yield 'replaced by ...()' => ['loadData', 'fetchData'];
45+
yield '{@see ...()}' => ['readData', 'fetchData'];
46+
yield 'static use ...() instead' => ['makeOld', 'make'];
47+
yield 'deprecated without method suggestion' => ['legacyData', null];
48+
yield 'suggested method does not exist' => ['vanishedData', null];
49+
yield 'suggested method is itself deprecated' => ['deadEndData', null];
50+
yield 'not deprecated at all' => ['fetchData', null];
51+
}
52+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Rector\Tests\Renaming\NodeAnalyzer\Source;
6+
7+
final class DeprecatedMethodsClient
8+
{
9+
/**
10+
* @deprecated since 2.0, use fetchData() instead
11+
*/
12+
public function getData(): array
13+
{
14+
return $this->fetchData();
15+
}
16+
17+
/**
18+
* @deprecated replaced by fetchData()
19+
*/
20+
public function loadData(): array
21+
{
22+
return $this->fetchData();
23+
}
24+
25+
/**
26+
* @deprecated {@see fetchData()}
27+
*/
28+
public function readData(): array
29+
{
30+
return $this->fetchData();
31+
}
32+
33+
/**
34+
* @deprecated since 2.0, use the repository layer instead
35+
*/
36+
public function legacyData(): array
37+
{
38+
return $this->fetchData();
39+
}
40+
41+
/**
42+
* @deprecated use missingMethod() instead
43+
*/
44+
public function vanishedData(): array
45+
{
46+
return $this->fetchData();
47+
}
48+
49+
/**
50+
* @deprecated use loadData() instead
51+
*/
52+
public function deadEndData(): array
53+
{
54+
return $this->fetchData();
55+
}
56+
57+
public function fetchData(): array
58+
{
59+
return [];
60+
}
61+
62+
/**
63+
* @deprecated use make() instead
64+
*/
65+
public static function makeOld(): self
66+
{
67+
return new self();
68+
}
69+
70+
public static function make(): self
71+
{
72+
return new self();
73+
}
74+
}
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\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Fixture;
4+
5+
use Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Source\SomeApiClient;
6+
7+
function renameReplacedBy(SomeApiClient $apiClient)
8+
{
9+
return $apiClient->loadData();
10+
}
11+
12+
?>
13+
-----
14+
<?php
15+
16+
namespace Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Fixture;
17+
18+
use Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Source\SomeApiClient;
19+
20+
function renameReplacedBy(SomeApiClient $apiClient)
21+
{
22+
return $apiClient->fetchData();
23+
}
24+
25+
?>
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\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Fixture;
4+
5+
use Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Source\SomeApiClient;
6+
7+
function renameSeeTag(SomeApiClient $apiClient)
8+
{
9+
return $apiClient->readData();
10+
}
11+
12+
?>
13+
-----
14+
<?php
15+
16+
namespace Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Fixture;
17+
18+
use Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Source\SomeApiClient;
19+
20+
function renameSeeTag(SomeApiClient $apiClient)
21+
{
22+
return $apiClient->fetchData();
23+
}
24+
25+
?>
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\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Fixture;
4+
5+
use Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Source\SomeApiClient;
6+
7+
function renameStaticCall()
8+
{
9+
return SomeApiClient::makeOld();
10+
}
11+
12+
?>
13+
-----
14+
<?php
15+
16+
namespace Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Fixture;
17+
18+
use Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Source\SomeApiClient;
19+
20+
function renameStaticCall()
21+
{
22+
return SomeApiClient::make();
23+
}
24+
25+
?>
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\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Fixture;
4+
5+
use Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Source\SomeApiClient;
6+
7+
function renameUseInstead(SomeApiClient $apiClient)
8+
{
9+
return $apiClient->getData();
10+
}
11+
12+
?>
13+
-----
14+
<?php
15+
16+
namespace Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Fixture;
17+
18+
use Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Source\SomeApiClient;
19+
20+
function renameUseInstead(SomeApiClient $apiClient)
21+
{
22+
return $apiClient->fetchData();
23+
}
24+
25+
?>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Fixture;
4+
5+
use Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Source\MagicMethodApiClient;
6+
7+
function skipMagicMethodSuggestion(MagicMethodApiClient $apiClient)
8+
{
9+
// suggested fetchData() exists only as a @method magic method, not a real native one
10+
return $apiClient->getData();
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Fixture;
4+
5+
use Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Source\SomeApiClient;
6+
7+
function skipNoSuggestion(SomeApiClient $apiClient)
8+
{
9+
// @deprecated description has no "use newMethod()" hint
10+
return $apiClient->legacyData();
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Fixture;
4+
5+
use Rector\Tests\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector\Source\SomeApiClient;
6+
7+
function skipNotDeprecated(SomeApiClient $apiClient)
8+
{
9+
return $apiClient->fetchData();
10+
}
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\Renaming\Rector\MethodCall\RenameDeprecatedMethodCallRector;
6+
7+
use Iterator;
8+
use PHPUnit\Framework\Attributes\DataProvider;
9+
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
10+
11+
final class RenameDeprecatedMethodCallRectorTest 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+
}

0 commit comments

Comments
 (0)