Skip to content

Commit ebb3b6f

Browse files
committed
Fix variable scope
1 parent fc63761 commit ebb3b6f

File tree

3 files changed

+100
-7
lines changed

3 files changed

+100
-7
lines changed

src/Rules/Variables/DefinedVariableRule.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
namespace PHPStan\Rules\Variables;
44

55
use PhpParser\Node;
6+
use PhpParser\Node\Expr\BinaryOp\Identical;
67
use PhpParser\Node\Expr\Variable;
8+
use PhpParser\Node\Scalar\String_;
79
use PHPStan\Analyser\Scope;
810
use PHPStan\Rules\IdentifierRuleError;
911
use PHPStan\Rules\Rule;
1012
use PHPStan\Rules\RuleErrorBuilder;
11-
use PHPStan\Type\Constant\ConstantStringType;
12-
use function array_map;
1313
use function array_merge;
1414
use function in_array;
1515
use function is_string;
@@ -37,14 +37,18 @@ public function processNode(Node $node, Scope $scope): array
3737
{
3838
$errors = [];
3939
if (is_string($node->name)) {
40-
$variableNames = [$node->name];
40+
$variableNameScopes = [$node->name => $scope];
4141
} else {
42-
$fetchType = $scope->getType($node->name);
43-
$variableNames = array_map(static fn (ConstantStringType $type): string => $type->getValue(), $fetchType->getConstantStrings());
42+
$nameType = $scope->getType($node->name);
43+
$variableNameScopes = [];
44+
foreach ($nameType->getConstantStrings() as $constantString) {
45+
$name = $constantString->getValue();
46+
$variableNameScopes[$name] = $scope->filterByTruthyValue(new Identical($node->name, new String_($name)));
47+
}
4448
}
4549

46-
foreach ($variableNames as $name) {
47-
$errors = array_merge($errors, $this->processSingleVariable($scope, $node, $name));
50+
foreach ($variableNameScopes as $name => $variableScope) {
51+
$errors = array_merge($errors, $this->processSingleVariable($variableScope, $node, $name));
4852
}
4953

5054
return $errors;

tests/PHPStan/Rules/Variables/DefinedVariableRuleTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,62 @@ public function testDynamicAccess(): void
11171117
'Undefined variable: $buz',
11181118
18,
11191119
],
1120+
[
1121+
'Variable $foo might not be defined.',
1122+
36,
1123+
],
1124+
[
1125+
'Variable $foo might not be defined.',
1126+
37,
1127+
],
1128+
[
1129+
'Variable $bar might not be defined.',
1130+
38,
1131+
],
1132+
[
1133+
'Variable $bar might not be defined.',
1134+
40,
1135+
],
1136+
[
1137+
'Variable $foo might not be defined.',
1138+
41,
1139+
],
1140+
[
1141+
'Variable $bar might not be defined.',
1142+
42,
1143+
],
1144+
[
1145+
'Undefined variable: $buz',
1146+
44,
1147+
],
1148+
[
1149+
'Undefined variable: $foo',
1150+
45,
1151+
],
1152+
[
1153+
'Undefined variable: $bar',
1154+
46,
1155+
],
1156+
[
1157+
'Undefined variable: $buz',
1158+
49,
1159+
],
1160+
[
1161+
'Variable $bar might not be defined.',
1162+
49,
1163+
],
1164+
[
1165+
'Variable $foo might not be defined.',
1166+
49,
1167+
],
1168+
[
1169+
'Variable $foo might not be defined.',
1170+
50,
1171+
],
1172+
[
1173+
'Variable $bar might not be defined.',
1174+
51,
1175+
],
11201176
]);
11211177
}
11221178

tests/PHPStan/Rules/Variables/data/dynamic-access.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,37 @@ public function test(string $string, object $obj): void
1818
echo ${$this->name};
1919
}
2020

21+
public function testScope(): void
22+
{
23+
$name1 = 'foo';
24+
$rand = rand();
25+
if ($rand === 1) {
26+
$foo = 1;
27+
$name = $name1;
28+
} elseif ($rand === 2) {
29+
$name = 'bar';
30+
$bar = 'str';
31+
} else {
32+
$name = 'buz';
33+
}
34+
35+
if ($name === 'foo') {
36+
echo $$name; // ok
37+
echo $foo; // ok
38+
echo $bar;
39+
} elseif ($name === 'bar') {
40+
echo $$name; // ok
41+
echo $foo;
42+
echo $bar; // ok
43+
} else {
44+
echo $$name; // ok
45+
echo $foo;
46+
echo $bar;
47+
}
48+
49+
echo $$name; // ok
50+
echo $foo;
51+
echo $bar;
52+
}
53+
2154
}

0 commit comments

Comments
 (0)