From 3d6c63bc08961bf3ae3146a95ae6741f69646ae6 Mon Sep 17 00:00:00 2001 From: Brown Date: Fri, 31 Jan 2020 13:58:02 -0500 Subject: [PATCH] Break apart FunctionCallTest --- tests/ArrayFunctionCallTest.php | 1465 +++++++++++++++++++++++++++++++ tests/FunctionCallTest.php | 1436 ------------------------------ 2 files changed, 1465 insertions(+), 1436 deletions(-) create mode 100644 tests/ArrayFunctionCallTest.php diff --git a/tests/ArrayFunctionCallTest.php b/tests/ArrayFunctionCallTest.php new file mode 100644 index 000000000..342ee512f --- /dev/null +++ b/tests/ArrayFunctionCallTest.php @@ -0,0 +1,1465 @@ +,error_levels?:string[]}> + */ + public function providerValidCodeParse() + { + return [ + 'arrayFilter' => [ + ' 5, "b" => 12, "c" => null]); + $e = array_filter( + ["a" => 5, "b" => 12, "c" => null], + function(?int $i): bool { + return true; + } + );', + 'assertions' => [ + '$d' => 'array', + '$e' => 'array', + ], + ], + 'arrayFilterAdvanced' => [ + ' 5, "b" => 12, "c" => null], function(?int $val, string $key): bool { + return true; + }, ARRAY_FILTER_USE_BOTH); + $g = array_filter(["a" => 5, "b" => 12, "c" => null], function(string $val): bool { + return true; + }, ARRAY_FILTER_USE_KEY); + + $bar = "bar"; + + $foo = [ + $bar => function (): string { + return "baz"; + }, + ]; + + $foo = array_filter( + $foo, + function (string $key): bool { + return $key === "bar"; + }, + ARRAY_FILTER_USE_KEY + );', + 'assertions' => [ + '$f' => 'array', + '$g' => 'array', + ], + ], + 'arrayFilterIgnoreNullable' => [ + ' + */ + public function getRows() : array { + return [new self, null]; + } + + public function filter() : void { + $arr = array_filter( + static::getRows(), + function (self $row) : bool { + return is_a($row, static::class); + } + ); + } + }', + 'assertions' => [], + 'error_levels' => ['PossiblyInvalidArgument'], + ], + 'arrayFilterAllowTrim' => [ + ' [ + ' [ + ' $a + * @return array + */ + function foo(array $a) : array { + return array_filter($a, "is_object"); + }', + ], + 'arrayKeys' => [ + ' 1, "b" => 2]);', + 'assertions' => [ + '$a' => 'list', + ], + ], + 'arrayKeysMixed' => [ + ' 5]; + $a = array_keys($b);', + 'assertions' => [ + '$a' => 'list', + ], + 'error_levels' => ['MixedArgument'], + ], + 'arrayValues' => [ + ' 1, "b" => 2]); + $c = array_values(["a" => "hello", "b" => "jello"]);', + 'assertions' => [ + '$b' => 'non-empty-list', + '$c' => 'non-empty-list', + ], + ], + 'arrayCombine' => [ + ' [ + '$c' => 'array|false', + ], + ], + 'arrayCombineFalse' => [ + ' [ + '$c' => 'array|false', + ], + ], + 'arrayMerge' => [ + ' [ + '$d' => 'array{0: string, 1: string, 2: string, 3: int, 4: int, 5: int}', + ], + ], + 'arrayMergeListResult' => [ + ' $list + * @return list + */ + function foo(array $list) : array { + return array_merge($list, ["test"]); + } + + /** + * @param array $list + * @return list + */ + function bar(array $list) : array { + return array_merge($list, ["test"]); + }', + ], + 'arrayReverseDontPreserveKey' => [ + ' 4]);', + 'assertions' => [ + '$d' => 'non-empty-array', + ], + ], + 'arrayReverseDontPreserveKeyExplicitArg' => [ + ' 4], false);', + 'assertions' => [ + '$d' => 'non-empty-array', + ], + ], + 'arrayReversePreserveKey' => [ + ' [ + '$d' => 'non-empty-array', + ], + ], + 'arrayDiff' => [ + ' 5, "b" => 12], [5]);', + 'assertions' => [ + '$d' => 'array', + ], + ], + 'arrayDiffIsVariadic' => [ + ' [], + ], + 'arrayDiffKeyIsVariadic' => [ + ' [], + ], + 'arrayDiffAssoc' => [ + ' $a + * @var array $b + * @var array $c + */ + $r = array_diff_assoc($a, $b, $c);', + 'assertions' => [ + '$r' => 'array', + ], + ], + 'arrayPopMixed' => [ + ' 5, "c" => 6]; + $a = array_pop($b);', + 'assertions' => [ + '$a' => 'mixed', + '$b' => 'mixed', + ], + 'error_levels' => ['MixedAssignment', 'MixedArgument'], + ], + 'arrayPopNonEmpty' => [ + ' */ + $a = ["a" => 5, "b" => 6, "c" => 7]; + $b = 5; + if ($a) { + $b = array_pop($a); + } + $c = array_pop($a);', + 'assertions' => [ + '$b' => 'int', + '$c' => 'int|null', + ], + ], + 'arrayPopNonEmptyAfterIsset' => [ + ' */ + $a = ["a" => 5, "b" => 6, "c" => 7]; + $b = 5; + if (isset($a["a"])) { + $b = array_pop($a); + }', + 'assertions' => [ + '$b' => 'int', + ], + ], + 'arrayPopNonEmptyAfterCount' => [ + ' */ + $a = ["a" => 5, "b" => 6, "c" => 7]; + $b = 5; + if (count($a)) { + $b = array_pop($a); + }', + 'assertions' => [ + '$b' => 'int', + ], + ], + 'arrayShiftNonEmptyList' => [ + ' [ + ' */ + $a = ["a" => 5, "b" => 6, "c" => 7]; + $b = 5; + if (count($a) === 1) { + $b = array_pop($a); + }', + 'assertions' => [ + '$b' => 'int', + ], + ], + 'arrayPopNonEmptyAfterCountSoftEqualsOne' => [ + ' */ + $a = ["a" => 5, "b" => 6, "c" => 7]; + $b = 5; + if (count($a) == 1) { + $b = array_pop($a); + }', + 'assertions' => [ + '$b' => 'int', + ], + ], + 'arrayPopNonEmptyAfterCountGreaterThanOne' => [ + ' */ + $a = ["a" => 5, "b" => 6, "c" => 7]; + $b = 5; + if (count($a) > 0) { + $b = array_pop($a); + }', + 'assertions' => [ + '$b' => 'int', + ], + ], + 'arrayPopNonEmptyAfterCountGreaterOrEqualsOne' => [ + ' */ + $a = ["a" => 5, "b" => 6, "c" => 7]; + $b = 5; + if (count($a) >= 1) { + $b = array_pop($a); + }', + 'assertions' => [ + '$b' => 'int', + ], + ], + 'arrayPopNonEmptyAfterCountEqualsOneReversed' => [ + ' */ + $a = ["a" => 5, "b" => 6, "c" => 7]; + $b = 5; + if (1 === count($a)) { + $b = array_pop($a); + }', + 'assertions' => [ + '$b' => 'int', + ], + ], + 'arrayPopNonEmptyAfterCountSoftEqualsOneReversed' => [ + ' */ + $a = ["a" => 5, "b" => 6, "c" => 7]; + $b = 5; + if (1 == count($a)) { + $b = array_pop($a); + }', + 'assertions' => [ + '$b' => 'int', + ], + ], + 'arrayPopNonEmptyAfterCountGreaterThanOneReversed' => [ + ' */ + $a = ["a" => 5, "b" => 6, "c" => 7]; + $b = 5; + if (0 < count($a)) { + $b = array_pop($a); + }', + 'assertions' => [ + '$b' => 'int', + ], + ], + 'arrayPopNonEmptyAfterCountGreatorOrEqualToOneReversed' => [ + ' */ + $a = ["a" => 5, "b" => 6, "c" => 7]; + $b = 5; + if (1 <= count($a)) { + $b = array_pop($a); + }', + 'assertions' => [ + '$b' => 'int', + ], + ], + 'arrayPopNonEmptyAfterArrayAddition' => [ + ' */ + $a = ["a" => 5, "b" => 6, "c" => 7]; + $a["foo"] = 10; + $b = array_pop($a);', + 'assertions' => [ + '$b' => 'int', + ], + ], + 'arrayPopNonEmptyAfterMixedArrayAddition' => [ + ' 5, "b" => 6, "c" => 7]; + $a[] = "hello"; + $b = array_pop($a);', + 'assertions' => [ + '$b' => 'mixed|string', + ], + 'error_levels' => [ + 'MixedAssignment', + ], + ], + 'uasort' => [ + ' 1, "b" => 2]; + uasort( + $manifest, + function (int $a, int $b) { + return $a > $b ? 1 : -1; + } + );', + 'assertions' => [ + '$manifest' => 'array' + ], + ], + 'uksort' => [ + ' 1, "a" => 2]; + uksort( + $array, + function (string $a, string $b) { + return $a <=> $b; + } + );', + 'assertions' => [ + '$array' => 'array', + ], + ], + 'arrayMergeObjectLike' => [ + ' $a + * @return array + */ + function foo($a) + { + return $a; + } + + $a1 = ["hi" => 3]; + $a2 = ["bye" => 5]; + $a3 = array_merge($a1, $a2); + + foo($a3);', + 'assertions' => [ + '$a3' => 'array{bye: int, hi: int}', + ], + ], + 'arrayRand' => [ + ' "a", "y" => "b"]; + $c = array_rand($vars); + $d = $vars[$c]; + $more_vars = ["a", "b"]; + $e = array_rand($more_vars);', + + 'assertions' => [ + '$vars' => 'array{x: string, y: string}', + '$c' => 'string', + '$d' => 'string', + '$more_vars' => 'array{0: string, 1: string}', + '$e' => 'int', + ], + ], + 'arrayRandMultiple' => [ + ' "a", "y" => "b"]; + $b = 3; + $c = array_rand($vars, 1); + $d = array_rand($vars, 2); + $e = array_rand($vars, 3); + $f = array_rand($vars, $b);', + + 'assertions' => [ + '$vars' => 'array{x: string, y: string}', + '$c' => 'string', + '$e' => 'list', + '$f' => 'list|string', + ], + ], + 'arrayKeysNoEmpty' => [ + ' [], + 'error_levels' => ['MixedAssignment', 'MixedArgument', 'MixedArgumentTypeCoercion'], + ], + 'arrayPopNotNullable' => [ + ' $list + */ + function test(array $list) : void + { + while (!empty($list)) { + $tmp = array_pop($list); + expectsInt($tmp["item"]); + } + }', + ], + 'arrayFilterWithAssert' => [ + ' [ + '$a' => 'array', + ], + 'error_levels' => [ + 'MissingClosureParamType', + ], + ], + 'arrayFilterUseKey' => [ + ' function (): string { + return "baz"; + }, + ]; + + $foo = array_filter( + $foo, + function (string $key): bool { + return $key === "bar"; + }, + ARRAY_FILTER_USE_KEY + );', + 'assertions' => [ + '$foo' => 'array', + ], + ], + 'ignoreFalsableCurrent' => [ + ' [ + ' [ + '$foo' => 'float|int', + ], + ], + 'arrayMapWithArrayAndCallable' => [ + ' + */ + function foo(array $v): array { + $r = array_map("intval", $v); + return $r; + }', + ], + 'arrayMapObjectLikeAndCallable' => [ + ' 1, "key2"=> "2"]; + $r = array_map("intval", $v); + return $r; + }', + ], + 'arrayMapObjectLikeListAndCallable' => [ + ' $list */ + function takesList(array $list): void {} + + takesList( + array_map( + "intval", + ["1", "2", "3"] + ) + );', + ], + 'arrayMapObjectLikeAndClosure' => [ + ' 1, "key2"=> "2"]; + $r = array_map(function($i) : int { return intval($i);}, $v); + return $r; + }', + 'assertions' => [], + 'error_levels' => [ + 'MissingClosureParamType', + 'MixedTypeCoercion', + ], + ], + 'arrayMapObjectLikeListAndClosure' => [ + ' $list */ + function takesList(array $list): void {} + + takesList( + array_map( + function (string $str): string { return $str . "x"; }, + ["foo", "bar", "baz"] + ) + );', + ], + 'arrayMapUntypedCallable' => [ + ' $array + */ + $a = array_map($callable, $array); + + /** + * @var callable $callable + * @var array $array + */ + $b = array_map($callable, $array, $array); + + /** + * @var callable $callable + * @var list $list + */ + $c = array_map($callable, $list); + + /** + * @var callable $callable + * @var list $list + */ + $d = array_map($callable, $list, $list);', + 'assertions' => [ + '$a' => 'array', + '$b' => 'list', + '$c' => 'list', + '$d' => 'list', + ], + ], + 'arrayFilterGoodArgs' => [ + ' [ + ' [], + 'error_levels' => ['UndefinedClass'], + ], + 'arrayFilterIgnoreMissingMethod' => [ + ' [], + 'error_levels' => ['UndefinedMethod'], + ], + 'arrayMapParamDefault' => [ + ' [ + ' [ + ' 1, "two" => 3]; + $b = key($a); + $c = $a[$b];', + 'assertions' => [ + '$b' => 'null|string', + '$c' => 'int', + ], + ], + 'array_key_first' => [ + ' 1, "two" => 3]; + $b = array_key_first($a); + $c = $a[$b];', + 'assertions' => [ + '$b' => 'null|string', + '$c' => 'int', + ], + ], + 'array_key_last' => [ + ' 1, "two" => 3]; + $b = array_key_last($a); + $c = $a[$b];', + 'assertions' => [ + '$b' => 'null|string', + '$c' => 'int', + ], + ], + 'arrayColumnInference' => [ + '> */ + function makeGenericArray(): array { return []; } + /** @return array */ + function makeShapeArray(): array { return []; } + /** @return array */ + function makeUnionArray(): array { return []; } + $a = array_column([[1], [2], [3]], 0); + $b = array_column([["a" => 1], ["a" => 2], ["a" => 3]], "a"); + $c = array_column([["k" => "a", "v" => 1], ["k" => "b", "v" => 2]], "v", "k"); + $d = array_column([], 0); + $e = array_column(makeMixedArray(), 0); + $f = array_column(makeMixedArray(), 0, "k"); + $g = array_column(makeMixedArray(), 0, null); + $h = array_column(makeGenericArray(), 0); + $i = array_column(makeShapeArray(), 0); + $j = array_column(makeUnionArray(), 0); + ', + 'assertions' => [ + '$a' => 'list', + '$b' => 'list', + '$c' => 'array', + '$d' => 'list', + '$e' => 'list', + '$f' => 'array', + '$g' => 'list', + '$h' => 'list', + '$i' => 'list', + '$j' => 'list', + ], + ], + 'splatArrayIntersect' => [ + ' [ + '$bar' => 'array', + ], + ], + 'arrayIntersectIsVariadic' => [ + ' [], + ], + 'arrayIntersectKeyIsVariadic' => [ + ' [], + ], + 'arrayIntersectKeyNoReturnType' => [ + ' "hello"]; + } + + class C { + /** + * @psalm-suppress MissingReturnType + */ + public static function unknownStatic() { + return ["x" => "hello"]; + } + + /** + * @psalm-suppress MissingReturnType + */ + public static function unknownInstance() { + return ["x" => "hello"]; + } + } + + /** + * @psalm-suppress MixedArgument + */ + function sdn(array $s) : void { + $r = array_intersect_key(unknown(), array_filter($s)); + if (empty($r)) {} + + $r = array_intersect_key(C::unknownStatic(), array_filter($s)); + if (empty($r)) {} + + $r = array_intersect_key((new C)->unknownInstance(), array_filter($s)); + if (empty($r)) {} + }', + ], + 'arrayIntersectAssoc' => [ + ' $a + * @var array $b + * @var array $c + */ + $r = array_intersect_assoc($a, $b, $c);', + 'assertions' => [ + '$r' => 'array', + ], + ], + 'arrayReduce' => [ + ' [ + '$direct_closure_result' => 'int', + '$passed_closure_result' => 'int', + '$function_call_result' => 'int', + ], + ], + 'arrayReduceMixedReturn' => [ + ' [], + 'error_levels' => ['MissingClosureReturnType', 'MixedAssignment'], + ], + 'arraySplice' => [ + ' [ + '$a' => 'non-empty-array', + '$b' => 'array{0: string, 1: string, 2: string}', + '$c' => 'array{0: int, 1: int, 2: int}', + ], + ], + 'arraySpliceOtherType' => [ + ' [ + '$d' => 'array', + ], + ], + 'ksortPreserveShape' => [ + ' 3, "b" => 4]; + ksort($a); + acceptsAShape($a); + + /** + * @param array{a:int,b:int} $a + */ + function acceptsAShape(array $a): void {}', + ], + 'arraySlicePreserveKeys' => [ + ' 1, "b" => 2, "c" => 3]; + $b = array_slice($a, 1, 2, true); + $c = array_slice($a, 1, 2, false); + $d = array_slice($a, 1, 2);', + 'assertions' => [ + '$b' => 'array', + '$c' => 'array', + '$d' => 'array', + ], + ], + 'arraySliceDontPreserveIntKeys' => [ + ' "a", 4 => "b", 3 => "c"]; + $b = array_slice($a, 1, 2, true); + $c = array_slice($a, 1, 2, false); + $d = array_slice($a, 1, 2);', + 'assertions' => [ + '$b' => 'array', + '$c' => 'list', + '$d' => 'list', + ], + ], + 'arrayReversePreserveNonEmptiness' => [ + ' [ + ' */ + function Foo(DateTime ...$dateTimes) : array { + return array_map( + function ($dateTime) { + return (string) ($dateTime->format("c")); + }, + $dateTimes + ); + }', + ], + 'inferArrayMapArrowFunctionReturnType' => [ + ' */ + function Foo(DateTime ...$dateTimes) : array { + return array_map( + fn ($dateTime) => (string) ($dateTime->format("c")), + $dateTimes + ); + }', + ], + 'arrayPad' => [ + ' 1, "bar" => 2], 10, 123); + $b = array_pad(["a", "b", "c"], 10, "x"); + /** @var list $list */ + $c = array_pad($list, 10, 0); + /** @var array $array */ + $d = array_pad($array, 10, "");', + 'assertions' => [ + '$a' => 'non-empty-array', + '$b' => 'non-empty-list', + '$c' => 'non-empty-list', + '$d' => 'non-empty-array', + ], + ], + 'arrayPadDynamicSize' => [ + ' 1, "bar" => 2], getSize(), 123); + $b = array_pad(["a", "b", "c"], getSize(), "x"); + /** @var list $list */ + $c = array_pad($list, getSize(), 0); + /** @var array $array */ + $d = array_pad($array, getSize(), "");', + 'assertions' => [ + '$a' => 'array', + '$b' => 'list', + '$c' => 'list', + '$d' => 'array', + ], + ], + 'arrayPadZeroSize' => [ + ' [ + '$result' => 'array', + ], + ], + 'arrayPadTypeCombination' => [ + ' 1, "bar" => "two"], 5, false); + $b = array_pad(["a", 2, 3.14], 5, null); + /** @var list $list */ + $c = array_pad($list, 5, 0); + /** @var array $array */ + $d = array_pad($array, 5, null);', + 'assertions' => [ + '$a' => 'non-empty-array', + '$b' => 'non-empty-list', + '$c' => 'non-empty-list', + '$d' => 'non-empty-array', + ], + ], + 'arrayPadMixed' => [ + ' [ + '$a' => 'non-empty-array', + '$b' => 'non-empty-list', + '$c' => 'non-empty-list', + '$d' => 'non-empty-array', + ], + ], + 'arrayPadFallback' => [ + ' [ + '$result' => 'array', + ], + ], + 'arrayChunk' => [ + ' $list */ + $b = array_chunk($list, 2); + /** @var array $arr */ + $c = array_chunk($arr, 2); + ', + 'assertions' => [ + '$a' => 'list>', + '$b' => 'list>', + '$c' => 'list>', + ], + ], + 'arrayChunkPreservedKeys' => [ + ' $list */ + $b = array_chunk($list, 2, true); + /** @var array $arr */ + $c = array_chunk($arr, 2, true);', + 'assertions' => [ + '$a' => 'list>', + '$b' => 'list>', + '$c' => 'list>', + ], + ], + 'arrayChunkPreservedKeysExplicitFalse' => [ + ' $arr */ + $result = array_chunk($arr, 2, false);', + 'assertions' => [ + '$result' => 'list>', + ], + ], + 'arrayChunkMixed' => [ + ' $list */ + $b = array_chunk($list, 2); + /** @var mixed[] $arr */ + $c = array_chunk($arr, 2);', + 'assertions' => [ + '$a' => 'list>', + '$b' => 'list>', + '$c' => 'list>', + ], + ], + 'arrayChunkFallback' => [ + ' [ + '$result' => 'list>', + ], + ], + 'arrayMapPreserveNonEmptiness' => [ + ' $strings + * @psalm-return non-empty-list + */ + function foo(array $strings): array { + return array_map("intval", $strings); + }' + ], + 'arrayMapZip' => [ + ' [ + ' [ + '$result' => 'array', + ], + ], + 'shuffle' => [ + ' 123, "bar" => 456]; + shuffle($array);', + 'assertions' => [ + '$array' => 'list', + ], + ], + 'sort' => [ + ' 123, "bar" => 456]; + sort($array);', + 'assertions' => [ + '$array' => 'list', + ], + ], + 'rsort' => [ + ' 123, "bar" => 456]; + sort($array);', + 'assertions' => [ + '$array' => 'list', + ], + ], + 'usort' => [ + ' 123, "bar" => 456]; + usort($array, function (int $a, int $b) { return $a <=> $b; });', + 'assertions' => [ + '$array' => 'list', + ], + ], + 'specialCaseArrayFilterOnSingleEntry' => [ + ' */ + function makeAList(int $ofThisInteger): array { + return array_filter([$ofThisInteger]); + }' + ], + 'arrayMapWithEmptyArrayReturn' => [ + '> $elements + * @return list + */ + function resolvePossibleFilePaths($elements) : array + { + return array_values( + array_filter( + array_merge( + ...array_map( + function (array $element) : array { + if (rand(0,1) == 1) { + return []; + } + return $element; + }, + $elements + ) + ) + ) + ); + }' + ], + 'arrayFilterArrowFunction' => [ + ' $x instanceof B + );', + 'assertions' => [ + '$a' => 'array', + '$b' => 'array', + ], + ], + 'arrayMergeTwoExplicitLists' => [ + ' $foo + */ + function foo(array $foo) : void {} + + $foo1 = [1, 2, 3]; + $foo2 = [1, 4, 5]; + foo(array_merge($foo1, $foo2));' + ], + 'arrayMergeTwoPossiblyFalse' => [ + ' 'list' + ], + ], + ]; + } + + /** + * @return iterable + */ + public function providerInvalidCodeParse() + { + return [ + 'arrayFilterWithoutTypes' => [ + ' 5, "b" => 12, "c" => null], + function(?int $i) { + return $_GET["a"]; + } + );', + 'error_message' => 'MixedArgumentTypeCoercion', + 'error_levels' => ['MissingClosureParamType', 'MissingClosureReturnType'], + ], + 'arrayFilterUseMethodOnInferrableInt' => [ + 'foo(); });', + 'error_message' => 'InvalidMethodCall', + ], + 'arrayMapUseMethodOnInferrableInt' => [ + 'foo(); }, [1, 2, 3, 4]);', + 'error_message' => 'InvalidMethodCall', + ], + 'arrayMapWithNonCallableStringArray' => [ + ' 'InvalidArgument', + ], + 'arrayMapWithNonCallableIntArray' => [ + ' 'InvalidArgument', + ], + 'arrayFilterBadArgs' => [ + ' 'InvalidScalarArgument', + ], + 'arrayFilterTooFewArgs' => [ + ' 'TooFewArguments', + ], + 'arrayMapBadArgs' => [ + ' 'InvalidScalarArgument', + ], + 'arrayMapTooFewArgs' => [ + ' 'TooFewArguments', + ], + 'arrayMapTooManyArgs' => [ + ' 'TooManyArguments', + ], + 'arrayReduceInvalidClosureTooFewArgs' => [ + ' 'InvalidArgument', + 'error_levels' => ['MixedTypeCoercion'], + ], + 'arrayReduceInvalidItemType' => [ + ' 'InvalidArgument', + 'error_levels' => ['MissingClosureReturnType'], + ], + 'arrayReduceInvalidCarryType' => [ + ' 'InvalidArgument', + 'error_levels' => ['MissingClosureReturnType'], + ], + 'arrayReduceInvalidCarryOutputType' => [ + ' 'InvalidArgument', + ], + 'arrayPopNotNull' => [ + ' $list + */ + function test(array $list) : void + { + while (!empty($list)) { + $tmp = array_pop($list); + if ($tmp === null) {} + } + }', + 'error_message' => 'DocblockTypeContradiction', + ], + 'usortInvalidCallableString' => [ + ' 'InvalidArgument', + ], + 'arrayShiftUndefinedVariable' => [ + ' 'UndefinedVariable', + ], + 'arrayFilterObjectLike' => [ + ' $ints */ + function ints(array $ints) : void {} + $brr = array_filter([2,3,0,4,5]); + ints($brr);', + 'error_message' => 'ArgumentTypeCoercion - src/somefile.php:5:26 - Argument 1 of ints expects list, parent type array provided', + ], + ]; + } +} diff --git a/tests/FunctionCallTest.php b/tests/FunctionCallTest.php index 8ea79230c..ece3ddd24 100644 --- a/tests/FunctionCallTest.php +++ b/tests/FunctionCallTest.php @@ -25,99 +25,7 @@ class FunctionCallTest extends TestCase } ' ], - 'arrayFilter' => [ - ' 5, "b" => 12, "c" => null]); - $e = array_filter( - ["a" => 5, "b" => 12, "c" => null], - function(?int $i): bool { - return true; - } - );', - 'assertions' => [ - '$d' => 'array', - '$e' => 'array', - ], - ], - 'arrayFilterAdvanced' => [ - ' 5, "b" => 12, "c" => null], function(?int $val, string $key): bool { - return true; - }, ARRAY_FILTER_USE_BOTH); - $g = array_filter(["a" => 5, "b" => 12, "c" => null], function(string $val): bool { - return true; - }, ARRAY_FILTER_USE_KEY); - $bar = "bar"; - - $foo = [ - $bar => function (): string { - return "baz"; - }, - ]; - - $foo = array_filter( - $foo, - function (string $key): bool { - return $key === "bar"; - }, - ARRAY_FILTER_USE_KEY - );', - 'assertions' => [ - '$f' => 'array', - '$g' => 'array', - ], - ], - 'arrayFilterIgnoreNullable' => [ - ' - */ - public function getRows() : array { - return [new self, null]; - } - - public function filter() : void { - $arr = array_filter( - static::getRows(), - function (self $row) : bool { - return is_a($row, static::class); - } - ); - } - }', - 'assertions' => [], - 'error_levels' => ['PossiblyInvalidArgument'], - ], - 'arrayFilterAllowTrim' => [ - ' [ - ' [ - ' $a - * @return array - */ - function foo(array $a) : array { - return array_filter($a, "is_object"); - }', - ], 'typedArrayWithDefault' => [ ' [ - ' 1, "b" => 2]);', - 'assertions' => [ - '$a' => 'list', - ], - ], - 'arrayKeysMixed' => [ - ' 5]; - $a = array_keys($b);', - 'assertions' => [ - '$a' => 'list', - ], - 'error_levels' => ['MixedArgument'], - ], - 'arrayValues' => [ - ' 1, "b" => 2]); - $c = array_values(["a" => "hello", "b" => "jello"]);', - 'assertions' => [ - '$b' => 'non-empty-list', - '$c' => 'non-empty-list', - ], - ], - 'arrayCombine' => [ - ' [ - '$c' => 'array|false', - ], - ], - 'arrayCombineFalse' => [ - ' [ - '$c' => 'array|false', - ], - ], - 'arrayMerge' => [ - ' [ - '$d' => 'array{0: string, 1: string, 2: string, 3: int, 4: int, 5: int}', - ], - ], - 'arrayMergeListResult' => [ - ' $list - * @return list - */ - function foo(array $list) : array { - return array_merge($list, ["test"]); - } - - /** - * @param array $list - * @return list - */ - function bar(array $list) : array { - return array_merge($list, ["test"]); - }', - ], - 'arrayReverseDontPreserveKey' => [ - ' 4]);', - 'assertions' => [ - '$d' => 'non-empty-array', - ], - ], - 'arrayReverseDontPreserveKeyExplicitArg' => [ - ' 4], false);', - 'assertions' => [ - '$d' => 'non-empty-array', - ], - ], - 'arrayReversePreserveKey' => [ - ' [ - '$d' => 'non-empty-array', - ], - ], - 'arrayDiff' => [ - ' 5, "b" => 12], [5]);', - 'assertions' => [ - '$d' => 'array', - ], - ], - 'arrayDiffIsVariadic' => [ - ' [], - ], - 'arrayDiffKeyIsVariadic' => [ - ' [], - ], - 'arrayDiffAssoc' => [ - ' $a - * @var array $b - * @var array $c - */ - $r = array_diff_assoc($a, $b, $c);', - 'assertions' => [ - '$r' => 'array', - ], - ], - 'arrayPopMixed' => [ - ' 5, "c" => 6]; - $a = array_pop($b);', - 'assertions' => [ - '$a' => 'mixed', - '$b' => 'mixed', - ], - 'error_levels' => ['MixedAssignment', 'MixedArgument'], - ], - 'arrayPopNonEmpty' => [ - ' */ - $a = ["a" => 5, "b" => 6, "c" => 7]; - $b = 5; - if ($a) { - $b = array_pop($a); - } - $c = array_pop($a);', - 'assertions' => [ - '$b' => 'int', - '$c' => 'int|null', - ], - ], - 'arrayPopNonEmptyAfterIsset' => [ - ' */ - $a = ["a" => 5, "b" => 6, "c" => 7]; - $b = 5; - if (isset($a["a"])) { - $b = array_pop($a); - }', - 'assertions' => [ - '$b' => 'int', - ], - ], - 'arrayPopNonEmptyAfterCount' => [ - ' */ - $a = ["a" => 5, "b" => 6, "c" => 7]; - $b = 5; - if (count($a)) { - $b = array_pop($a); - }', - 'assertions' => [ - '$b' => 'int', - ], - ], - 'arrayShiftNonEmptyList' => [ - ' [ ' */ @@ -414,102 +147,6 @@ class FunctionCallTest extends TestCase $segments = explode(".", $s); if (count($segments) === 1) {}', ], - 'arrayPopNonEmptyAfterCountEqualsOne' => [ - ' */ - $a = ["a" => 5, "b" => 6, "c" => 7]; - $b = 5; - if (count($a) === 1) { - $b = array_pop($a); - }', - 'assertions' => [ - '$b' => 'int', - ], - ], - 'arrayPopNonEmptyAfterCountSoftEqualsOne' => [ - ' */ - $a = ["a" => 5, "b" => 6, "c" => 7]; - $b = 5; - if (count($a) == 1) { - $b = array_pop($a); - }', - 'assertions' => [ - '$b' => 'int', - ], - ], - 'arrayPopNonEmptyAfterCountGreaterThanOne' => [ - ' */ - $a = ["a" => 5, "b" => 6, "c" => 7]; - $b = 5; - if (count($a) > 0) { - $b = array_pop($a); - }', - 'assertions' => [ - '$b' => 'int', - ], - ], - 'arrayPopNonEmptyAfterCountGreaterOrEqualsOne' => [ - ' */ - $a = ["a" => 5, "b" => 6, "c" => 7]; - $b = 5; - if (count($a) >= 1) { - $b = array_pop($a); - }', - 'assertions' => [ - '$b' => 'int', - ], - ], - 'arrayPopNonEmptyAfterCountEqualsOneReversed' => [ - ' */ - $a = ["a" => 5, "b" => 6, "c" => 7]; - $b = 5; - if (1 === count($a)) { - $b = array_pop($a); - }', - 'assertions' => [ - '$b' => 'int', - ], - ], - 'arrayPopNonEmptyAfterCountSoftEqualsOneReversed' => [ - ' */ - $a = ["a" => 5, "b" => 6, "c" => 7]; - $b = 5; - if (1 == count($a)) { - $b = array_pop($a); - }', - 'assertions' => [ - '$b' => 'int', - ], - ], - 'arrayPopNonEmptyAfterCountGreaterThanOneReversed' => [ - ' */ - $a = ["a" => 5, "b" => 6, "c" => 7]; - $b = 5; - if (0 < count($a)) { - $b = array_pop($a); - }', - 'assertions' => [ - '$b' => 'int', - ], - ], - 'arrayPopNonEmptyAfterCountGreatorOrEqualToOneReversed' => [ - ' */ - $a = ["a" => 5, "b" => 6, "c" => 7]; - $b = 5; - if (1 <= count($a)) { - $b = array_pop($a); - }', - 'assertions' => [ - '$b' => 'int', - ], - ], 'arrayPopNonEmptyAfterThreeAssertions' => [ ' 'array', ], ], - 'arrayPopNonEmptyAfterArrayAddition' => [ - ' */ - $a = ["a" => 5, "b" => 6, "c" => 7]; - $a["foo"] = 10; - $b = array_pop($a);', - 'assertions' => [ - '$b' => 'int', - ], - ], - 'arrayPopNonEmptyAfterMixedArrayAddition' => [ - ' 5, "b" => 6, "c" => 7]; - $a[] = "hello"; - $b = array_pop($a);', - 'assertions' => [ - '$b' => 'mixed|string', - ], - 'error_levels' => [ - 'MixedAssignment', - ], - ], 'countMoreThan0CanBeInverted' => [ ' 'array', ], ], - 'uasort' => [ - ' 1, "b" => 2]; - uasort( - $manifest, - function (int $a, int $b) { - return $a > $b ? 1 : -1; - } - );', - 'assertions' => [ - '$manifest' => 'array' - ], - ], - 'uksort' => [ - ' 1, "a" => 2]; - uksort( - $array, - function (string $a, string $b) { - return $a <=> $b; - } - );', - 'assertions' => [ - '$array' => 'array', - ], - ], 'byRefAfterCallable' => [ ' [ - ' $a - * @return array - */ - function foo($a) - { - return $a; - } - - $a1 = ["hi" => 3]; - $a2 = ["bye" => 5]; - $a3 = array_merge($a1, $a2); - - foo($a3);', - 'assertions' => [ - '$a3' => 'array{bye: int, hi: int}', - ], - ], - 'arrayRand' => [ - ' "a", "y" => "b"]; - $c = array_rand($vars); - $d = $vars[$c]; - $more_vars = ["a", "b"]; - $e = array_rand($more_vars);', - - 'assertions' => [ - '$vars' => 'array{x: string, y: string}', - '$c' => 'string', - '$d' => 'string', - '$more_vars' => 'array{0: string, 1: string}', - '$e' => 'int', - ], - ], - 'arrayRandMultiple' => [ - ' "a", "y" => "b"]; - $b = 3; - $c = array_rand($vars, 1); - $d = array_rand($vars, 2); - $e = array_rand($vars, 3); - $f = array_rand($vars, $b);', - - 'assertions' => [ - '$vars' => 'array{x: string, y: string}', - '$c' => 'string', - '$e' => 'list', - '$f' => 'list|string', - ], - ], - 'arrayKeysNoEmpty' => [ - ' [], - 'error_levels' => ['MixedAssignment', 'MixedArgument', 'MixedArgumentTypeCoercion'], - ], 'compact' => [ ' 'false|string', ], ], - 'arrayPopNotNullable' => [ - ' $list - */ - function test(array $list) : void - { - while (!empty($list)) { - $tmp = array_pop($list); - expectsInt($tmp["item"]); - } - }', - ], - 'arrayFilterWithAssert' => [ - ' [ - '$a' => 'array', - ], - 'error_levels' => [ - 'MissingClosureParamType', - ], - ], - 'arrayFilterUseKey' => [ - ' function (): string { - return "baz"; - }, - ]; - - $foo = array_filter( - $foo, - function (string $key): bool { - return $key === "bar"; - }, - ARRAY_FILTER_USE_KEY - );', - 'assertions' => [ - '$foo' => 'array', - ], - ], - 'ignoreFalsableCurrent' => [ - ' [ ' [ - ' [ - '$foo' => 'float|int', - ], - ], - 'arrayMapWithArrayAndCallable' => [ - ' - */ - function foo(array $v): array { - $r = array_map("intval", $v); - return $r; - }', - ], - 'arrayMapObjectLikeAndCallable' => [ - ' 1, "key2"=> "2"]; - $r = array_map("intval", $v); - return $r; - }', - ], - 'arrayMapObjectLikeListAndCallable' => [ - ' $list */ - function takesList(array $list): void {} - - takesList( - array_map( - "intval", - ["1", "2", "3"] - ) - );', - ], - 'arrayMapObjectLikeAndClosure' => [ - ' 1, "key2"=> "2"]; - $r = array_map(function($i) : int { return intval($i);}, $v); - return $r; - }', - 'assertions' => [], - 'error_levels' => [ - 'MissingClosureParamType', - 'MixedTypeCoercion', - ], - ], - 'arrayMapObjectLikeListAndClosure' => [ - ' $list */ - function takesList(array $list): void {} - - takesList( - array_map( - function (string $str): string { return $str . "x"; }, - ["foo", "bar", "baz"] - ) - );', - ], - 'arrayMapUntypedCallable' => [ - ' $array - */ - $a = array_map($callable, $array); - - /** - * @var callable $callable - * @var array $array - */ - $b = array_map($callable, $array, $array); - - /** - * @var callable $callable - * @var list $list - */ - $c = array_map($callable, $list); - - /** - * @var callable $callable - * @var list $list - */ - $d = array_map($callable, $list, $list);', - 'assertions' => [ - '$a' => 'array', - '$b' => 'list', - '$c' => 'list', - '$d' => 'list', - ], - ], - 'arrayFilterGoodArgs' => [ - ' [ - ' [], - 'error_levels' => ['UndefinedClass'], - ], - 'arrayFilterIgnoreMissingMethod' => [ - ' [], - 'error_levels' => ['UndefinedMethod'], - ], 'validCallables' => [ ' [ - ' [ ' [ - ' [ ' [ - ' 1, "two" => 3]; - $b = key($a); - $c = $a[$b];', - 'assertions' => [ - '$b' => 'null|string', - '$c' => 'int', - ], - ], - 'array_key_first' => [ - ' 1, "two" => 3]; - $b = array_key_first($a); - $c = $a[$b];', - 'assertions' => [ - '$b' => 'null|string', - '$c' => 'int', - ], - ], - 'array_key_last' => [ - ' 1, "two" => 3]; - $b = array_key_last($a); - $c = $a[$b];', - 'assertions' => [ - '$b' => 'null|string', - '$c' => 'int', - ], - ], 'explode' => [ ' 'list', ], ], - 'arrayColumnInference' => [ - '> */ - function makeGenericArray(): array { return []; } - /** @return array */ - function makeShapeArray(): array { return []; } - /** @return array */ - function makeUnionArray(): array { return []; } - $a = array_column([[1], [2], [3]], 0); - $b = array_column([["a" => 1], ["a" => 2], ["a" => 3]], "a"); - $c = array_column([["k" => "a", "v" => 1], ["k" => "b", "v" => 2]], "v", "k"); - $d = array_column([], 0); - $e = array_column(makeMixedArray(), 0); - $f = array_column(makeMixedArray(), 0, "k"); - $g = array_column(makeMixedArray(), 0, null); - $h = array_column(makeGenericArray(), 0); - $i = array_column(makeShapeArray(), 0); - $j = array_column(makeUnionArray(), 0); - ', - 'assertions' => [ - '$a' => 'list', - '$b' => 'list', - '$c' => 'array', - '$d' => 'list', - '$e' => 'list', - '$f' => 'array', - '$g' => 'list', - '$h' => 'list', - '$i' => 'list', - '$j' => 'list', - ], - ], 'strtrWithPossiblyFalseFirstArg' => [ ' [ - ' [ - '$bar' => 'array', - ], - ], - 'arrayIntersectIsVariadic' => [ - ' [], - ], - 'arrayIntersectKeyIsVariadic' => [ - ' [], - ], - 'arrayIntersectKeyNoReturnType' => [ - ' "hello"]; - } - - class C { - /** - * @psalm-suppress MissingReturnType - */ - public static function unknownStatic() { - return ["x" => "hello"]; - } - - /** - * @psalm-suppress MissingReturnType - */ - public static function unknownInstance() { - return ["x" => "hello"]; - } - } - - /** - * @psalm-suppress MixedArgument - */ - function sdn(array $s) : void { - $r = array_intersect_key(unknown(), array_filter($s)); - if (empty($r)) {} - - $r = array_intersect_key(C::unknownStatic(), array_filter($s)); - if (empty($r)) {} - - $r = array_intersect_key((new C)->unknownInstance(), array_filter($s)); - if (empty($r)) {} - }', - ], - 'arrayIntersectAssoc' => [ - ' $a - * @var array $b - * @var array $c - */ - $r = array_intersect_assoc($a, $b, $c);', - 'assertions' => [ - '$r' => 'array', - ], - ], - 'arrayReduce' => [ - ' [ - '$direct_closure_result' => 'int', - '$passed_closure_result' => 'int', - '$function_call_result' => 'int', - ], - ], - 'arrayReduceMixedReturn' => [ - ' [], - 'error_levels' => ['MissingClosureReturnType', 'MixedAssignment'], - ], 'versionCompare' => [ ' [], 'error_levels' => ['MixedMethodCall'], ], - 'arraySplice' => [ - ' [ - '$a' => 'non-empty-array', - '$b' => 'array{0: string, 1: string, 2: string}', - '$c' => 'array{0: int, 1: int, 2: int}', - ], - ], - 'arraySpliceOtherType' => [ - ' [ - '$d' => 'array', - ], - ], - 'ksortPreserveShape' => [ - ' 3, "b" => 4]; - ksort($a); - acceptsAShape($a); - - /** - * @param array{a:int,b:int} $a - */ - function acceptsAShape(array $a): void {}', - ], 'suppressError' => [ ' 'false|string', ], ], - 'arraySlicePreserveKeys' => [ - ' 1, "b" => 2, "c" => 3]; - $b = array_slice($a, 1, 2, true); - $c = array_slice($a, 1, 2, false); - $d = array_slice($a, 1, 2);', - 'assertions' => [ - '$b' => 'array', - '$c' => 'array', - '$d' => 'array', - ], - ], - 'arraySliceDontPreserveIntKeys' => [ - ' "a", 4 => "b", 3 => "c"]; - $b = array_slice($a, 1, 2, true); - $c = array_slice($a, 1, 2, false); - $d = array_slice($a, 1, 2);', - 'assertions' => [ - '$b' => 'array', - '$c' => 'list', - '$d' => 'list', - ], - ], 'printrOutput' => [ 'arr[] = get_class($anon_instance);', ], - 'arrayReversePreserveNonEmptiness' => [ - ' [ ' 'float|int|string', ], ], - 'inferArrayMapReturnType' => [ - ' */ - function Foo(DateTime ...$dateTimes) : array { - return array_map( - function ($dateTime) { - return (string) ($dateTime->format("c")); - }, - $dateTimes - ); - }', - ], - 'inferArrayMapArrowFunctionReturnType' => [ - ' */ - function Foo(DateTime ...$dateTimes) : array { - return array_map( - fn ($dateTime) => (string) ($dateTime->format("c")), - $dateTimes - ); - }', - ], 'noImplicitAssignmentToStringFromMixedWithDocblockTypes' => [ ' [ - ' 1, "bar" => 2], 10, 123); - $b = array_pad(["a", "b", "c"], 10, "x"); - /** @var list $list */ - $c = array_pad($list, 10, 0); - /** @var array $array */ - $d = array_pad($array, 10, "");', - 'assertions' => [ - '$a' => 'non-empty-array', - '$b' => 'non-empty-list', - '$c' => 'non-empty-list', - '$d' => 'non-empty-array', - ], - ], - 'arrayPadDynamicSize' => [ - ' 1, "bar" => 2], getSize(), 123); - $b = array_pad(["a", "b", "c"], getSize(), "x"); - /** @var list $list */ - $c = array_pad($list, getSize(), 0); - /** @var array $array */ - $d = array_pad($array, getSize(), "");', - 'assertions' => [ - '$a' => 'array', - '$b' => 'list', - '$c' => 'list', - '$d' => 'array', - ], - ], - 'arrayPadZeroSize' => [ - ' [ - '$result' => 'array', - ], - ], - 'arrayPadTypeCombination' => [ - ' 1, "bar" => "two"], 5, false); - $b = array_pad(["a", 2, 3.14], 5, null); - /** @var list $list */ - $c = array_pad($list, 5, 0); - /** @var array $array */ - $d = array_pad($array, 5, null);', - 'assertions' => [ - '$a' => 'non-empty-array', - '$b' => 'non-empty-list', - '$c' => 'non-empty-list', - '$d' => 'non-empty-array', - ], - ], - 'arrayPadMixed' => [ - ' [ - '$a' => 'non-empty-array', - '$b' => 'non-empty-list', - '$c' => 'non-empty-list', - '$d' => 'non-empty-array', - ], - ], - 'arrayPadFallback' => [ - ' [ - '$result' => 'array', - ], - ], - 'arrayChunk' => [ - ' $list */ - $b = array_chunk($list, 2); - /** @var array $arr */ - $c = array_chunk($arr, 2); - ', - 'assertions' => [ - '$a' => 'list>', - '$b' => 'list>', - '$c' => 'list>', - ], - ], - 'arrayChunkPreservedKeys' => [ - ' $list */ - $b = array_chunk($list, 2, true); - /** @var array $arr */ - $c = array_chunk($arr, 2, true);', - 'assertions' => [ - '$a' => 'list>', - '$b' => 'list>', - '$c' => 'list>', - ], - ], - 'arrayChunkPreservedKeysExplicitFalse' => [ - ' $arr */ - $result = array_chunk($arr, 2, false);', - 'assertions' => [ - '$result' => 'list>', - ], - ], - 'arrayChunkMixed' => [ - ' $list */ - $b = array_chunk($list, 2); - /** @var mixed[] $arr */ - $c = array_chunk($arr, 2);', - 'assertions' => [ - '$a' => 'list>', - '$b' => 'list>', - '$c' => 'list>', - ], - ], - 'arrayChunkFallback' => [ - ' [ - '$result' => 'list>', - ], - ], - 'arrayMapPreserveNonEmptiness' => [ - ' $strings - * @psalm-return non-empty-list - */ - function foo(array $strings): array { - return array_map("intval", $strings); - }' - ], - 'arrayMapZip' => [ - ' [ - ' [ - '$result' => 'array', - ], - ], - 'shuffle' => [ - ' 123, "bar" => 456]; - shuffle($array);', - 'assertions' => [ - '$array' => 'list', - ], - ], - 'sort' => [ - ' 123, "bar" => 456]; - sort($array);', - 'assertions' => [ - '$array' => 'list', - ], - ], - 'rsort' => [ - ' 123, "bar" => 456]; - sort($array);', - 'assertions' => [ - '$array' => 'list', - ], - ], - 'usort' => [ - ' 123, "bar" => 456]; - usort($array, function (int $a, int $b) { return $a <=> $b; });', - 'assertions' => [ - '$array' => 'list', - ], - ], - 'specialCaseArrayFilterOnSingleEntry' => [ - ' */ - function makeAList(int $ofThisInteger): array { - return array_filter([$ofThisInteger]); - }' - ], - 'arrayMapWithEmptyArrayReturn' => [ - '> $elements - * @return list - */ - function resolvePossibleFilePaths($elements) : array - { - return array_values( - array_filter( - array_merge( - ...array_map( - function (array $element) : array { - if (rand(0,1) == 1) { - return []; - } - return $element; - }, - $elements - ) - ) - ) - ); - }' - ], - 'arrayFilterArrowFunction' => [ - ' $x instanceof B - );', - 'assertions' => [ - '$a' => 'array', - '$b' => 'array', - ], - ], - 'arrayMergeTwoExplicitLists' => [ - ' $foo - */ - function foo(array $foo) : void {} - - $foo1 = [1, 2, 3]; - $foo2 = [1, 4, 5]; - foo(array_merge($foo1, $foo2));' - ], - 'arrayMergeTwoPossiblyFalse' => [ - ' 'list' - ], - ], 'callUserFunc' => [ ' [ - ' 5, "b" => 12, "c" => null], - function(?int $i) { - return $_GET["a"]; - } - );', - 'error_message' => 'MixedArgumentTypeCoercion', - 'error_levels' => ['MissingClosureParamType', 'MissingClosureReturnType'], - ], - 'arrayFilterUseMethodOnInferrableInt' => [ - 'foo(); });', - 'error_message' => 'InvalidMethodCall', - ], - 'arrayMapUseMethodOnInferrableInt' => [ - 'foo(); }, [1, 2, 3, 4]);', - 'error_message' => 'InvalidMethodCall', - ], 'invalidScalarArgument' => [ ' 'UndefinedFunction', ], - 'arrayMapWithNonCallableStringArray' => [ - ' 'InvalidArgument', - ], - 'arrayMapWithNonCallableIntArray' => [ - ' 'InvalidArgument', - ], 'objectLikeKeyChecksAgainstDifferentGeneric' => [ ' 'PossiblyInvalidFunctionCall', ], - 'arrayFilterBadArgs' => [ - ' 'InvalidScalarArgument', - ], - 'arrayFilterTooFewArgs' => [ - ' 'TooFewArguments', - ], - 'arrayMapBadArgs' => [ - ' 'InvalidScalarArgument', - ], - 'arrayMapTooFewArgs' => [ - ' 'TooFewArguments', - ], - 'arrayMapTooManyArgs' => [ - ' 'TooManyArguments', - ], 'varExportAssignmentToVoid' => [ ' 'InvalidArgument', ], - 'arrayReduceInvalidClosureTooFewArgs' => [ - ' 'InvalidArgument', - 'error_levels' => ['MixedTypeCoercion'], - ], - 'arrayReduceInvalidItemType' => [ - ' 'InvalidArgument', - 'error_levels' => ['MissingClosureReturnType'], - ], - 'arrayReduceInvalidCarryType' => [ - ' 'InvalidArgument', - 'error_levels' => ['MissingClosureReturnType'], - ], - 'arrayReduceInvalidCarryOutputType' => [ - ' 'InvalidArgument', - ], - 'arrayPopNotNull' => [ - ' $list - */ - function test(array $list) : void - { - while (!empty($list)) { - $tmp = array_pop($list); - if ($tmp === null) {} - } - }', - 'error_message' => 'DocblockTypeContradiction', - ], 'getTypeInvalidValue' => [ ' 'InvalidArgument', ], - 'usortInvalidCallableString' => [ - ' 'InvalidArgument', - ], 'functionCallOnMixed' => [ ' 'TypeDoesNotContainType', ], - 'arrayShiftUndefinedVariable' => [ - ' 'UndefinedVariable', - ], 'coerceCallMapArgsInStrictMode' => [ ' 'TypeDoesNotContainType', ], - 'arrayFilterObjectLike' => [ - ' $ints */ - function ints(array $ints) : void {} - $brr = array_filter([2,3,0,4,5]); - ints($brr);', - 'error_message' => 'ArgumentTypeCoercion - src/somefile.php:5:26 - Argument 1 of ints expects list, parent type array provided', - ], ]; } }