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:
parent
bde77f7a95
commit
b91ad2cb1d
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user