Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 93d85c4

Browse files
authored
Make assigning property via reference impure
1 parent 43d3ac4 commit 93d85c4

File tree

4 files changed

+91
-2
lines changed

4 files changed

+91
-2
lines changed

‎src/Analyser/ImpurePoint.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use PHPStan\Node\VirtualNode;
77

88
/**
9-
* @phpstan-type ImpurePointIdentifier = 'echo'|'die'|'exit'|'propertyAssign'|'propertyUnset'|'methodCall'|'new'|'functionCall'|'include'|'require'|'print'|'eval'|'superglobal'|'yield'|'yieldFrom'|'static'|'global'|'betweenPhpTags'
9+
* @phpstan-type ImpurePointIdentifier = 'echo'|'die'|'exit'|'propertyAssign'|'propertyAssignByRef'|'propertyUnset'|'methodCall'|'new'|'functionCall'|'include'|'require'|'print'|'eval'|'superglobal'|'yield'|'yieldFrom'|'static'|'global'|'betweenPhpTags'
1010
* @api
1111
*/
1212
class ImpurePoint

‎src/Analyser/NodeScopeResolver.php‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2138,7 +2138,23 @@ public function processExprNode(Node\Stmt $stmt, Expr $expr, MutatingScope $scop
21382138
$nodeCallback,
21392139
$context,
21402140
function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context): ExpressionResult {
2141+
$impurePoints = [];
21412142
if ($expr instanceof AssignRef) {
2143+
$referencedExpr = $expr->expr;
2144+
while ($referencedExpr instanceof ArrayDimFetch) {
2145+
$referencedExpr = $referencedExpr->var;
2146+
}
2147+
2148+
if ($referencedExpr instanceof PropertyFetch || $referencedExpr instanceof StaticPropertyFetch) {
2149+
$impurePoints[] = new ImpurePoint(
2150+
$scope,
2151+
$expr,
2152+
'propertyAssignByRef',
2153+
'property assignment by reference',
2154+
false,
2155+
);
2156+
}
2157+
21422158
$scope = $scope->enterExpressionAssign($expr->expr);
21432159
}
21442160

@@ -2153,7 +2169,7 @@ function (MutatingScope $scope) use ($stmt, $expr, $nodeCallback, $context): Exp
21532169
$result = $this->processExprNode($stmt, $expr->expr, $scope, $nodeCallback, $context->enterDeep());
21542170
$hasYield = $result->hasYield();
21552171
$throwPoints = $result->getThrowPoints();
2156-
$impurePoints = $result->getImpurePoints();
2172+
$impurePoints = array_merge($impurePoints, $result->getImpurePoints());
21572173
$scope = $result->getScope();
21582174

21592175
if ($expr instanceof AssignRef) {

‎tests/PHPStan/Rules/Pure/PureMethodRuleTest.php‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,14 @@ public function testPureConstructor(): void
157157
]);
158158
}
159159

160+
public function testImpureAssignRef(): void
161+
{
162+
$this->analyse([__DIR__ . '/data/impure-assign-ref.php'], [
163+
[
164+
'Possibly impure property assignment by reference in pure method ImpureAssignRef\HelloWorld::bar6().',
165+
49,
166+
],
167+
]);
168+
}
169+
160170
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php declare(strict_types = 1); // lint >= 7.4
2+
3+
namespace ImpureAssignRef;
4+
5+
class HelloWorld
6+
{
7+
public int $value = 0;
8+
/** @var array<int, int> */
9+
public array $arr = [];
10+
/** @var array<int, \stdClass> */
11+
public array $objectArr = [];
12+
public static int $staticValue = 0;
13+
/** @var array<int, int> */
14+
public static array $staticArr = [];
15+
16+
private function bar1(): void
17+
{
18+
$value = &$this->value;
19+
$value = 1;
20+
}
21+
22+
private function bar2(): void
23+
{
24+
$value = &$this->arr[0];
25+
$value = 1;
26+
}
27+
28+
private function bar3(): void
29+
{
30+
$value = &self::$staticValue;
31+
$value = 1;
32+
}
33+
34+
private function bar4(): void
35+
{
36+
$value = &self::$staticArr[0];
37+
$value = 1;
38+
}
39+
40+
private function bar5(self $other): void
41+
{
42+
$value = &$other->value;
43+
$value = 1;
44+
}
45+
46+
/** @phpstan-pure */
47+
private function bar6(): int
48+
{
49+
$value = &$this->objectArr[0]->foo;
50+
51+
return 1;
52+
}
53+
54+
public function foo(): void
55+
{
56+
$this->bar1();
57+
$this->bar2();
58+
$this->bar3();
59+
$this->bar4();
60+
$this->bar5(new self());
61+
$this->bar6();
62+
}
63+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /