1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-05 21:19:03 +01:00
psalm/tests/Loop/ForTest.php

238 lines
7.4 KiB
PHP
Raw Normal View History

<?php
2023-10-19 13:12:06 +02:00
declare(strict_types=1);
namespace Psalm\Tests\Loop;
2021-12-03 20:11:20 +01:00
use Psalm\Tests\TestCase;
2021-12-04 21:55:53 +01:00
use Psalm\Tests\Traits\InvalidCodeAnalysisTestTrait;
use Psalm\Tests\Traits\ValidCodeAnalysisTestTrait;
2021-06-08 04:55:21 +02:00
use const DIRECTORY_SEPARATOR;
2021-12-03 20:11:20 +01:00
class ForTest extends TestCase
{
2021-12-04 21:55:53 +01:00
use InvalidCodeAnalysisTestTrait;
use ValidCodeAnalysisTestTrait;
public function providerValidCodeParse(): iterable
{
return [
2022-12-18 18:19:22 +01:00
'forTrue' => [
'code' => '<?php
function ret(): int {
for (;;) {
return 1;
}
2022-12-18 17:15:15 +01:00
}',
2022-12-18 18:19:22 +01:00
],
'implicitFourthLoop' => [
'code' => '<?php
function test(): int {
$x = 0;
$y = 1;
$z = 2;
for ($i = 0; $i < 3; $i++) {
$x = $y;
$y = $z;
$z = 5;
}
return $x;
}',
],
'falseToBoolInContinueAndBreak' => [
'code' => '<?php
$a = false;
for ($i = 0; $i < 4; $i++) {
$j = rand(0, 10);
if ($j === 2) {
$a = true;
continue;
}
if ($j === 3) {
$a = true;
break;
}
}',
Add support for strict arrays, fix type alias intersection, fix array_is_list assertion on non-lists (#8395) * Immutable CodeLocation * Remove excess clones * Remove external clones * Remove leftover clones * Fix final clone issue * Immutable storages * Refactoring * Fixes * Fixes * Fix * Fix * Fixes * Simplify * Fixes * Fix * Fixes * Update * Fix * Cache global types * Fix * Update * Update * Fixes * Fixes * Refactor * Fixes * Fix * Fix * More caching * Fix * Fix * Update * Update * Fix * Fixes * Update * Refactor * Update * Fixes * Break one more test * Fix * FIx * Fix * Fix * Fix * Fix * Improve performance and readability * Equivalent logic * Fixes * Revert * Revert "Revert" This reverts commit f9175100c8452c80559234200663fd4c4f4dd889. * Fix * Fix reference bug * Make default TypeVisitor immutable * Bugfix * Remove clones * Partial refactoring * Refactoring * Fixes * Fix * Fixes * Fixes * cs-fix * Fix final bugs * Add test * Misc fixes * Update * Fixes * Experiment with removing different property * revert "Experiment with removing different property" This reverts commit ac1156e077fc4ea633530d51096d27b6e88bfdf9. * Uniform naming * Uniform naming * Hack hotfix * Clean up $_FILES ref #8621 * Undo hack, try fixing properly * Helper method * Remove redundant call * Partially fix bugs * Cleanup * Change defaults * Fix bug * Fix (?, hope this doesn't break anything else) * cs-fix * Review fixes * Bugfix * Bugfix * Improve logic * Add support for list{} and callable-list{} types, properly implement array_is_list assertions (fixes #8389) * Default to sealed arrays * Fix array_merge bug * Fixes * Fix * Sealed type checks * Properly infer properties-of and get_object_vars on final classes * Fix array_map zipping * Fix tests * Fixes * Fixes * Fix more stuff * Recursively resolve type aliases * Fix typo * Fixes * Fix array_is_list assertion on keyed array * Add BC docs * Fixes * fix * Update * Update * Update * Update * Seal arrays with count assertions * Fix #8528 * Fix * Update * Improve sealed array foreach logic * get_object_vars on template properties * Fix sealed array assertion reconciler logic * Improved reconciler * Add tests * Single source of truth for test types * Fix tests * Fixup tests * Fixup tests * Fixup tests * Update * Fix tests * Fix tests * Final fixes * Fixes * Use list syntax only when needed * Fix tests * Cs-fix * Update docs * Update docs * Update docs * Update docs * Update docs * Document missing types * Update docs * Improve class-string-map docs * Update * Update * I love working on psalm :) * Keep arrays unsealed by default * Fixup tests * Fix syntax mistake * cs-fix * Fix typo * Re-import missing types * Keep strict types only in return types * argc/argv fixes * argc/argv fixes * Fix test * Comment-out valinor code, pinging @romm pls merge https://github.com/CuyZ/Valinor/pull/246 so we can add valinor to the psalm docs :)
2022-11-05 22:34:42 +01:00
'assertions' => [
'$a' => 'bool',
],
],
'forLoopwithOKChange' => [
'code' => '<?php
$j = 5;
for ($i = $j; $i < 4; $i++) {
$j = 9;
}',
],
'preventNegativeZeroScrewingThingsUp' => [
'code' => '<?php
function foo() : void {
2022-01-23 22:05:38 +01:00
/** @var array<int, int> $v */
$v = [1 => 0];
for ($d = 0; $d <= 10; $d++) {
for ($k = -$d; $k <= $d; $k += 2) {
if ($k === -$d || ($k !== $d && $v[$k-1] < $v[$k+1])) {
$x = $v[$k+1];
} else {
$x = $v[$k-1] + 1;
}
$v[$k] = $x;
}
}
2019-03-23 19:27:54 +01:00
}',
],
'whileTrueWithBreak' => [
'code' => '<?php
for (;;) {
$a = "hello";
break;
}
for (;;) {
$b = 5;
break;
}',
'assertions' => [
'$a' => 'string',
'$b' => 'int',
],
],
'continueOutsideLoop' => [
'code' => '<?php
class Node {
/** @var Node|null */
public $next;
}
/** @return void */
function test(Node $head) {
for ($node = $head; $node; $node = $next) {
$next = $node->next;
$node->next = null;
}
}',
],
'echoAfterFor' => [
'code' => '<?php
for ($i = 0; $i < 5; $i++);
echo $i;',
],
'nestedEchoAfterFor' => [
'code' => '<?php
for ($i = 1; $i < 2; $i++) {
for ($j = 1; $j < 2; $j++) {}
}
2022-12-18 17:15:15 +01:00
echo $i * $j;',
],
'reconcileOuterVars' => [
'code' => '<?php
for ($i = 0; $i < 2; $i++) {
if ($i === 0) {
continue;
}
2022-12-18 17:15:15 +01:00
}',
],
'noException' => [
'code' => '<?php
/**
* @param list<int> $arr
*/
function cartesianProduct(array $arr) : void {
2023-10-26 12:25:12 +02:00
for ($i = 20; $i > 0 && $arr[$i] === 5 ; $i--) {}
2022-12-18 17:15:15 +01:00
}',
],
'noCrashOnLongThing' => [
'code' => '<?php
/**
* @param list<array{a: array{int, int}}> $data
*/
function makeData(array $data) : array {
while (rand(0, 1)) {
while (rand(0, 1)) {
while (rand(0, 1)) {
if (rand(0, 1)) {
continue;
}
/** @psalm-suppress PossiblyUndefinedArrayOffset */
$data[0]["a"] = array_merge($data[0]["a"], $data[0]["a"]);
}
}
}
return $data;
2022-12-18 17:15:15 +01:00
}',
],
2021-10-10 10:31:30 +02:00
'InfiniteForLoop' => [
'code' => '<?php
2021-10-10 10:31:30 +02:00
/**
* @return int
*/
function g() {
for (;;) {
return 1;
}
}
/**
* @return int
*/
function h() {
for (;1;) {
return 1;
}
2022-12-18 17:15:15 +01:00
}',
2021-10-10 10:31:30 +02:00
],
];
}
public function providerInvalidCodeParse(): iterable
{
return [
'possiblyUndefinedArrayInWhileAndForeach' => [
'code' => '<?php
for ($i = 0; $i < 4; $i++) {
while (rand(0,10) === 5) {
$array[] = "hello";
}
}
echo $array;',
2019-02-27 22:00:44 +01:00
'error_message' => 'PossiblyUndefinedGlobalVariable - src' . DIRECTORY_SEPARATOR . 'somefile.php:4:29 - Possibly undefined ' .
'global variable $array, first seen on line 4',
],
'forLoopInvalidation' => [
'code' => '<?php
for ($i = 0; $i < 4; $i++) {
foreach ([1, 2, 3] as $i) {}
}',
'error_message' => 'LoopInvalidation',
],
'forInfiniteNoBreak' => [
'code' => '<?php
for (;;) {
$a = "hello";
}
echo $a;',
'error_message' => 'UndefinedGlobalVariable',
],
'nestedEchoAfterFor' => [
'code' => '<?php
for ($i = 1; $i < 2; $i++) {
if (rand(0, 1)) break;
for ($j = 1; $j < 2; $j++) {}
}
echo $i * $j;',
'error_message' => 'PossiblyUndefinedGlobalVariable',
],
];
}
}