Skip to content

Commit

Permalink
Fixed handling analysis with early termination in loops for general e…
Browse files Browse the repository at this point in the history
…xpressions
  • Loading branch information
ondrejmirtes committed Jun 23, 2018
1 parent 2d62b9b commit c32cc9c
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 42 deletions.
11 changes: 10 additions & 1 deletion src/Analyser/Scope.php
Original file line number Diff line number Diff line change
Expand Up @@ -2135,13 +2135,22 @@ public function removeSpecified(self $initialScope): self
}
}

$moreSpecificTypeHolders = $this->moreSpecificTypes;
foreach ($moreSpecificTypeHolders as $exprString => $holder) {
if (isset($initialScope->moreSpecificTypes[$exprString])) {
continue;
}

unset($moreSpecificTypeHolders[$exprString]);
}

return $this->scopeFactory->create(
$this->context,
$this->isDeclareStrictTypes(),
$this->getFunction(),
$this->getNamespace(),
$variableTypeHolders,
[],
$moreSpecificTypeHolders,
$this->inClosureBindScopeClass,
$this->getAnonymousFunctionReturnType(),
$this->getInFunctionCall(),
Expand Down
15 changes: 15 additions & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5445,6 +5445,21 @@ public function dataForeachLoopVariables(): array
'$integers',
"'afterLoop'",
],
[
'array<string, mixed>', // should be 'array<string, 1|2|3>',
'$this->property',
"'begin'",
],
[
'array<string, mixed>', // should be 'array<string, 1|2|3>',
'$this->property',
"'end'",
],
[
'array<string, mixed>', // should be 'array<string, 1|2|3>',
'$this->property',
"'afterLoop'",
],
];
}

Expand Down
99 changes: 58 additions & 41 deletions tests/PHPStan/Analyser/data/foreach-loop-variables.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,69 @@

namespace LoopVariables;

function () {
$foo = null;
$key = null;
$val = null;

$integers = [];
$i = 0;
foreach ([1, 2, 3] as $key => $val) {
'begin';
$foo = new Foo();
'afterAssign';

$foo && $i++;

$nullableInt = $val;
if (rand(0, 1) === 1) {
$nullableInt = null;
}
class ForeachFoo
{

if (something()) {
$foo = new Bar();
break;
}
if (something()) {
$foo = new Baz();
return;
}
if (something()) {
$foo = new Lorem();
continue;
}
/** @var int[] */
private $property = [];

if ($nullableInt === null) {
continue;
}
public function doFoo(string $s)
{
$foo = null;
$key = null;
$val = null;

$integers[] = $nullableInt;
$this->property = [];

'end';
}
$integers = [];
$i = 0;
foreach ([1, 2, 3] as $key => $val) {
'begin';
$foo = new Foo();
'afterAssign';

$foo && $i++;

$nullableInt = $val;
if (rand(0, 1) === 1) {
$nullableInt = null;
}

if (something()) {
$foo = new Bar();
break;
}
if (something()) {
$foo = new Baz();
return;
}
if (something()) {
$foo = new Lorem();
continue;
}

$emptyForeachKey = null;
$emptyForeachVal = null;
foreach ([1, 2, 3] as $emptyForeachKey => $emptyForeachVal) {
if ($nullableInt === null) {
continue;
}

if (isset($this->property[$s])) {
continue;
}

$this->property[$s] = $val;

$integers[] = $nullableInt;

'end';
}

$emptyForeachKey = null;
$emptyForeachVal = null;
foreach ([1, 2, 3] as $emptyForeachKey => $emptyForeachVal) {

}

'afterLoop';
}

'afterLoop';
};
}

0 comments on commit c32cc9c

Please sign in to comment.