[ ' [], 'error_levels' => ['EmptyArrayAccess'], ], 'issetWithMultipleAssignments' => [ ' 2) { $arr = [5 => [3 => "hello"]]; } if (isset($arr[$a = 5][$b = 3])) { } echo $a; echo $b;', 'assertions' => [], 'error_levels' => ['MixedArrayAccess'], ], 'isset' => [ ' [ '$a' => 'mixed', ], 'error_levels' => ['MixedAssignment'], ], 'nullCoalesce' => [ ' [ '$a' => 'mixed', ], 'error_levels' => ['MixedAssignment'], ], 'nullCoalesceWithGoodVariable' => [ ' 5 ? "hello" : null; $a = $b ?? null;', 'assertions' => [ '$a' => 'string|null', ], ], 'issetKeyedOffset' => [ ' [ '$foo[\'a\']' => 'mixed', ], 'error_levels' => [], 'scope_vars' => [ '$foo' => \Psalm\Type::getArray(), ], ], 'issetKeyedOffsetORFalse' => [ ' "bar"] : false; if (isset($bar["foo"])) { takesString($bar["foo"]); }', 'assertions' => [], 'error_levels' => ['PossiblyInvalidArrayAccess'], ], 'nullCoalesceKeyedOffset' => [ ' [ '$foo[\'a\']' => 'mixed', ], 'error_levels' => ['MixedAssignment'], 'scope_vars' => [ '$foo' => \Psalm\Type::getArray(), ], ], 'noRedundantConditionOnMixed' => [ ' [], 'error_levels' => ['MixedAssignment', 'MixedArrayAccess'], ], 'testUnset' => [ ' [ ' [ "foo" => "bar", ], "groups" => [ "foo" => "bar", "hide" => rand() % 2 > 0, ], ]; foreach ($arr as $item) { if (!isset($item["hide"]) || !$item["hide"]) {} }', ], 'issetPropertyAffirmsObject' => [ 'id)) { return $a; } return new A(); }', ], 'issetVariableKeysWithoutChange' => [ ' [ ' $arr */ function foo(array $arr) : int { $b = rand(0, 3); if (!isset($arr[$b])) { throw new \Exception("bad"); } return $arr[$b]; }', ], 'issetArrayOffsetConditionalCreationWithInt' => [ ' $arr */ function foo(array $arr) : string { if (!isset($arr[0])) { $arr[0] = "hello"; } return $arr[0]; }', ], 'issetArrayOffsetConditionalCreationWithVariable' => [ ' $arr */ function foo(array $arr) : string { $b = 5; if (!isset($arr[$b])) { $arr[$b] = "hello"; } return $arr[$b]; }', ], 'noExceptionOnBracketString' => [ ' [ 'b)) { return $arr[1]->b; } throw new \Exception("bad"); }', ], 'allowUnknownAdditionToInt' => [ ' [ ' [ ' [ ' [ ' [ ' [ '> $arr */ function foo(array $arr, string $k) : void { if (!isset($arr[$k])) { return; } if ($arr[$k][0]) {} }', ], 'mixedArrayIsset' => [ ' [], 'error_levels' => ['MixedAssignment', 'MixedArrayAccess'], ], 'mixedArrayIssetGetStringVar' => [ ' [ ' [ ' [ ' [], 'error_levels' => ['MixedAssignment', 'MixedArgument'], ], 'noParadoxOnMultipleNotIssets' => [ ' [ ' rand(0,1) ? new DateTime : null, "two" => rand(0,1) ? new DateTime : null, "three" => new DateTime ]; if (!(isset($foo["one"]) || isset($foo["two"]))) { exit; } echo $foo["one"]->format("Y");', 'assertions' => [], 'error_levels' => ['PossiblyNullReference'], ], 'notIssetOneOrOtherWithoutAssert' => [ ' rand(0,1) ? new DateTime : null, "two" => rand(0,1) ? new DateTime : null, "three" => new DateTime ]; isset($foo["one"]) || isset($foo["two"]); echo $foo["one"]->format("Y");', 'assertions' => [], 'error_levels' => ['PossiblyNullReference'], ], 'notIssetOneOrOtherWithAssert' => [ ' rand(0,1) ? new DateTime : null, "two" => rand(0,1) ? new DateTime : null, "three" => new DateTime ]; assert(isset($foo["one"]) || isset($foo["two"])); echo $foo["one"]->format("Y");', 'assertions' => [], 'error_levels' => ['PossiblyNullReference'], ], ]; } /** * @return array */ public function providerFileCheckerInvalidCodeParse() { return [ 'complainAboutBadCallInIsset' => [ ' 'UndefinedMethod', ], 'issetVariableKeysWithChange' => [ ' 'NullArrayAccess', ], 'issetAdditionalVarWithSealedObjectLike' => [ ' "bat"]; if (isset($params[self::FOO])) { return true; } return false; } }', 'error_message' => 'InvalidArrayOffset', ], ]; } }