1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-15 10:57:08 +01:00
psalm/tests/TypeReconciliation/TypeTest.php

1782 lines
59 KiB
PHP
Raw Normal View History

2016-04-04 01:47:06 +02:00
<?php
2019-12-06 20:58:18 +01:00
namespace Psalm\Tests\TypeReconciliation;
2016-04-04 01:47:06 +02:00
2021-12-03 20:11:20 +01:00
use Psalm\Tests\TestCase;
use Psalm\Tests\Traits\InvalidCodeAnalysisTestTrait;
use Psalm\Tests\Traits\ValidCodeAnalysisTestTrait;
use const DIRECTORY_SEPARATOR;
2021-12-03 20:11:20 +01:00
class TypeTest extends TestCase
2016-04-04 01:47:06 +02:00
{
2021-12-03 20:11:20 +01:00
use InvalidCodeAnalysisTestTrait;
use ValidCodeAnalysisTestTrait;
2016-04-04 06:17:19 +02:00
/**
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
*
2016-04-04 06:17:19 +02:00
*/
public function providerValidCodeParse(): iterable
2016-04-04 06:17:19 +02:00
{
return [
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
'sealArray' => [
'code' => '<?php
/** @var array */
$a = [];
assert(isset($a["a"]));
assert(count($a) === 1);
',
'assertions' => [
'$a===' => 'array{a: mixed}'
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
]
],
'sealedArrayCount' => [
'code' => '<?php
$a = random_int(0,1) ? [] : [0, 1];
$b = null;
if (count($a) === 2) {
$b = $a;
}',
'assertions' => [
'$a===' => 'list{0?: 0, 1?: 1}',
'$b===' => 'list{0, 1}|null'
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
]
],
'sealedArrayMagic' => [
'code' => '<?php
/** @var array{invoice?: string, utd?: "utd", cancel_agreement?: "test", installment?: "test"} */
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
$b = [];
$buttons = [];
foreach ($b as $text) {
$buttons[] = $text;
}
if (count($buttons) === 0) {
echo "Zero";
}
/** @var ?string */
$test = null;
$urls = array_filter([$test]);
$mainUrlSet = false;
foreach ($urls as $_) {
if (!$mainUrlSet) {
$mainUrlSet = true;
}
}
if (!$mainUrlSet) {
echo "SKIP";
}
/**
* @param string|list<bool|array{0:string, 1:string}> $time
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
*/
function mapTime($time): void
{
$atime = is_array($time) ? $time : [];
if ($time === "24h") {
return;
}
for ($day = 0; $day < 7; ++$day) {
if (!array_key_exists($day, $atime) || !is_array($atime[$day])) {
continue;
}
$dayWh = $atime[$day];
array_pop($dayWh);
}
}',
'assertions' => [
'$buttons===' => 'list<string>',
'$urls===' => 'list{0?: non-falsy-string}',
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
'$mainUrlSet===' => 'bool',
]
],
'validSealedArrayAssertions' => [
'code' => '<?php
/** @var array{a: string, b: string, c?: string} */
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
$a = [];
if (count($a) > 2) {
echo "Have C!";
}
if (count($a) < 3) {
echo "Do not have C!";
}
',
],
'validSealedArrayAssertions2' => [
'code' => '<?php
/** @var array{a: string, b: string, c?: string} */
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
$a = [];
assert(count($a) > 2);
',
'assertions' => [
'$a===' => 'array{a: string, b: string, c: string}',
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
]
],
2022-11-05 22:22:29 +01:00
'instanceOfInterface' => [
'code' => '<?php
interface Supplier {
public function get(): iterable;
}
class SomeClass {
protected Supplier|iterable $prop;
public function __construct(Supplier|iterable $value) {
$this->prop = $value;
}
public function do(): void {
$var = $this->prop;
if ($var instanceof Supplier) {
$var->get();
}
}
}',
'assertions' => [],
'ignored_issues' => [],
'php_version' => '8.0'
],
'nullableMethodWithTernaryGuard' => [
'code' => '<?php
class A {
/** @return void */
public function fooFoo() {}
2016-04-04 06:17:19 +02:00
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(A $a = null) {
$b = $a ? $a->fooFoo() : null;
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithTernaryIfNullGuard' => [
'code' => '<?php
class A {
/** @return void */
public function fooFoo() {}
2016-04-04 06:17:19 +02:00
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(A $a = null) {
$b = $a === null ? null : $a->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithTernaryEmptyGuard' => [
'code' => '<?php
class A {
/** @return void */
public function fooFoo() {}
2016-04-04 06:17:19 +02:00
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(A $a = null) {
$b = empty($a) ? null : $a->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithTernaryIsNullGuard' => [
'code' => '<?php
class A {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(A $a = null) {
$b = is_null($a) ? null : $a->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithIfGuard' => [
'code' => '<?php
class A {
/** @return void */
public function fooFoo() {}
2016-06-30 00:15:51 +02:00
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(A $a = null) {
if ($a) {
$a->fooFoo();
}
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithTernaryGuardWithThis' => [
'code' => '<?php
class A {
/** @return void */
public function fooFoo() {}
2016-06-30 00:15:51 +02:00
}
2017-06-29 16:22:49 +02:00
class B {
/** @var A|null */
public $a;
2017-06-29 16:22:49 +02:00
/** @return void */
public function barBar(A $a = null) {
$this->a = $a;
$b = $this->a ? $this->a->fooFoo() : null;
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithTernaryIfNullGuardWithThis' => [
'code' => '<?php
class A {
/** @return void */
public function fooFoo() {}
2016-06-30 00:15:51 +02:00
}
2017-06-29 16:22:49 +02:00
class B {
/** @var A|null */
public $a;
2017-06-29 16:22:49 +02:00
/** @return void */
public function barBar(A $a = null) {
$this->a = $a;
$b = $this->a === null ? null : $this->a->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithIfGuardWithThis' => [
'code' => '<?php
class A {
/** @return void */
public function fooFoo() {}
2016-07-08 00:10:01 +02:00
}
2017-06-29 16:22:49 +02:00
class B {
/** @var A|null */
public $a;
2017-06-29 16:22:49 +02:00
/** @return void */
public function barBar(A $a = null) {
$this->a = $a;
2017-06-29 16:22:49 +02:00
if ($this->a) {
$this->a->fooFoo();
}
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithExceptionThrown' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
2016-04-04 06:17:19 +02:00
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
if (!$one) {
throw new Exception();
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithRedefinitionAndElse' => [
'code' => '<?php
class One {
/** @var int|null */
public $two;
2017-06-29 16:22:49 +02:00
/** @return void */
public function fooFoo() {}
2016-04-04 06:17:19 +02:00
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
if (!$one) {
$one = new One();
}
else {
$one->two = 3;
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithBooleanIfGuard' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null, Two $two = null) {
if ($one && $two) {
$two->fooFoo();
}
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithNonNullBooleanIfGuard' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null, Two $two = null) {
if ($one !== null && $two) {
$one->fooFoo();
}
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithNonNullBooleanIfGuardAndBooleanAnd' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null, Two $two = null) {
2020-10-13 02:25:46 +02:00
if ($one !== null && ($two || rand(0, 1))) {
$one->fooFoo();
}
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodInConditionWithIfGuardBefore' => [
'code' => '<?php
class One {
/** @var string */
public $a = "";
2017-06-29 16:22:49 +02:00
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null, Two $two = null) {
if ($one === null) {
return;
}
2017-06-29 16:22:49 +02:00
if (!$one->a && $one->fooFoo()) {
// do something
}
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithBooleanIfGuardBefore' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null, Two $two = null) {
if ($one === null || $two === null) {
return;
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithGuardedRedefinition' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
if ($one === null) {
$one = new One();
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithGuardedRedefinitionInElse' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
if ($one) {
// do nothing
}
else {
$one = new One();
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithGuardedNestedRedefinition' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
$a = rand(0, 4);
2017-06-29 16:22:49 +02:00
if ($one === null) {
if ($a === 4) {
$one = new One();
}
else {
$one = new One();
}
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithGuardedSwitchRedefinition' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
$a = rand(0, 4);
2017-06-29 16:22:49 +02:00
if ($one === null) {
switch ($a) {
case 4:
$one = new One();
break;
2017-06-29 16:22:49 +02:00
default:
$one = new One();
break;
}
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithGuardedSwitchRedefinitionDueToException' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/**
* @return void
*/
public function barBar(One $one = null) {
$a = rand(0, 4);
2017-06-29 16:22:49 +02:00
if ($one === null) {
switch ($a) {
case 4:
$one = new One();
break;
2017-06-29 16:22:49 +02:00
default:
throw new \Exception("bad");
}
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithGuardedSwitchThatAlwaysReturns' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
$a = rand(0, 4);
2017-06-29 16:22:49 +02:00
if ($one === null) {
switch ($a) {
case 4:
return;
2017-06-29 16:22:49 +02:00
default:
return;
}
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithGuardedNestedRedefinitionWithReturn' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
$a = rand(0, 4);
2017-06-29 16:22:49 +02:00
if ($one === null) {
if ($a === 4) {
$one = new One();
return;
}
else {
$one = new One();
}
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithGuardedNestedRedefinitionWithElseReturn' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
$a = rand(0, 4);
2017-06-29 16:22:49 +02:00
if ($one === null) {
if ($a === 4) {
$one = new One();
}
else {
$one = new One();
return;
}
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithGuardedNestedRedefinitionWithElseifReturn' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
$a = rand(0, 4);
2017-06-29 16:22:49 +02:00
if ($one === null) {
if ($a === 4) {
$one = new One();
}
else if ($a === 3) {
// do nothing
return;
}
else {
$one = new One();
}
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithGuardedSwitchBreak' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
$a = 4;
2017-06-29 16:22:49 +02:00
switch ($a) {
case 4:
if ($one === null) {
break;
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
break;
}
}
2017-05-27 02:05:57 +02:00
}',
],
'nullableMethodWithGuardedRedefinitionOnThis' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @var One|null */
public $one;
2017-06-29 16:22:49 +02:00
/** @return void */
public function barBar(One $one = null) {
$this->one = $one;
2017-06-29 16:22:49 +02:00
if ($this->one === null) {
$this->one = new One();
}
2017-06-29 16:22:49 +02:00
$this->one->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'arrayUnionTypeAssertion' => [
'code' => '<?php
$ids = (1 + 1 === 2) ? [] : null;
2017-06-29 16:22:49 +02:00
if ($ids === null) {
$ids = [];
}',
'assertions' => [
2021-10-13 19:37:47 +02:00
'$ids' => 'array<never, never>',
2017-05-27 02:05:57 +02:00
],
],
'arrayUnionTypeAssertionWithIsArray' => [
'code' => '<?php
$ids = (1 + 1 === 2) ? [] : null;
2017-06-29 16:22:49 +02:00
if (!is_array($ids)) {
$ids = [];
}',
'assertions' => [
2021-10-13 19:37:47 +02:00
'$ids' => 'array<never, never>',
2017-05-27 02:05:57 +02:00
],
],
'2dArrayUnionTypeAssertionWithIsArray' => [
'code' => '<?php
/** @return array<array<string>>|null */
function foo() {
$ids = rand(0, 1) ? [["hello"]] : null;
2017-06-29 16:22:49 +02:00
if (is_array($ids)) {
return $ids;
}
2017-06-29 16:22:49 +02:00
return null;
2017-05-27 02:05:57 +02:00
}',
],
'variableReassignment' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function barBar() {}
}
2017-06-29 16:22:49 +02:00
$one = new One();
2017-06-29 16:22:49 +02:00
$one = new Two();
2017-06-29 16:22:49 +02:00
2017-05-27 02:05:57 +02:00
$one->barBar();',
],
'variableReassignmentInIf' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function barBar() {}
}
2017-06-29 16:22:49 +02:00
$one = new One();
2017-06-29 16:22:49 +02:00
if (1 + 1 === 2) {
$one = new Two();
2017-06-29 16:22:49 +02:00
$one->barBar();
2017-05-27 02:05:57 +02:00
}',
],
'unionTypeFlow' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function barBar() {}
}
2017-06-29 16:22:49 +02:00
class Three {
/** @return void */
public function baz() {}
}
2017-06-29 16:22:49 +02:00
/** @var One|Two|Three|null */
$var = null;
2017-06-29 16:22:49 +02:00
if ($var instanceof One) {
$var->fooFoo();
2016-04-04 22:33:26 +02:00
}
else {
if ($var instanceof Two) {
$var->barBar();
}
else if ($var) {
$var->baz();
}
2017-05-27 02:05:57 +02:00
}',
],
'unionTypeFlowWithThrow' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
2016-04-04 22:33:26 +02:00
}
2017-06-29 16:22:49 +02:00
/** @return void */
function a(One $var = null) {
if (!$var) {
throw new \Exception("some exception");
}
else {
$var->fooFoo();
}
2017-05-27 02:05:57 +02:00
}',
],
'unionTypeFlowWithElseif' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
/** @var One|null */
$var = null;
2017-06-29 16:22:49 +02:00
if (rand(0,100) === 5) {
2017-06-29 16:22:49 +02:00
2016-04-04 06:17:19 +02:00
}
elseif (!$var) {
2017-06-29 16:22:49 +02:00
2016-04-04 22:33:26 +02:00
}
2016-04-04 06:17:19 +02:00
else {
$var->fooFoo();
2017-05-27 02:05:57 +02:00
}',
],
'typedAdjustment' => [
'code' => '<?php
$var = 0;
2017-06-29 16:22:49 +02:00
if (5 + 3 === 8) {
$var = "hello";
2016-04-04 06:17:19 +02:00
}
2017-06-29 16:22:49 +02:00
echo $var;',
'assertions' => [
'$var' => 'int|string',
2017-05-27 02:05:57 +02:00
],
],
'typeMixedAdjustment' => [
'code' => '<?php
$var = 0;
2017-06-29 16:22:49 +02:00
$arr = ["hello"];
2017-06-29 16:22:49 +02:00
if (5 + 3 === 8) {
$var = $arr[0];
}
2017-06-29 16:22:49 +02:00
echo $var;',
'assertions' => [
'$var' => 'int|string',
2017-05-27 02:05:57 +02:00
],
],
'typeAdjustmentIfNull' => [
'code' => '<?php
class A {}
class B {}
2017-06-29 16:22:49 +02:00
$var = rand(0,10) > 5 ? new A : null;
2017-06-29 16:22:49 +02:00
if ($var === null) {
$var = new B;
}',
'assertions' => [
2017-06-29 16:22:49 +02:00
'$var' => 'A|B',
2017-05-27 02:05:57 +02:00
],
],
'whileTrue' => [
'code' => '<?php
class One {
/**
* @return array|false
*/
public function fooFoo(){
return rand(0,100) ? ["hello"] : false;
}
2017-06-29 16:22:49 +02:00
/** @return void */
public function barBar(){
while ($row = $this->fooFoo()) {
$row[0] = "bad";
}
}
2017-05-27 02:05:57 +02:00
}',
],
'passingParam' => [
'code' => '<?php
class A {}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(A $a) {}
}
2017-06-29 16:22:49 +02:00
$b = new B();
2017-05-27 02:05:57 +02:00
$b->barBar(new A);',
],
'nullToNullableParam' => [
'code' => '<?php
class A {}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(A $a = null) {}
}
2017-06-29 16:22:49 +02:00
$b = new B();
2017-05-27 02:05:57 +02:00
$b->barBar(null);',
],
'objectToNullableObjectParam' => [
'code' => '<?php
class A {}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(A $a = null) {}
}
2017-06-29 16:22:49 +02:00
$b = new B();
2017-05-27 02:05:57 +02:00
$b->barBar(new A);',
],
'paramCoercion' => [
'code' => '<?php
class A {}
class B extends A {
/** @return void */
public function barBar() {}
}
2017-06-29 16:22:49 +02:00
class C {
/** @return void */
function fooFoo(A $a) {
if ($a instanceof B) {
$a->barBar();
}
}
2017-05-27 02:05:57 +02:00
}',
],
'paramElseifCoercion' => [
'code' => '<?php
class A {}
class B extends A {
/** @return void */
public function barBar() {}
}
class C extends A {
/** @return void */
public function baz() {}
}
2017-06-29 16:22:49 +02:00
class D {
/** @return void */
function fooFoo(A $a) {
if ($a instanceof B) {
$a->barBar();
}
elseif ($a instanceof C) {
$a->baz();
}
}
2017-05-27 02:05:57 +02:00
}',
],
'plusPlus' => [
'code' => '<?php
$a = 0;
$b = $a++;',
'assertions' => [
2021-09-20 13:09:02 +02:00
'$a===' => '1',
2017-05-27 02:05:57 +02:00
],
],
'typedValueAssertion' => [
'code' => '<?php
/**
* @param array|string $a
*/
2018-01-11 21:50:45 +01:00
function fooFoo($a): void {
$b = "aadad";
2017-06-29 16:22:49 +02:00
if ($a === $b) {
echo substr($a, 1);
}
2017-05-27 02:05:57 +02:00
}',
],
'isIntOnUnaryPlus' => [
'code' => '<?php
$a = +"5";
if (!is_int($a)) {
2017-05-27 02:05:57 +02:00
}',
],
'suppressOneSuppressesAll' => [
'code' => '<?php
class A {
/** @return void */
public function fooFoo() {}
/** @return void */
public function barFoo() {}
}
class B {
/** @return void */
public function barBar(A $a = null) {
/** @psalm-suppress PossiblyNullReference */
$a->fooFoo();
$a->barFoo();
}
}',
'assertions' => [],
],
'trueFalseTest' => [
'code' => '<?php
class A {
/** @return true */
public function returnsTrue() { return true; }
/** @return false */
public function returnsFalse() { return false; }
/** @return bool */
public function returnsBool() {
if (rand() % 2 > 0) {
return true;
}
return false;
}
}',
],
'intersectionTypeAfterInstanceof' => [
'code' => '<?php
/**
* @psalm-consistent-constructor
*/
abstract class A {
/** @var string|null */
public $foo;
public static function getFoo(): void {
$a = new static();
if ($a instanceof I) {}
$a->foo = "bar";
}
}
interface I {}',
],
2018-01-20 17:48:16 +01:00
'intersectionTypeInsideInstanceof' => [
'code' => '<?php
/**
* @psalm-consistent-constructor
*/
2018-01-20 17:48:16 +01:00
abstract class A {
/** @var string|null */
public $foo;
public static function getFoo(): void {
$a = new static();
if ($a instanceof I) {
takesI($a);
takesA($a);
}
}
}
interface I {}
function takesI(I $i): void {}
function takesA(A $i): void {}',
],
2018-05-03 19:15:16 +02:00
'intersectionInNamespace' => [
'code' => '<?php
2018-05-03 19:15:16 +02:00
namespace NS;
use Countable;
class Item {}
/**
* @var iterable<Item>&Countable $collection
*/
$collection = [];
count($collection);
/**
* @param iterable<Item>&Countable $collection
*/
function mycount($collection): int {
return count($collection);
}
mycount($collection);',
],
'scalarTypeParam' => [
'code' => '<?php
/**
* @param scalar $var
*/
function test($var): void {}
test("a");
test(1);
test(1.1);
test(true);
test(false);',
],
'assignOpUpdateArray' => [
'code' => '<?php
$optgroup = ["a" => ""];
if (rand(0, 1)) {
$optgroup["a"] .= "v";
}
if ($optgroup["a"] !== "") {}'
],
'redefineArrayKeyInsideIsStringConditional' => [
'code' => '<?php
/**
* @param string|int $key
*/
function get($key, array $arr) : void {
if (!isset($arr[$key])) {
if (is_string($key)) {
$key = "p" . $key;
}
if (!isset($arr[$key])) {}
}
}'
],
2022-01-24 22:35:42 +01:00
'redefineArrayKeyInsideIsStringConditionalElse' => [
'code' => '<?php
/**
* @param string|int $key
*/
function get($key, array $arr) : void {
if (!isset($arr[$key])) {
if (!is_string($key)) {
// do nothing
} else {
$key = "p" . $key;
}
if (!isset($arr[$key])) {}
}
}'
],
'redefineArrayKeyInsideIsStringConditionalElseif' => [
'code' => '<?php
/**
* @param string|int $key
*/
function get($key, array $arr) : void {
if (!isset($arr[$key])) {
if (!is_string($key)) {
// do nothing
} elseif (rand(0, 1)) {
$key = "p" . $key;
}
if (!isset($arr[$key])) {}
}
}'
],
'redefineArrayKeyInsideIsStringConditionalWhile' => [
'code' => '<?php
/**
* @param string|int $key
*/
function get($key, array $arr) : void {
if (!isset($arr[$key])) {
while (rand(0, 1)) {
$key = "p" . $key;
}
if (!isset($arr[$key])) {}
}
}'
],
'redefineArrayKeyInsideIsIntConditional' => [
'code' => '<?php
/**
* @param string|int $key
*/
function get($key, array $arr) : void {
if (!isset($arr[$key])) {
if (is_int($key)) {
$key++;
}
if (!isset($arr[$key])) {}
}
}'
],
2020-02-22 18:34:27 +01:00
'arrayKeyCanBeNumeric' => [
'code' => '<?php
2020-02-22 18:34:27 +01:00
/** @param array<string> $arr */
function foo(array $arr) : void {
foreach ($arr as $k => $_) {
if (is_numeric($k)) {}
if (!is_numeric($k)) {}
2020-02-22 18:34:27 +01:00
}
}'
],
'narrowScalar' => [
'code' => '<?php
/** @var scalar $s */
$s = 1;
if (!is_int($s) && !is_bool($s) && !is_float($s)) {
strlen($s);
}'
],
'narrowWithCountToAllowNonTupleKeyedArray' => [
'code' => '<?php
/**
* @param list<string> $arr
*/
function foo($arr): void {
if (count($arr) === 2) {
consume($arr);
}
}
/**
* @param array{0:string, 1: string} $input
*/
function consume($input): void{}'
],
2021-07-26 09:50:12 +02:00
'notDateTimeWithDateTimeInterface' => [
'code' => '<?php
2021-07-26 14:56:15 +02:00
function foo(DateTimeInterface $dateTime): DateTimeInterface {
2021-07-26 09:50:12 +02:00
$dateInterval = new DateInterval("P1D");
2021-07-26 14:56:15 +02:00
if ($dateTime instanceof DateTime) {
2021-07-26 09:50:12 +02:00
$dateTime->add($dateInterval);
return $dateTime;
} else {
return $dateTime->add($dateInterval);
}
}
',
],
'notDateTimeImmutableWithDateTimeInterface' => [
'code' => '<?php
2021-07-26 14:56:15 +02:00
function foo(DateTimeInterface $dateTime): DateTimeInterface {
2021-07-26 09:50:12 +02:00
$dateInterval = new DateInterval("P1D");
2021-07-26 14:56:15 +02:00
if ($dateTime instanceof DateTimeImmutable) {
2021-07-26 09:50:12 +02:00
return $dateTime->add($dateInterval);
} else {
$dateTime->add($dateInterval);
return $dateTime;
}
}
',
],
'CountEqual0MakesNonEmptyArray' => [
'code' => '<?php
function a(array $a): void {
if (count($a) === 0) {
throw new \LogicException;
}
expectNonEmptyArray($a);
}
function b(array $a): void {
if (count($a) !== 0) {
expectNonEmptyArray($a);
}
}
function c(array $a): void {
if (count($a) === 0) {
throw new \LogicException;
} else {
expectNonEmptyArray($a);
}
}
/** @param non-empty-array $a */
function expectNonEmptyArray(array $a): array { return $a; }'
],
];
}
/**
* @return iterable<string,array{code:string,error_message:string,ignored_issues?:list<string>,php_version?:string}>
*/
public function providerInvalidCodeParse(): iterable
{
return [
'possiblyUndefinedVariable' => [
'code' => '<?php
if (rand(0, 1)) {
$a = 5;
}
echo $a;',
'error_message' => 'PossiblyUndefinedGlobalVariable',
],
'nullableMethodCall' => [
'code' => '<?php
class A {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(A $a = null) {
$a->fooFoo();
}
}',
2017-05-27 02:05:57 +02:00
'error_message' => 'PossiblyNullReference',
],
'nullableMethodCallWithThis' => [
'code' => '<?php
class A {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @var A|null */
protected $a;
2017-06-29 16:22:49 +02:00
/** @return void */
public function barBar(A $a = null) {
$this->a = $a;
$this->a->fooFoo();
}
}',
2017-05-27 02:05:57 +02:00
'error_message' => 'PossiblyNullReference',
],
'nullableMethodWithIfGuard' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null, Two $two = null) {
if ($one) {
$two->fooFoo();
}
}
}',
2017-05-27 02:05:57 +02:00
'error_message' => 'PossiblyNullReference',
],
'nullableMethodWithWrongBooleanIfGuard' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null, Two $two = null) {
if ($one || $two) {
$two->fooFoo();
}
}
}',
2017-05-27 02:05:57 +02:00
'error_message' => 'PossiblyNullReference',
],
'nullableMethodWithWrongIfGuardedBefore' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null, Two $two = null) {
if ($two === null) {
return;
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
}',
2017-05-27 02:05:57 +02:00
'error_message' => 'PossiblyNullReference',
],
'nullableMethodWithWrongBooleanIfGuardBefore' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null, Two $two = null) {
if ($one === null && $two === null) {
return;
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
}',
2019-03-01 21:55:20 +01:00
'error_message' => 'PossiblyNullReference',
],
'nullableMethodWithGuardedNestedIncompleteRedefinition' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null, Two $two = null) {
$a = rand(0, 4);
2017-06-29 16:22:49 +02:00
if ($one === null) {
if ($a === 4) {
$one = new One();
}
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
}',
2017-05-27 02:05:57 +02:00
'error_message' => 'PossiblyNullReference',
],
'nullableMethodWithGuardedSwitchRedefinitionNoDefault' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
$a = rand(0, 4);
2017-06-29 16:22:49 +02:00
if ($one === null) {
switch ($a) {
case 4:
$one = new One();
break;
}
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
}',
2017-05-27 02:05:57 +02:00
'error_message' => 'PossiblyNullReference',
],
'nullableMethodWithGuardedSwitchRedefinitionEmptyDefault' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
$a = rand(0, 4);
2017-06-29 16:22:49 +02:00
if ($one === null) {
switch ($a) {
case 4:
$one = new One();
break;
2017-06-29 16:22:49 +02:00
default:
break;
}
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
}',
2017-05-27 02:05:57 +02:00
'error_message' => 'PossiblyNullReference',
],
'nullableMethodWithGuardedNestedRedefinitionWithUselessElseReturn' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(One $one = null) {
$a = rand(0, 4);
2017-06-29 16:22:49 +02:00
if ($one === null) {
if ($a === 4) {
$one = new One();
}
else if ($a === 3) {
// do nothing
}
else {
$one = new One();
return;
}
}
2017-06-29 16:22:49 +02:00
$one->fooFoo();
}
}',
2017-05-27 02:05:57 +02:00
'error_message' => 'PossiblyNullReference',
],
'variableReassignmentInIfWithOutsideCall' => [
'code' => '<?php
class One {
/** @return void */
public function fooFoo() {}
2016-04-04 22:33:26 +02:00
}
2017-06-29 16:22:49 +02:00
class Two {
/** @return void */
public function barBar() {}
}
2017-06-29 16:22:49 +02:00
$one = new One();
2017-06-29 16:22:49 +02:00
if (1 + 1 === 2) {
$one = new Two();
2017-06-29 16:22:49 +02:00
$one->barBar();
}
2017-06-29 16:22:49 +02:00
$one->barBar();',
'error_message' => 'PossiblyUndefinedMethod',
],
'wrongParam' => [
'code' => '<?php
class A {}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(A $a) {}
2016-04-04 22:33:26 +02:00
}
2017-06-29 16:22:49 +02:00
$b = new B();
$b->barBar(5);',
2017-05-27 02:05:57 +02:00
'error_message' => 'InvalidArgument',
],
'intToNullableObjectParam' => [
'code' => '<?php
class A {}
2017-06-29 16:22:49 +02:00
class B {
/** @return void */
public function barBar(A $a = null) {}
}
2017-06-29 16:22:49 +02:00
$b = new B();
$b->barBar(5);',
2017-05-27 02:05:57 +02:00
'error_message' => 'InvalidArgument',
],
'paramCoercionWithBadArg' => [
'code' => '<?php
class A {}
class B extends A {
/** @return void */
public function blab() {}
}
2017-06-29 16:22:49 +02:00
class C {
/** @return void */
function fooFoo(A $a) {
if ($a instanceof B) {
$a->barBar();
}
}
}',
2017-05-27 02:05:57 +02:00
'error_message' => 'UndefinedMethod',
],
'nullCheckInsideForeachWithNoLeaveStatement' => [
'code' => '<?php
$a = null;
2017-06-29 16:22:49 +02:00
$a->fooBar();',
2017-05-27 02:05:57 +02:00
'error_message' => 'NullReference',
],
'possiblyUndefinedMethod' => [
'code' => '<?php
class A {
2018-01-11 21:50:45 +01:00
public function foo(): void {}
}
class B {
2018-01-11 21:50:45 +01:00
public function other(): void {}
}
2018-01-11 21:50:45 +01:00
function a(bool $cond): void {
if ($cond) {
$a = new A();
} else {
$a = new B();
}
if ($cond) {
$a->foo();
}
}',
'error_message' => 'PossiblyUndefinedMethod',
],
'notTrueTest' => [
'code' => '<?php
/** @return true */
function returnsTrue() { return rand() % 2 > 0; }
',
'error_message' => 'InvalidReturnStatement',
],
'notFalseTest' => [
'code' => '<?php
/** @return false */
function returnsFalse() { return rand() % 2 > 0; }
',
'error_message' => 'InvalidReturnStatement',
],
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
'invalidSealedArrayAssertion1' => [
'code' => '<?php
/** @var array{a: string, b: string, c?: string} */
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
$a = [];
if (count($a) > 1) {
}',
'error_message' => 'RedundantConditionGivenDocblockType'
],
'invalidSealedArrayAssertion2' => [
'code' => '<?php
/** @var array{a: string, b: string, c?: string} */
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
$a = [];
if (count($a) > 3) {
}',
'error_message' => 'DocblockTypeContradiction'
],
'invalidSealedArrayAssertion3' => [
'code' => '<?php
/** @var array{a: string, b: string, c?: string} */
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
$a = [];
if (count($a) > 4) {
}',
'error_message' => 'DocblockTypeContradiction'
],
'invalidSealedArrayAssertion4' => [
'code' => '<?php
/** @var array{a: string, b: string, c?: string} */
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
$a = [];
if (count($a) < 1) {
}',
2022-12-04 18:05:36 +01:00
'error_message' => 'DocblockTypeContradiction'
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
],
'invalidSealedArrayAssertion5' => [
'code' => '<?php
/** @var array{a: string, b: string, c?: string} */
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
$a = [];
if (count($a) < 2) {
}',
'error_message' => 'DocblockTypeContradiction'
],
'invalidSealedArrayAssertion6' => [
'code' => '<?php
/** @var array{a: string, b: string, c?: string} */
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
$a = [];
if (count($a) < 4) {
}',
'error_message' => 'RedundantConditionGivenDocblockType'
],
2018-01-20 17:48:16 +01:00
'intersectionTypeClassCheckAfterInstanceof' => [
'code' => '<?php
/**
* @psalm-consistent-constructor
*/
2018-01-20 17:48:16 +01:00
abstract class A {
/** @var string|null */
public $foo;
public static function getFoo(): void {
$a = new static();
if ($a instanceof B) {}
elseif ($a instanceof C) {}
else {}
takesB($a);
}
}
class B extends A {}
class C extends A {}
function takesB(B $i): void {}',
'error_message' => 'ArgumentTypeCoercion - src' . DIRECTORY_SEPARATOR . 'somefile.php:14:32 - Argument 1 of takesB expects B,'
2022-08-03 19:56:38 +02:00
. ' but parent type A&static provided',
2018-01-20 17:48:16 +01:00
],
'intersectionTypeInterfaceCheckAfterInstanceof' => [
'code' => '<?php
/**
* @psalm-consistent-constructor
*/
2018-01-20 17:48:16 +01:00
abstract class A {
/** @var string|null */
public $foo;
public static function getFoo(): void {
$a = new static();
if ($a instanceof I) {}
takesI($a);
}
}
interface I {}
function takesI(I $i): void {}',
2022-08-03 19:56:38 +02:00
'error_message' => 'InvalidArgument - src' . DIRECTORY_SEPARATOR . 'somefile.php:12:32 - Argument 1 of takesI expects I, but A&static provided',
2018-01-20 17:48:16 +01:00
],
];
2017-01-26 04:02:19 +01:00
}
2016-04-04 01:47:06 +02:00
}