Skip to content

Commit 7a8f54b

Browse files
committed
Use RuleLevelHelper::findTypeToCheck when symbol is not a Name
1 parent e5a4408 commit 7a8f54b

8 files changed

+202
-78
lines changed

src/Rules/Deprecations/CallToDeprecatedStaticMethodRule.php

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,24 @@
88
use PhpParser\Node\Name;
99
use PHPStan\Analyser\Scope;
1010
use PHPStan\Broker\Broker;
11-
use PHPStan\Reflection\ClassReflection;
1211
use PHPStan\Reflection\DeprecatableReflection;
12+
use PHPStan\Rules\RuleLevelHelper;
13+
use PHPStan\Type\ErrorType;
14+
use PHPStan\Type\Type;
1315

1416
class CallToDeprecatedStaticMethodRule implements \PHPStan\Rules\Rule
1517
{
1618

1719
/** @var Broker */
1820
private $broker;
1921

20-
public function __construct(Broker $broker)
22+
/** @var RuleLevelHelper */
23+
private $ruleLevelHelper;
24+
25+
public function __construct(Broker $broker, RuleLevelHelper $ruleLevelHelper)
2126
{
2227
$this->broker = $broker;
28+
$this->ruleLevelHelper = $ruleLevelHelper;
2329
}
2430

2531
public function getNodeType(): string
@@ -43,35 +49,51 @@ public function processNode(Node $node, Scope $scope): array
4349
}
4450

4551
$methodName = $node->name->name;
52+
$referencedClasses = [];
53+
54+
if ($node->class instanceof Name) {
55+
$referencedClasses[] = $scope->resolveName($node->class);
56+
} else {
57+
$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
58+
$scope,
59+
$node->class,
60+
'', // We don't care about the error message
61+
function (Type $type) use ($methodName) {
62+
return $type->canCallMethods()->yes() && $type->hasMethod($methodName);
63+
}
64+
);
4665

47-
if (!$node->class instanceof Name) {
48-
return [];
49-
}
50-
51-
$className = (string) $node->class;
52-
$class = $this->getClassWithClassName($className, $scope);
53-
54-
if ($class === null) {
55-
return [];
56-
}
66+
if ($classTypeResult->getType() instanceof ErrorType) {
67+
return [];
68+
}
5769

58-
try {
59-
$methodReflection = $class->getMethod($methodName, $scope);
60-
} catch (\PHPStan\Reflection\MissingMethodFromReflectionException $e) {
61-
return [];
70+
$referencedClasses = $classTypeResult->getReferencedClasses();
6271
}
6372

6473
$errors = [];
6574

66-
if ($class->isDeprecated()) {
67-
$errors[] = sprintf(
68-
'Call to method %s() of deprecated class %s.',
69-
$methodReflection->getName(),
70-
$methodReflection->getDeclaringClass()->getName()
71-
);
72-
}
75+
foreach ($referencedClasses as $referencedClass) {
76+
try {
77+
$class = $this->broker->getClass($referencedClass);
78+
$methodReflection = $class->getMethod($methodName, $scope);
79+
} catch (\PHPStan\Broker\ClassNotFoundException $e) {
80+
continue;
81+
} catch (\PHPStan\Reflection\MissingMethodFromReflectionException $e) {
82+
continue;
83+
}
84+
85+
if ($class->isDeprecated()) {
86+
$errors[] = sprintf(
87+
'Call to method %s() of deprecated class %s.',
88+
$methodReflection->getName(),
89+
$methodReflection->getDeclaringClass()->getName()
90+
);
91+
}
92+
93+
if (!$methodReflection instanceof DeprecatableReflection || !$methodReflection->isDeprecated()) {
94+
continue;
95+
}
7396

74-
if ($methodReflection instanceof DeprecatableReflection && $methodReflection->isDeprecated()) {
7597
$errors[] = sprintf(
7698
'Call to deprecated method %s() of class %s.',
7799
$methodReflection->getName(),
@@ -82,26 +104,4 @@ public function processNode(Node $node, Scope $scope): array
82104
return $errors;
83105
}
84106

85-
private function getClassWithClassName(string $className, Scope $scope): ?ClassReflection
86-
{
87-
if ($className === 'parent') {
88-
if (!$scope->isInClass()) {
89-
return null;
90-
}
91-
92-
$class = $scope->getClassReflection();
93-
$class = $class->getParentClass();
94-
95-
return $class !== false
96-
? $class
97-
: null;
98-
}
99-
100-
try {
101-
return $this->broker->getClass($className);
102-
} catch (\PHPStan\Broker\ClassNotFoundException $e) {
103-
return null;
104-
}
105-
}
106-
107107
}

src/Rules/Deprecations/FetchingClassConstOfDeprecatedClassRule.php

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,28 @@
44

55
use PhpParser\Node;
66
use PhpParser\Node\Expr\ClassConstFetch;
7+
use PhpParser\Node\Identifier;
78
use PhpParser\Node\Name;
89
use PHPStan\Analyser\Scope;
910
use PHPStan\Broker\Broker;
11+
use PHPStan\Reflection\DeprecatableReflection;
12+
use PHPStan\Rules\RuleLevelHelper;
13+
use PHPStan\Type\ErrorType;
14+
use PHPStan\Type\Type;
1015

1116
class FetchingClassConstOfDeprecatedClassRule implements \PHPStan\Rules\Rule
1217
{
1318

1419
/** @var Broker */
1520
private $broker;
1621

17-
public function __construct(Broker $broker)
22+
/** @var RuleLevelHelper */
23+
private $ruleLevelHelper;
24+
25+
public function __construct(Broker $broker, RuleLevelHelper $ruleLevelHelper)
1826
{
1927
$this->broker = $broker;
28+
$this->ruleLevelHelper = $ruleLevelHelper;
2029
}
2130

2231
public function getNodeType(): string
@@ -35,26 +44,67 @@ public function processNode(Node $node, Scope $scope): array
3544
return [];
3645
}
3746

38-
if (!$node->class instanceof Name) {
47+
if (!$node->name instanceof Identifier) {
3948
return [];
4049
}
4150

42-
$className = (string) $node->class;
51+
$constantName = $node->name->name;
52+
$referencedClasses = [];
4353

44-
try {
45-
$class = $this->broker->getClass($className);
46-
} catch (\PHPStan\Broker\ClassNotFoundException $e) {
47-
return [];
54+
if ($node->class instanceof Name) {
55+
$referencedClasses[] = $scope->resolveName($node->class);
56+
} else {
57+
$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
58+
$scope,
59+
$node->class,
60+
'', // We don't care about the error message
61+
function (Type $type) use ($constantName) {
62+
return $type->canAccessConstants()->yes() && $type->hasConstant($constantName);
63+
}
64+
);
65+
66+
if ($classTypeResult->getType() instanceof ErrorType) {
67+
return [];
68+
}
69+
70+
$referencedClasses = $classTypeResult->getReferencedClasses();
4871
}
4972

50-
if (!$class->isDeprecated()) {
51-
return [];
73+
$errors = [];
74+
75+
foreach ($referencedClasses as $referencedClass) {
76+
try {
77+
$class = $this->broker->getClass($referencedClass);
78+
} catch (\PHPStan\Broker\ClassNotFoundException $e) {
79+
continue;
80+
}
81+
82+
if ($class->isDeprecated()) {
83+
$errors[] = sprintf(
84+
'Fetching class constant %s of deprecated class %s.',
85+
$constantName,
86+
$referencedClass
87+
);
88+
}
89+
90+
if (!$class->hasConstant($constantName)) {
91+
continue;
92+
}
93+
94+
$constantReflection = $class->getConstant($constantName);
95+
96+
if (!$constantReflection instanceof DeprecatableReflection || !$constantReflection->isDeprecated()) {
97+
continue;
98+
}
99+
100+
$errors[] = sprintf(
101+
'Fetching deprecated class constant %s of class %s.',
102+
$constantName,
103+
$referencedClass
104+
);
52105
}
53106

54-
return [sprintf(
55-
'Fetching class constant of deprecated class %s.',
56-
$className
57-
)];
107+
return $errors;
58108
}
59109

60110
}

src/Rules/Deprecations/InstantiationOfDeprecatedClassRule.php

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,25 @@
55
use PhpParser\Node;
66
use PhpParser\Node\Expr\New_;
77
use PhpParser\Node\Name;
8+
use PhpParser\Node\Stmt\Class_;
89
use PHPStan\Analyser\Scope;
910
use PHPStan\Broker\Broker;
11+
use PHPStan\Rules\RuleLevelHelper;
12+
use PHPStan\Type\ErrorType;
1013

1114
class InstantiationOfDeprecatedClassRule implements \PHPStan\Rules\Rule
1215
{
1316

1417
/** @var Broker */
1518
private $broker;
1619

17-
public function __construct(Broker $broker)
20+
/** @var RuleLevelHelper */
21+
private $ruleLevelHelper;
22+
23+
public function __construct(Broker $broker, RuleLevelHelper $ruleLevelHelper)
1824
{
1925
$this->broker = $broker;
26+
$this->ruleLevelHelper = $ruleLevelHelper;
2027
}
2128

2229
public function getNodeType(): string
@@ -35,26 +42,49 @@ public function processNode(Node $node, Scope $scope): array
3542
return [];
3643
}
3744

38-
if (!$node->class instanceof Name) {
39-
return [];
40-
}
45+
$referencedClasses = [];
4146

42-
$className = (string) $node->class;
47+
if ($node->class instanceof Name) {
48+
$referencedClasses[] = $scope->resolveName($node->class);
49+
} elseif ($node->class instanceof Class_) {
50+
$referencedClasses[] = $scope->resolveName($node->class->namespacedName);
51+
} else {
52+
$classTypeResult = $this->ruleLevelHelper->findTypeToCheck(
53+
$scope,
54+
$node->class,
55+
'', // We don't care about the error message
56+
function () {
57+
return true;
58+
}
59+
);
4360

44-
try {
45-
$class = $this->broker->getClass($className);
46-
} catch (\PHPStan\Broker\ClassNotFoundException $e) {
47-
return [];
61+
if ($classTypeResult->getType() instanceof ErrorType) {
62+
return [];
63+
}
64+
65+
$referencedClasses = $classTypeResult->getReferencedClasses();
4866
}
4967

50-
if (!$class->isDeprecated()) {
51-
return [];
68+
$errors = [];
69+
70+
foreach ($referencedClasses as $referencedClass) {
71+
try {
72+
$class = $this->broker->getClass($referencedClass);
73+
} catch (\PHPStan\Broker\ClassNotFoundException $e) {
74+
continue;
75+
}
76+
77+
if (!$class->isDeprecated()) {
78+
continue;
79+
}
80+
81+
$errors[] = sprintf(
82+
'Instantiation of deprecated class %s.',
83+
$referencedClass
84+
);
5285
}
5386

54-
return [sprintf(
55-
'Instantiation of deprecated class %s.',
56-
$className
57-
)];
87+
return $errors;
5888
}
5989

6090
}

tests/Rules/Deprecations/CallToDeprecatedStaticMethodRuleTest.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22

33
namespace PHPStan\Rules\Deprecations;
44

5+
use PHPStan\Rules\RuleLevelHelper;
6+
57
class CallToDeprecatedStaticMethodRuleTest extends \PHPStan\Testing\RuleTestCase
68
{
79

810
protected function getRule(): \PHPStan\Rules\Rule
911
{
1012
$broker = $this->createBroker();
11-
return new CallToDeprecatedStaticMethodRule($broker);
13+
$ruleLevelHelper = new RuleLevelHelper($this->createBroker(), true, false, true);
14+
15+
return new CallToDeprecatedStaticMethodRule($broker, $ruleLevelHelper);
1216
}
1317

1418
public function testDeprecatedStaticMethodCall(): void

tests/Rules/Deprecations/FetchingClassConstOfDeprecatedClassRuleTest.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22

33
namespace PHPStan\Rules\Deprecations;
44

5+
use PHPStan\Rules\RuleLevelHelper;
6+
57
class FetchingClassConstOfDeprecatedClassRuleTest extends \PHPStan\Testing\RuleTestCase
68
{
79

810
protected function getRule(): \PHPStan\Rules\Rule
911
{
1012
$broker = $this->createBroker();
11-
return new FetchingClassConstOfDeprecatedClassRule($broker);
13+
$ruleLevelHelper = new RuleLevelHelper($this->createBroker(), true, false, true);
14+
15+
return new FetchingClassConstOfDeprecatedClassRule($broker, $ruleLevelHelper);
1216
}
1317

1418
public function testFetchingClassConstOfDeprecatedClass(): void
@@ -18,9 +22,21 @@ public function testFetchingClassConstOfDeprecatedClass(): void
1822
[__DIR__ . '/data/fetching-class-const-of-deprecated-class.php'],
1923
[
2024
[
21-
'Fetching class constant of deprecated class FetchingClassConstOfDeprecatedClass\DeprecatedFoo.',
25+
'Fetching class constant class of deprecated class FetchingClassConstOfDeprecatedClass\DeprecatedFoo.',
2226
6,
2327
],
28+
[
29+
'Fetching deprecated class constant DEPRECATED_FOO of class FetchingClassConstOfDeprecatedClass\Foo.',
30+
9,
31+
],
32+
[
33+
'Fetching class constant class of deprecated class FetchingClassConstOfDeprecatedClass\DeprecatedFoo.',
34+
11,
35+
],
36+
[
37+
'Fetching class constant class of deprecated class FetchingClassConstOfDeprecatedClass\DeprecatedFoo.',
38+
12,
39+
],
2440
]
2541
);
2642
}

0 commit comments

Comments
 (0)