Skip to content

Commit 747a742

Browse files
committed
VariablePropertyFetchRule - allow universal object crate classes
1 parent 12c7542 commit 747a742

File tree

4 files changed

+87
-15
lines changed

4 files changed

+87
-15
lines changed

rules.neon

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,16 @@ rules:
4141
- PHPStan\Rules\VariableVariables\VariableMethodCallRule
4242
- PHPStan\Rules\VariableVariables\VariableStaticMethodCallRule
4343
- PHPStan\Rules\VariableVariables\VariableStaticPropertyFetchRule
44-
- PHPStan\Rules\VariableVariables\VariablePropertyFetchRule
4544
- PHPStan\Rules\VariableVariables\VariableVariablesRule
4645

4746
services:
4847
-
4948
class: PHPStan\Rules\BooleansInConditions\BooleanRuleHelper
5049
-
5150
class: PHPStan\Rules\Operators\OperatorRuleHelper
51+
-
52+
class: PHPStan\Rules\VariableVariables\VariablePropertyFetchRule
53+
arguments:
54+
universalObjectCratesClasses: %universalObjectCratesClasses%
55+
tags:
56+
- phpstan.rules.rule

src/Rules/VariableVariables/VariablePropertyFetchRule.php

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,31 @@
44

55
use PhpParser\Node;
66
use PHPStan\Analyser\Scope;
7+
use PHPStan\Broker\Broker;
8+
use PHPStan\Reflection\ClassReflection;
79
use PHPStan\Rules\Rule;
10+
use PHPStan\Type\TypeUtils;
811
use PHPStan\Type\VerbosityLevel;
912

1013
class VariablePropertyFetchRule implements Rule
1114
{
1215

16+
/** @var Broker */
17+
private $broker;
18+
19+
/** @var string[] */
20+
private $universalObjectCratesClasses;
21+
22+
/**
23+
* @param Broker $broker
24+
* @param string[] $universalObjectCratesClasses
25+
*/
26+
public function __construct(Broker $broker, array $universalObjectCratesClasses)
27+
{
28+
$this->broker = $broker;
29+
$this->universalObjectCratesClasses = $universalObjectCratesClasses;
30+
}
31+
1332
public function getNodeType(): string
1433
{
1534
return Node\Expr\PropertyFetch::class;
@@ -26,12 +45,43 @@ public function processNode(Node $node, Scope $scope): array
2645
return [];
2746
}
2847

48+
$fetchedOnType = $scope->getType($node->var);
49+
foreach (TypeUtils::getDirectClassNames($fetchedOnType) as $referencedClass) {
50+
if (!$this->broker->hasClass($referencedClass)) {
51+
continue;
52+
}
53+
54+
if ($this->isUniversalObjectCrate($this->broker->getClass($referencedClass))) {
55+
return [];
56+
}
57+
}
58+
2959
return [
3060
sprintf(
3161
'Variable property access on %s.',
32-
$scope->getType($node->var)->describe(VerbosityLevel::typeOnly())
62+
$fetchedOnType->describe(VerbosityLevel::typeOnly())
3363
),
3464
];
3565
}
3666

67+
private function isUniversalObjectCrate(
68+
ClassReflection $classReflection
69+
): bool
70+
{
71+
foreach ($this->universalObjectCratesClasses as $className) {
72+
if (!$this->broker->hasClass($className)) {
73+
continue;
74+
}
75+
76+
if (
77+
$classReflection->getName() === $className
78+
|| $classReflection->isSubclassOf($className)
79+
) {
80+
return true;
81+
}
82+
}
83+
84+
return false;
85+
}
86+
3787
}

tests/Rules/VariableVariables/VariablePropertyFetchRuleTest.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,18 @@ class VariablePropertyFetchRuleTest extends RuleTestCase
1010

1111
protected function getRule(): Rule
1212
{
13-
return new VariablePropertyFetchRule();
13+
return new VariablePropertyFetchRule($this->createBroker(), [
14+
'stdClass',
15+
'SimpleXMLElement',
16+
]);
1417
}
1518

1619
public function testRule(): void
1720
{
1821
$this->analyse([__DIR__ . '/data/properties.php'], [
1922
[
20-
'Variable property access on stdClass.',
21-
6,
22-
],
23-
[
24-
'Variable property access on stdClass.',
25-
9,
23+
'Variable property access on VariablePropertyFetch\Foo.',
24+
24,
2625
],
2726
]);
2827
}
Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
11
<?php
22

3-
function (stdClass $std) {
4-
$std->foo = 'test';
5-
$foo = 'bar';
6-
$std->$foo = 'foo';
3+
namespace VariablePropertyFetch;
74

8-
echo $std->foo;
9-
echo $std->$foo;
5+
use stdClass;
6+
7+
class Foo
8+
{
9+
10+
}
11+
12+
class Bar extends stdClass
13+
{
14+
15+
}
16+
17+
function (stdClass $std, Foo $foo, Bar $bar) {
18+
$str = 'str';
19+
20+
$std->foo;
21+
$std->$str;
22+
23+
$foo->foo;
24+
$foo->$str;
25+
26+
$bar->foo;
27+
$bar->$str;
1028
};

0 commit comments

Comments
 (0)