Skip to content

Commit 2a8ff1d

Browse files
committed
detect override of deprecated method
1 parent 5cb615c commit 2a8ff1d

File tree

5 files changed

+132
-1
lines changed

5 files changed

+132
-1
lines changed

Diff for: rules.neon

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ services:
66
class: PHPStan\Rules\Deprecations\DeprecatedClassHelper
77
-
88
class: PHPStan\Rules\Deprecations\OverrideDeprecatedPropertyRule
9+
-
10+
class: PHPStan\Rules\Deprecations\OverrideDeprecatedMethodRule
911

1012
rules:
1113
- PHPStan\Rules\Deprecations\AccessDeprecatedPropertyRule
@@ -28,3 +30,5 @@ rules:
2830
conditionalTags:
2931
PHPStan\Rules\Deprecations\OverrideDeprecatedPropertyRule:
3032
phpstan.rules.rule: %featureToggles.bleedingEdge%
33+
PHPStan\Rules\Deprecations\OverrideDeprecatedMethodRule:
34+
phpstan.rules.rule: %featureToggles.bleedingEdge%

Diff for: src/Rules/Deprecations/DeprecatedScopeHelper.php

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
class DeprecatedScopeHelper
88
{
99

10-
public static function isScopeDeprecated(Scope $scope): bool
10+
public static function isScopeDeprecated(Scope $scope, bool $skipMethod = false): bool
1111
{
1212
$class = $scope->getClassReflection();
1313
if ($class !== null && $class->isDeprecated()) {
@@ -19,6 +19,10 @@ public static function isScopeDeprecated(Scope $scope): bool
1919
return true;
2020
}
2121

22+
if ($skipMethod) {
23+
return false;
24+
}
25+
2226
$function = $scope->getFunction();
2327
if ($function !== null && $function->isDeprecated()->yes()) {
2428
return true;
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Deprecations;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Node\InClassMethodNode;
8+
use PHPStan\Rules\Rule;
9+
use function sprintf;
10+
11+
/**
12+
* @implements Rule<InClassMethodNode>
13+
*/
14+
class OverrideDeprecatedMethodRule implements Rule
15+
{
16+
17+
public function getNodeType(): string
18+
{
19+
return InClassMethodNode::class;
20+
}
21+
22+
public function processNode(Node $node, Scope $scope): array
23+
{
24+
if (DeprecatedScopeHelper::isScopeDeprecated($scope, true)) {
25+
return [];
26+
}
27+
28+
if (!$scope->isInClass()) {
29+
return [];
30+
}
31+
32+
if ($node->getMethodReflection()->isPrivate()) {
33+
return [];
34+
}
35+
36+
$class = $scope->getClassReflection();
37+
38+
$parents = $class->getParents();
39+
40+
$methodName = $node->getMethodReflection()->getName();
41+
42+
foreach ($parents as $parent) {
43+
if (!$parent->hasMethod($methodName)) {
44+
continue;
45+
}
46+
47+
$parentMethod = $parent->getMethod($methodName, $scope);
48+
49+
if (!$parentMethod->isDeprecated()->yes()) {
50+
return [];
51+
}
52+
53+
return [sprintf(
54+
'Class %s overrides deprecated method %s of class %s.',
55+
$class->getName(),
56+
$methodName,
57+
$parent->getName()
58+
)];
59+
}
60+
61+
return [];
62+
}
63+
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Deprecations;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Testing\RuleTestCase;
7+
8+
/**
9+
* @extends RuleTestCase<OverrideDeprecatedMethodRule>
10+
*/
11+
class OverrideDeprecatedMethodRuleTest extends RuleTestCase
12+
{
13+
14+
protected function getRule(): Rule
15+
{
16+
return new OverrideDeprecatedMethodRule();
17+
}
18+
19+
public function testDeprecatedMethodOverride(): void
20+
{
21+
$this->analyse(
22+
[__DIR__ . '/data/override-deprecated-method.php'],
23+
[
24+
[
25+
'Class OverrideDeprecatedMethod\Child overrides deprecated method foo of class OverrideDeprecatedMethod\Foo.',
26+
22,
27+
],
28+
]
29+
);
30+
}
31+
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace OverrideDeprecatedMethod;
4+
5+
class Foo
6+
{
7+
/**
8+
* @deprecated
9+
*/
10+
public function foo(): void
11+
{}
12+
13+
/**
14+
* @deprecated
15+
*/
16+
private function bar(): void
17+
{}
18+
}
19+
20+
class Child extends Foo
21+
{
22+
public function foo(): void
23+
{}
24+
25+
private function bar(): void
26+
{}
27+
}

0 commit comments

Comments
 (0)