From f8e22ab7accd24f0ead51c7bbe7ae9af112e8108 Mon Sep 17 00:00:00 2001 From: Matt Brown Date: Wed, 2 Dec 2020 14:42:16 -0500 Subject: [PATCH] Break out array_key_exists tests --- tests/ArrayAccessTest.php | 61 ---- tests/ArrayAssignmentTest.php | 70 ---- tests/ArrayFunctionCallTest.php | 18 - tests/ConstantTest.php | 31 -- .../TypeReconciliation/ArrayKeyExistsTest.php | 339 ++++++++++++++++++ tests/TypeReconciliation/ConditionalTest.php | 44 --- tests/TypeReconciliation/IssetTest.php | 43 --- .../RedundantConditionTest.php | 9 - tests/TypeReconciliation/ValueTest.php | 36 -- 9 files changed, 339 insertions(+), 312 deletions(-) create mode 100644 tests/TypeReconciliation/ArrayKeyExistsTest.php diff --git a/tests/ArrayAccessTest.php b/tests/ArrayAccessTest.php index e14a91b38..e8314ff20 100644 --- a/tests/ArrayAccessTest.php +++ b/tests/ArrayAccessTest.php @@ -776,67 +776,6 @@ class ArrayAccessTest extends TestCase ' "str"]["str"[0]];', ], - 'assertConstantOffsetsInMethod' => [ - ' ["foo" => true], - "b" => [] - ]; - - public function bar(string $key): bool { - if (!array_key_exists($key, self::ARR) || !array_key_exists("foo", self::ARR[$key])) { - return false; - } - - return self::ARR[$key]["foo"]; - } - }', - [], - ['MixedReturnStatement', 'MixedInferredReturnType'], - ], - 'assertSelfClassConstantOffsetsInFunction' => [ - ' ["foo" => true], - "b" => [] - ]; - - public function bar(?string $key): bool { - if ($key === null || !array_key_exists($key, self::ARR) || !array_key_exists("foo", self::ARR[$key])) { - return false; - } - - return self::ARR[$key]["foo"]; - } - }', - [], - ['MixedReturnStatement', 'MixedInferredReturnType'], - ], - 'assertNamedClassConstantOffsetsInFunction' => [ - ' ["foo" => true], - "b" => [], - ]; - } - - function bar(?string $key): bool { - if ($key === null || !array_key_exists($key, C::ARR) || !array_key_exists("foo", C::ARR[$key])) { - return false; - } - - return C::ARR[$key]["foo"]; - }', - [], - ['MixedReturnStatement', 'MixedInferredReturnType'], - ], 'arrayAccessAfterByRefArrayOffsetAssignment' => [ ' [ - ' 1]; - } else { - $a = [2, 3]; - } - - if (array_key_exists(0, $a)) { - echo $a[0]; - }', - ], - 'noCrashOnArrayKeyExistsBracket' => [ - 'getIterator(); - while ($iter->valid() && $count < $numToGet) { - $value = $iter->current(); - if ($value[0] != $commenter) { - if (!array_key_exists($value[0], $posters)) { - $posters[$value[0]] = 1; - $count++; - } - } - $iter->next(); - } - return array_keys($posters); - } - }', - 'assertions' => [], - 'error_levels' => [ - 'MixedArrayAccess', 'MixedAssignment', 'MixedArrayOffset', - 'MixedArgument', - ], - ], 'accessArrayAfterSuppressingBugs' => [ ' 'InvalidPropertyAssignmentValue', ], - 'possiblyUndefinedArrayAccessWithArrayKeyExistsOnWrongKey' => [ - ' 1]; - } else { - $a = [2, 3]; - } - - if (array_key_exists("a", $a)) { - echo $a[0]; - }', - 'error_message' => 'PossiblyUndefinedArrayOffset', - ], - 'possiblyUndefinedArrayAccessWithArrayKeyExistsOnMissingKey' => [ - ' 1]; - } else { - $a = [2, 3]; - } - - if (array_key_exists("b", $a)) { - echo $a[0]; - }', - 'error_message' => 'PossiblyUndefinedArrayOffset', - ], 'duplicateStringArrayKey' => [ ' [ - ' "a", - 404 => "b", - 500 => "c" - ]; - } - - function init(string $code) : string { - if (array_key_exists($code, HttpError::ERRS)) { - return $code; - } - - return ""; - }' - ], 'arrayChangeKeyCaseWithNonStringKeys' => [ ' [ - ' [C::class => "foo"], - 1 => [D::class => "bar"], - ]; - - private function foo(int $i) : void { - if (array_key_exists(C::class, self::FLAGS[$i])) { - echo self::FLAGS[$i][C::class]; - } - } - }' - ], 'getClassConstantOffset' => [ ' [ - ' [ ',error_levels?:string[]}> + */ + public function providerValidCodeParse(): iterable + { + return [ + 'arrayKeyExistsOnStringArrayShouldInformArrayness' => [ + ' [ + ' [ + ' [ + ' ["foo" => true], + "b" => [] + ]; + + public function bar(string $key): bool { + if (!array_key_exists($key, self::ARR) || !array_key_exists("foo", self::ARR[$key])) { + return false; + } + + return self::ARR[$key]["foo"]; + } + }', + [], + ['MixedReturnStatement', 'MixedInferredReturnType'], + ], + 'assertSelfClassConstantOffsetsInFunction' => [ + ' ["foo" => true], + "b" => [] + ]; + + public function bar(?string $key): bool { + if ($key === null || !array_key_exists($key, self::ARR) || !array_key_exists("foo", self::ARR[$key])) { + return false; + } + + return self::ARR[$key]["foo"]; + } + }', + [], + ['MixedReturnStatement', 'MixedInferredReturnType'], + ], + 'assertNamedClassConstantOffsetsInFunction' => [ + ' ["foo" => true], + "b" => [], + ]; + } + + function bar(?string $key): bool { + if ($key === null || !array_key_exists($key, C::ARR) || !array_key_exists("foo", C::ARR[$key])) { + return false; + } + + return C::ARR[$key]["foo"]; + }', + [], + ['MixedReturnStatement', 'MixedInferredReturnType'], + ], + 'possiblyUndefinedArrayAccessWithArrayKeyExists' => [ + ' 1]; + } else { + $a = [2, 3]; + } + + if (array_key_exists(0, $a)) { + echo $a[0]; + }', + ], + 'arrayKeyExistsShoudldNotModifyIntType' => [ + ' "a", + 404 => "b", + 500 => "c" + ]; + } + + function init(string $code) : string { + if (array_key_exists($code, HttpError::ERRS)) { + return $code; + } + + return ""; + }' + ], + 'arrayKeyExistsWithClassConst' => [ + ' [C::class => "foo"], + 1 => [D::class => "bar"], + ]; + + private function foo(int $i) : void { + if (array_key_exists(C::class, self::FLAGS[$i])) { + echo self::FLAGS[$i][C::class]; + } + } + }' + ], + 'constantArrayKeyExistsWithClassConstant' => [ + ' [ + 'format("Y-m-d"); + } + }', + ], + 'assertArrayKeyExistsRefinesType' => [ + ' */ + public const DAYS = [ + 1 => "mon", + 2 => "tue", + 3 => "wed", + 4 => "thu", + 5 => "fri", + 6 => "sat", + 7 => "sun", + ]; + + /** @param key-of $dayNum*/ + private static function doGetDayName(int $dayNum): string { + return self::DAYS[$dayNum]; + } + + /** @throws LogicException */ + public static function getDayName(int $dayNum): string { + if (! array_key_exists($dayNum, self::DAYS)) { + throw new \LogicException(); + } + return self::doGetDayName($dayNum); + } + }' + ], + 'arrayKeyExistsInferString' => [ + ' 1, "b" => 2])) { + return $file; + } + + return ""; + }', + [], + [], + '8.0' + ], + 'arrayKeyExistsComplex' => [ + ' 1, + "b" => 2, + "c" => 3, + "d" => 4, + "e" => 5, + "f" => 6, + "g" => 7, + "h" => 8, + "i" => 9, + "j" => 10, + "k" => 11, + ]; + + public function doWork(string $a): void { + if (!array_key_exists($a, self::MAP)) {} + } + }' + ], + 'arrayKeyExistsAccess' => [ + ' $arr */ + function foo(array $arr) : void { + if (array_key_exists(1, $arr)) { + $a = ($arr[1] === "b") ? true : false; + } + }', + ], + 'noCrashOnArrayKeyExistsBracket' => [ + 'getIterator(); + while ($iter->valid() && $count < $numToGet) { + $value = $iter->current(); + if ($value[0] != $commenter) { + if (!array_key_exists($value[0], $posters)) { + $posters[$value[0]] = 1; + $count++; + } + } + $iter->next(); + } + return array_keys($posters); + } + }', + 'assertions' => [], + 'error_levels' => [ + 'MixedArrayAccess', 'MixedAssignment', 'MixedArrayOffset', + 'MixedArgument', + ], + ], + ]; + } + + /** + * @return iterable + */ + public function providerInvalidCodeParse(): iterable + { + return [ + 'possiblyUndefinedArrayAccessWithArrayKeyExistsOnWrongKey' => [ + ' 1]; + } else { + $a = [2, 3]; + } + + if (array_key_exists("a", $a)) { + echo $a[0]; + }', + 'error_message' => 'PossiblyUndefinedArrayOffset', + ], + 'possiblyUndefinedArrayAccessWithArrayKeyExistsOnMissingKey' => [ + ' 1]; + } else { + $a = [2, 3]; + } + + if (array_key_exists("b", $a)) { + echo $a[0]; + }', + 'error_message' => 'PossiblyUndefinedArrayOffset', + ], + ]; + } +} diff --git a/tests/TypeReconciliation/ConditionalTest.php b/tests/TypeReconciliation/ConditionalTest.php index e997d6d0f..b41a43757 100644 --- a/tests/TypeReconciliation/ConditionalTest.php +++ b/tests/TypeReconciliation/ConditionalTest.php @@ -1394,22 +1394,6 @@ class ConditionalTest extends \Psalm\Tests\TestCase return $ret; }', ], - 'assertTypeNarrowedByNestedIsset' => [ - 'format("Y-m-d"); - } - }', - ], 'assertCheckOnNonZeroArrayOffset' => [ ' [ - ' */ - public const DAYS = [ - 1 => "mon", - 2 => "tue", - 3 => "wed", - 4 => "thu", - 5 => "fri", - 6 => "sat", - 7 => "sun", - ]; - - /** @param key-of $dayNum*/ - private static function doGetDayName(int $dayNum): string { - return self::DAYS[$dayNum]; - } - - /** @throws LogicException */ - public static function getDayName(int $dayNum): string { - if (! array_key_exists($dayNum, self::DAYS)) { - throw new \LogicException(); - } - return self::doGetDayName($dayNum); - } - }' - ], 'assertPropertiesOfElseStatement' => [ ' [ - ' [ ' [ - ' [ - ' [ ' [ - ' $arr */ - function foo(array $arr) : void { - if (array_key_exists(1, $arr)) { - $a = ($arr[1] === "b") ? true : false; - } - }', - ], 'noRedundantConditionStringNotFalse' => [ ' [ - ' 1, "b" => 2])) { - return $file; - } - - return ""; - }', - [], - [], - '8.0' - ], - 'arrayKeyExistsComplex' => [ - ' 1, - "b" => 2, - "c" => 3, - "d" => 4, - "e" => 5, - "f" => 6, - "g" => 7, - "h" => 8, - "i" => 9, - "j" => 10, - "k" => 11, - ]; - - public function doWork(string $a): void { - if (!array_key_exists($a, self::MAP)) {} - } - }' - ], ]; }