From ce5460e85635ac5a28b578cbb0a9fc7ccfa0a2d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Unger?= Date: Thu, 12 Apr 2018 14:57:04 +0200 Subject: [PATCH] Strict iterator_to_array, do not overwite duplicate keys --- README.md | 1 + .../StrictCalls/StrictFunctionCallsRule.php | 19 ++++++++++--------- .../StrictFunctionCallsRuleTest.php | 8 ++++++++ tests/Rules/StrictCalls/data/strict-calls.php | 4 ++++ 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 06be467d..f782f86b 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ * `array_search` (3rd parameter) * `array_keys` (3rd parameter; only if the 2nd parameter `$search_value` is provided) * `base64_decode` (2nd parameter) +* Function `iterator_to_array` must be called with second parameter `$use_keys` set to `false` to not overwite duplicate iterator keys in the result. * Variables assigned in `while` loop condition and `for` loop initial assignment cannot be used after the loop. * Types in `switch` condition and `case` value must match. PHP compares them loosely by default and that can lead to unexpected results. * Statically declared methods are called statically. diff --git a/src/Rules/StrictCalls/StrictFunctionCallsRule.php b/src/Rules/StrictCalls/StrictFunctionCallsRule.php index e5977e09..be4b73ce 100644 --- a/src/Rules/StrictCalls/StrictFunctionCallsRule.php +++ b/src/Rules/StrictCalls/StrictFunctionCallsRule.php @@ -7,12 +7,13 @@ class StrictFunctionCallsRule implements \PHPStan\Rules\Rule { - /** @var int[] */ + /** @var array */ private $functionArguments = [ - 'in_array' => 2, - 'array_search' => 2, - 'base64_decode' => 1, - 'array_keys' => 2, + 'in_array' => [2, true], + 'array_search' => [2, true], + 'base64_decode' => [1, true], + 'array_keys' => [2, true], + 'iterator_to_array' => [1, false], ]; /** @var \PHPStan\Broker\Broker */ @@ -52,15 +53,15 @@ public function processNode(\PhpParser\Node $node, \PHPStan\Analyser\Scope $scop return []; } - $argumentPosition = $this->functionArguments[$functionName]; + $argumentPosition = $this->functionArguments[$functionName][0]; if (!array_key_exists($argumentPosition, $node->args)) { return [sprintf('Call to function %s() requires parameter #%d to be set.', $functionName, $argumentPosition + 1)]; } $argumentType = $scope->getType($node->args[$argumentPosition]->value); - $trueType = new ConstantBooleanType(true); - if (!$trueType->isSuperTypeOf($argumentType)->yes()) { - return [sprintf('Call to function %s() requires parameter #%d to be true.', $functionName, $argumentPosition + 1)]; + $strictType = new ConstantBooleanType((bool) $this->functionArguments[$functionName][1]); + if (!$strictType->isSuperTypeOf($argumentType)->yes()) { + return [sprintf('Call to function %s() requires parameter #%d to be %s.', $functionName, $argumentPosition + 1, (bool) $this->functionArguments[$functionName][1] ? 'true' : 'false')]; } return []; diff --git a/tests/Rules/StrictCalls/StrictFunctionCallsRuleTest.php b/tests/Rules/StrictCalls/StrictFunctionCallsRuleTest.php index 1a7d0f35..f606b5ee 100644 --- a/tests/Rules/StrictCalls/StrictFunctionCallsRuleTest.php +++ b/tests/Rules/StrictCalls/StrictFunctionCallsRuleTest.php @@ -67,6 +67,14 @@ public function testRule(): void 'Call to function array_keys() requires parameter #3 to be true.', 31, ], + [ + 'Call to function iterator_to_array() requires parameter #2 to be false.', + 34, + ], + [ + 'Call to function iterator_to_array() requires parameter #2 to be set.', + 35, + ], ]); } diff --git a/tests/Rules/StrictCalls/data/strict-calls.php b/tests/Rules/StrictCalls/data/strict-calls.php index 408fdf73..e379b656 100644 --- a/tests/Rules/StrictCalls/data/strict-calls.php +++ b/tests/Rules/StrictCalls/data/strict-calls.php @@ -29,3 +29,7 @@ /** @var bool $bool */ $bool = doFoo(); array_keys([1, 2, 3], 1, $bool); + +iterator_to_array(new \ArrayIterator([]), false); +iterator_to_array(new \ArrayIterator([]), true); +iterator_to_array(new \ArrayIterator([]));