1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-30 04:39:00 +01:00

Begin fixing #8942

This commit is contained in:
Daniil Gentili 2022-12-19 12:55:32 +01:00
parent bde77f7a95
commit b91ad2cb1d
3 changed files with 74 additions and 9 deletions

View File

@ -650,17 +650,18 @@ class ArrayAssignmentAnalyzer
} else {
assert($array_atomic_type_list !== null);
$array_atomic_type = new TKeyedArray(
array_fill(
[...array_fill(
$atomic_root_type_array->getMinCount(),
count($atomic_root_type_array->properties)-1,
$array_atomic_type_list
), ...array_fill(
0,
count($atomic_root_type_array->properties),
$array_atomic_type_list,
),
count($atomic_root_type_array->properties)-1,
Type::getNever()
)],
null,
[
Type::getListKey(),
$array_atomic_type_list,
],
true,
null,
true
);
}
$from_countable_object_like = true;

View File

@ -85,6 +85,19 @@ class TKeyedArray extends Atomic
$this->fallback_params = $fallback_params;
$this->is_list = $is_list;
$this->from_docblock = $from_docblock;
if ($this->is_list) {
$last_k = -1;
$had_possibly_undefined = false;
ksort($this->properties);
foreach ($this->properties as $k => $v) {
if (is_string($k) || $last_k !== ($k-1) || ($had_possibly_undefined && !$v->possibly_undefined)) {
$this->is_list = false;
break;
}
$had_possibly_undefined = $v->possibly_undefined || $had_possibly_undefined;
$last_k = $k;
}
}
}
/**
@ -98,6 +111,19 @@ class TKeyedArray extends Atomic
}
$cloned = clone $this;
$cloned->properties = $properties;
if ($cloned->is_list) {
$last_k = -1;
$had_possibly_undefined = false;
ksort($cloned->properties);
foreach ($cloned->properties as $k => $v) {
if (is_string($k) || $last_k !== ($k-1) || ($had_possibly_undefined && !$v->possibly_undefined)) {
$cloned->is_list = false;
break;
}
$had_possibly_undefined = $v->possibly_undefined || $had_possibly_undefined;
$last_k = $k;
}
}
return $cloned;
}

View File

@ -433,6 +433,44 @@ class ArrayAccessTest extends TestCase
public function providerValidCodeParse(): iterable
{
return [
'testBuildList' => [
'code' => '<?php
$a = [];
if (random_int(0, 1)) {
$a []= 0;
}
if (random_int(0, 1)) {
$a []= 1;
}
$pre = $a;
$a []= 2;
',
'assertions' => [
'$pre===' => 'list{0?: 0|1, 1?: 1}',
'$a===' => 'list{0: 0|1|2, 1?: 1|2, 2?: 2}',
]
],
'testBuildListOther' => [
'code' => '<?php
$list = [];
$entropy = random_int(0, 2);
if ($entropy === 0) {
$list[] = "A";
} elseif ($entropy === 1) {
$list[] = "B";
}
$list[] = "C";
',
'assertions' => [
'$list===' => "list{0: 'A'|'B'|'C', 1?: 'C'}"
]
],
'instanceOfStringOffset' => [
'code' => '<?php
class A {