[ ' [ ' [ ' [ ' [ ' [ '$worked' => 'bool', ], ], 'doWhileVar' => [ ' [ '$worked' => 'bool', ], ], 'doWhileUndefinedVar' => [ ' [ ' [ 'parent = rand(0, 1) ? new A(): new B(); } } function makeA(): A { return new A(); } $a = makeA(); while ($a instanceof A) { $a = $a->parent; }', 'assertions' => [ '$a' => 'B', ], ], 'objectValueWithInstanceofProperty' => [ 'parent = rand(0, 1) ? new A(): new B(); } } function makeA(): A { return new A(); } $a = makeA(); while ($a->parent instanceof A) { $a = $a->parent; } $b = $a->parent;', 'assertions' => [ '$a' => 'A', '$b' => 'A|B', ], ], 'objectValueNullable' => [ 'parent = rand(0, 1) ? new A(): null; } } function makeA(): A { return new A(); } $a = makeA(); while ($a) { $a = $a->parent; }', 'assertions' => [ '$a' => 'null', ], ], 'objectValueWithAnd' => [ 'parent = rand(0, 1) ? new A(): null; } } function makeA(): A { return new A(); } $a = makeA(); while ($a && rand(0, 10) > 5) { $a = $a->parent; }', 'assertions' => [ '$a' => 'A|null', ], ], 'secondLoopWithNotNullCheck' => [ ' [ ' [ ' [ ' [ ' [ ' [ ' [ ' [ ' [ ' [ '$b' => 'bool', ], ], 'assignInsideForeachWithBreak' => [ ' [ '$b' => 'bool', ], ], 'nullCheckInsideForeachWithContinue' => [ ' */ public static function loadMultiple() { return [new A, null]; } /** @return void */ public function barBar() { } } foreach (A::loadMultiple() as $a) { if ($a === null) { continue; } $a->barBar(); }', ], 'loopWithArrayKey' => [ '>> $args * @return array[] */ function get_merged_dict(array $args) { $merged = array(); foreach ($args as $group) { foreach ($group as $key => $value) { if (isset($merged[$key])) { $merged[$key] = array_merge($merged[$key], $value); } else { $merged[$key] = $value; } } } return $merged; }', ], 'loopWithNoParadox' => [ ' [ ' 5; foreach ([1, 2, 3] as $i) { if (rand(0, 5)) { $a[] = 5; continue; } if ($b) { continue; // if this is removed, no failure } else {} // if else is removed, no failure } if ($a) {}', ], 'bleedVarIntoOuterContextWithEmptyLoop' => [ ' [ '$tag' => 'null|string', ], ], 'bleedVarIntoOuterContextWithRedefinedAsNull' => [ ' [ '$tag' => 'null', ], ], 'bleedVarIntoOuterContextWithRedefinedAsNullAndBreak' => [ ' [ '$tag' => 'null', ], ], 'bleedVarIntoOuterContextWithBreakInElse' => [ ' [ '$tag' => 'string|null', ], ], 'bleedVarIntoOuterContextWithBreakInIf' => [ ' [ '$tag' => 'string|null', ], ], 'bleedVarIntoOuterContextWithBreakInElseAndIntSet' => [ ' [ '$tag' => 'string|null|int', ], ], 'bleedVarIntoOuterContextWithRedefineAndBreak' => [ ' [ '$tag' => 'null', ], ], 'nullToMixedWithNullCheckNoContinue' => [ ' [ '$a' => 'mixed', ], 'error_levels' => [ 'MixedAssignment', ], ], 'nullToMixedWithNullCheckAndContinue' => [ ' [ '$a' => 'mixed', ], 'error_levels' => [ 'MixedAssignment', ], ], 'falseToBoolExplicitBreak' => [ ' [ '$a' => 'bool', ], ], 'falseToBoolExplicitContinue' => [ ' [ '$a' => 'bool', ], ], 'falseToBoolInBreak' => [ ' [ '$a' => 'bool', ], ], 'falseToBoolInContinue' => [ ' [ '$a' => 'bool', ], ], 'falseToBoolInBreakAndContinue' => [ ' [ '$a' => 'bool', ], ], 'falseToBoolInNestedForeach' => [ ' [ '$a' => 'bool', ], ], 'falseToBoolInContinueAndBreak' => [ ' [ '$a' => 'bool', ], ], 'falseToBoolAfterContinueAndBreak' => [ ' 0) { $a = true; continue; } break; }', 'assignments' => [ '$a' => 'bool', ], ], 'variableDefinedInForeachAndIf' => [ ' [ 'bar) {} }', ], 'noRedundantConditionAfterIsNumeric' => [ ' [ ' $value) { if ($value["foo"]) {} $r[] = $key; } }', 'assignments' => [], 'error_levels' => [ 'MixedAssignment', 'MixedArrayAccess', ], ], 'whileTrue' => [ ' [ '$a' => 'string', '$b' => 'int', '$c' => 'true', ], ], 'foreachLoopWithOKManipulation' => [ ' [ ' [ ' [ 'a = rand(0, 1) ? new A : null; } } function takesA(A $a): void {} $a = new A(); while ($a) { takesA($a); $a = $a->a; };', 'assertions' => [ '$a' => 'null', ], ], 'doWhileWithNotEmptyCheck' => [ 'a = rand(0, 1) ? new A : null; } } function takesA(A $a): void {} $a = new A(); do { takesA($a); $a = $a->a; } while ($a);', 'assertions' => [ '$a' => 'null', ], ], 'doWhileWithMethodCall' => [ 'getParent(); } while ($a);', 'assertions' => [ '$a' => 'null', ], ], 'doWhileFirstGood' => [ ' 0; } while (!$done);', ], 'doWhileWithIfException' => [ 'parent === null) { throw new \Exception("bad"); } $a = $a->parent; } while (rand(0,1)); } }', ], 'doWhileWithIfExceptionOutside' => [ 'parent === null) { throw new \Exception("bad"); } do { $a = $a->parent; } while ($a->parent && rand(0, 1)); } }', ], 'whileInstanceOf' => [ 'parent instanceof B) { $a = $a->parent; }', ], 'whileInstanceOfAndNotEmptyCheck' => [ 'parent; $foo = rand(0, 1) ? "hello" : null; if (!$foo) { while ($a instanceof B && !$foo) { $a = $a->parent; $foo = rand(0, 1) ? "hello" : null; } }', ], 'doWhileDefinedVar' => [ ' [ ' [ ' 'PossiblyUndefinedGlobalVariable', ], 'possiblyUndefinedArrayInForeach' => [ ' 'PossiblyUndefinedGlobalVariable - src/somefile.php:3 - Possibly undefined ' . 'global variable $array, first seen on line 3', ], 'possiblyUndefinedArrayInWhileAndForeach' => [ ' 'PossiblyUndefinedGlobalVariable - src/somefile.php:4 - Possibly undefined ' . 'global variable $array, first seen on line 4', ], 'possiblyUndefinedVariableInForeach' => [ ' 'PossiblyUndefinedGlobalVariable - src/somefile.php:6 - Possibly undefined ' . 'global variable $car, first seen on line 3', ], 'possibleUndefinedVariableInForeachAndIfWithBreak' => [ ' 'PossiblyUndefinedGlobalVariable - src/somefile.php:9 - Possibly undefined ' . 'global variable $a, first seen on line 4', ], 'possibleUndefinedVariableInForeachAndIf' => [ ' 'PossiblyUndefinedGlobalVariable - src/somefile.php:7 - Possibly undefined ' . 'global variable $a, first seen on line 4', ], 'implicitFourthLoopWithBadReturnType' => [ ' 'InvalidReturnStatement', ], 'possiblyNullCheckInsideForeachWithNoLeaveStatement' => [ ' */ public static function loadMultiple() { return [new A, null]; } /** @return void */ public function barBar() { } } foreach (A::loadMultiple() as $a) { if ($a === null) { // do nothing } $a->barBar(); }', 'error_message' => 'PossiblyNullReference', ], 'redundantConditionInForeachIf' => [ ' 'RedundantCondition', ], 'redundantConditionInForeachWithIfElse' => [ ' 'RedundantCondition', ], 'whileTrueNoBreak' => [ ' 'UndefinedGlobalVariable', ], 'forInfiniteNoBreak' => [ ' 'UndefinedGlobalVariable', ], 'foreachLoopInvalidation' => [ ' 'LoopInvalidation', ], 'forLoopInvalidation' => [ ' 'LoopInvalidation', ], ]; } }