,error_levels?:string[]}> */ public function providerValidCodeParse(): iterable { return [ 'nullableMethodWithTernaryGuard' => [ 'fooFoo(): null; } }', ], 'nullableMethodWithTernaryIfNullGuard' => [ 'fooFoo(); } }', ], 'nullableMethodWithTernaryEmptyGuard' => [ 'fooFoo(); } }', ], 'nullableMethodWithTernaryIsNullGuard' => [ 'fooFoo(); } }', ], 'nullableMethodWithIfGuard' => [ 'fooFoo(); } } }', ], 'nullableMethodWithTernaryGuardWithThis' => [ 'a = $a; $b = $this->a ? $this->a->fooFoo(): null; } }', ], 'nullableMethodWithTernaryIfNullGuardWithThis' => [ 'a = $a; $b = $this->a === null ? null : $this->a->fooFoo(); } }', ], 'nullableMethodWithIfGuardWithThis' => [ 'a = $a; if ($this->a) { $this->a->fooFoo(); } } }', ], 'nullableMethodWithExceptionThrown' => [ 'fooFoo(); } }', ], 'nullableMethodWithRedefinitionAndElse' => [ 'two = 3; } $one->fooFoo(); } }', ], 'nullableMethodWithBooleanIfGuard' => [ 'fooFoo(); } } }', ], 'nullableMethodWithNonNullBooleanIfGuard' => [ 'fooFoo(); } } }', ], 'nullableMethodWithNonNullBooleanIfGuardAndBooleanAnd' => [ 'fooFoo(); } } }', ], 'nullableMethodInConditionWithIfGuardBefore' => [ 'a && $one->fooFoo()) { // do something } } }', ], 'nullableMethodWithBooleanIfGuardBefore' => [ 'fooFoo(); } }', ], 'nullableMethodWithGuardedRedefinition' => [ 'fooFoo(); } }', ], 'nullableMethodWithGuardedRedefinitionInElse' => [ 'fooFoo(); } }', ], 'nullableMethodWithGuardedNestedRedefinition' => [ 'fooFoo(); } }', ], 'nullableMethodWithGuardedSwitchRedefinition' => [ 'fooFoo(); } }', ], 'nullableMethodWithGuardedSwitchRedefinitionDueToException' => [ 'fooFoo(); } }', ], 'nullableMethodWithGuardedSwitchThatAlwaysReturns' => [ 'fooFoo(); } }', ], 'nullableMethodWithGuardedNestedRedefinitionWithReturn' => [ 'fooFoo(); } }', ], 'nullableMethodWithGuardedNestedRedefinitionWithElseReturn' => [ 'fooFoo(); } }', ], 'nullableMethodWithGuardedNestedRedefinitionWithElseifReturn' => [ 'fooFoo(); } }', ], 'nullableMethodWithGuardedSwitchBreak' => [ 'fooFoo(); break; } } }', ], 'nullableMethodWithGuardedRedefinitionOnThis' => [ 'one = $one; if ($this->one === null) { $this->one = new One(); } $this->one->fooFoo(); } }', ], 'arrayUnionTypeAssertion' => [ ' [ '$ids' => 'array', ], ], 'arrayUnionTypeAssertionWithIsArray' => [ ' [ '$ids' => 'array', ], ], '2dArrayUnionTypeAssertionWithIsArray' => [ '>|null */ function foo() { $ids = rand(0, 1) ? [["hello"]] : null; if (is_array($ids)) { return $ids; } return null; }', ], 'variableReassignment' => [ 'barBar();', ], 'variableReassignmentInIf' => [ 'barBar(); }', ], 'unionTypeFlow' => [ 'fooFoo(); } else { if ($var instanceof Two) { $var->barBar(); } else if ($var) { $var->baz(); } }', ], 'unionTypeFlowWithThrow' => [ 'fooFoo(); } }', ], 'unionTypeFlowWithElseif' => [ 'fooFoo(); }', ], 'typedAdjustment' => [ ' [ '$var' => 'int|string', ], ], 'typeMixedAdjustment' => [ ' [ '$var' => 'int|string', ], ], 'typeAdjustmentIfNull' => [ ' 5 ? new A : null; if ($var === null) { $var = new B; }', 'assertions' => [ '$var' => 'A|B', ], ], 'whileTrue' => [ 'fooFoo()) { $row[0] = "bad"; } } }', ], 'passingParam' => [ 'barBar(new A);', ], 'nullToNullableParam' => [ 'barBar(null);', ], 'objectToNullableObjectParam' => [ 'barBar(new A);', ], 'paramCoercion' => [ 'barBar(); } } }', ], 'paramElseifCoercion' => [ 'barBar(); } elseif ($a instanceof C) { $a->baz(); } } }', ], 'plusPlus' => [ ' [ '$a' => 'positive-int', ], ], 'typedValueAssertion' => [ ' [ ' [ 'fooFoo(); $a->barFoo(); } }', 'assertions' => [], ], 'trueFalseTest' => [ ' 0) { return true; } return false; } }', ], 'intersectionTypeAfterInstanceof' => [ 'foo = "bar"; } } interface I {}', ], 'intersectionTypeInsideInstanceof' => [ ' [ '&Countable $collection */ $collection = []; count($collection); /** * @param iterable&Countable $collection */ function mycount($collection): int { return count($collection); } mycount($collection);', ], 'scalarTypeParam' => [ ' [ ' ""]; if (rand(0, 1)) { $optgroup["a"] .= "v"; } if ($optgroup["a"] !== "") {}' ], 'redefineArrayKeyInsideIsStringConditional' => [ ' [ ' [ ' $arr */ function foo(array $arr) : void { foreach ($arr as $k => $_) { if (is_numeric($k)) {} if (!is_numeric($k)) {} } }' ], 'narrowScalar' => [ ' [ ' $arr */ function foo($arr): void { if (count($arr) === 2) { consume($arr); } } /** * @param array{0:string, 1: string} $input */ function consume($input): void{}' ], ]; } /** * @return iterable */ public function providerInvalidCodeParse(): iterable { return [ 'possiblyUndefinedVariable' => [ ' 'PossiblyUndefinedGlobalVariable', ], 'nullableMethodCall' => [ 'fooFoo(); } }', 'error_message' => 'PossiblyNullReference', ], 'nullableMethodCallWithThis' => [ 'a = $a; $this->a->fooFoo(); } }', 'error_message' => 'PossiblyNullReference', ], 'nullableMethodWithIfGuard' => [ 'fooFoo(); } } }', 'error_message' => 'PossiblyNullReference', ], 'nullableMethodWithWrongBooleanIfGuard' => [ 'fooFoo(); } } }', 'error_message' => 'PossiblyNullReference', ], 'nullableMethodWithWrongIfGuardedBefore' => [ 'fooFoo(); } }', 'error_message' => 'PossiblyNullReference', ], 'nullableMethodWithWrongBooleanIfGuardBefore' => [ 'fooFoo(); } }', 'error_message' => 'PossiblyNullReference', ], 'nullableMethodWithGuardedNestedIncompleteRedefinition' => [ 'fooFoo(); } }', 'error_message' => 'PossiblyNullReference', ], 'nullableMethodWithGuardedSwitchRedefinitionNoDefault' => [ 'fooFoo(); } }', 'error_message' => 'PossiblyNullReference', ], 'nullableMethodWithGuardedSwitchRedefinitionEmptyDefault' => [ 'fooFoo(); } }', 'error_message' => 'PossiblyNullReference', ], 'nullableMethodWithGuardedNestedRedefinitionWithUselessElseReturn' => [ 'fooFoo(); } }', 'error_message' => 'PossiblyNullReference', ], 'variableReassignmentInIfWithOutsideCall' => [ 'barBar(); } $one->barBar();', 'error_message' => 'PossiblyUndefinedMethod', ], 'wrongParam' => [ 'barBar(5);', 'error_message' => 'InvalidArgument', ], 'intToNullableObjectParam' => [ 'barBar(5);', 'error_message' => 'InvalidArgument', ], 'paramCoercionWithBadArg' => [ 'barBar(); } } }', 'error_message' => 'UndefinedMethod', ], 'nullCheckInsideForeachWithNoLeaveStatement' => [ 'fooBar();', 'error_message' => 'NullReference', ], 'possiblyUndefinedMethod' => [ 'foo(); } }', 'error_message' => 'PossiblyUndefinedMethod', ], 'notTrueTest' => [ ' 0; } ', 'error_message' => 'InvalidReturnStatement', ], 'notFalseTest' => [ ' 0; } ', 'error_message' => 'InvalidReturnStatement', ], 'intersectionTypeClassCheckAfterInstanceof' => [ ' 'ArgumentTypeCoercion - src' . DIRECTORY_SEPARATOR . 'somefile.php:14:32 - Argument 1 of takesB expects B,' . ' parent type A&static provided', ], 'intersectionTypeInterfaceCheckAfterInstanceof' => [ ' 'InvalidArgument - src' . DIRECTORY_SEPARATOR . 'somefile.php:12:32 - Argument 1 of takesI expects I, A&static provided', ], ]; } }