mirror of
https://github.com/danog/psalm.git
synced 2024-12-11 16:59:45 +01:00
Merge pull request #10450 from nicelocal/fix_class_string_key
Fix shaped array class string key combination
This commit is contained in:
commit
f4e9837e27
@ -351,7 +351,9 @@ final class ArrayAssignmentAnalyzer
|
|||||||
if (!$has_matching_objectlike_property && !$has_matching_string) {
|
if (!$has_matching_objectlike_property && !$has_matching_string) {
|
||||||
$properties = [];
|
$properties = [];
|
||||||
$classStrings = [];
|
$classStrings = [];
|
||||||
$current_type = $current_type->setPossiblyUndefined(count($key_values) > 1);
|
$current_type = $current_type->setPossiblyUndefined(
|
||||||
|
$current_type->possibly_undefined || count($key_values) > 1,
|
||||||
|
);
|
||||||
foreach ($key_values as $key_value) {
|
foreach ($key_values as $key_value) {
|
||||||
$properties[$key_value->value] = $current_type;
|
$properties[$key_value->value] = $current_type;
|
||||||
if ($key_value instanceof TLiteralClassString) {
|
if ($key_value instanceof TLiteralClassString) {
|
||||||
|
@ -55,6 +55,9 @@ final class TypeCombination
|
|||||||
/** @var array<string|int, Union> */
|
/** @var array<string|int, Union> */
|
||||||
public array $objectlike_entries = [];
|
public array $objectlike_entries = [];
|
||||||
|
|
||||||
|
/** @var array<string, bool> */
|
||||||
|
public array $objectlike_class_string_keys = [];
|
||||||
|
|
||||||
public bool $objectlike_sealed = true;
|
public bool $objectlike_sealed = true;
|
||||||
|
|
||||||
public ?Union $objectlike_key_type = null;
|
public ?Union $objectlike_key_type = null;
|
||||||
|
@ -667,6 +667,7 @@ final class TypeCombiner
|
|||||||
|
|
||||||
$has_defined_keys = false;
|
$has_defined_keys = false;
|
||||||
|
|
||||||
|
$class_strings = $type->class_strings ?? [];
|
||||||
foreach ($type->properties as $candidate_property_name => $candidate_property_type) {
|
foreach ($type->properties as $candidate_property_name => $candidate_property_type) {
|
||||||
$value_type = $combination->objectlike_entries[$candidate_property_name] ?? null;
|
$value_type = $combination->objectlike_entries[$candidate_property_name] ?? null;
|
||||||
|
|
||||||
@ -706,6 +707,19 @@ final class TypeCombiner
|
|||||||
}
|
}
|
||||||
|
|
||||||
unset($missing_entries[$candidate_property_name]);
|
unset($missing_entries[$candidate_property_name]);
|
||||||
|
|
||||||
|
if (is_int($candidate_property_name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($combination->objectlike_class_string_keys[$candidate_property_name])) {
|
||||||
|
$combination->objectlike_class_string_keys[$candidate_property_name] =
|
||||||
|
$combination->objectlike_class_string_keys[$candidate_property_name]
|
||||||
|
&& ($class_strings[$candidate_property_name] ?? false);
|
||||||
|
} else {
|
||||||
|
$combination->objectlike_class_string_keys[$candidate_property_name] =
|
||||||
|
($class_strings[$candidate_property_name] ?? false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($type->fallback_params) {
|
if ($type->fallback_params) {
|
||||||
@ -1421,7 +1435,7 @@ final class TypeCombiner
|
|||||||
} else {
|
} else {
|
||||||
$objectlike = new TKeyedArray(
|
$objectlike = new TKeyedArray(
|
||||||
$combination->objectlike_entries,
|
$combination->objectlike_entries,
|
||||||
null,
|
array_filter($combination->objectlike_class_string_keys),
|
||||||
$sealed || $fallback_key_type === null || $fallback_value_type === null
|
$sealed || $fallback_key_type === null || $fallback_value_type === null
|
||||||
? null
|
? null
|
||||||
: [$fallback_key_type, $fallback_value_type],
|
: [$fallback_key_type, $fallback_value_type],
|
||||||
|
@ -1148,7 +1148,9 @@ class Reconciler
|
|||||||
|
|
||||||
$base_key = implode($key_parts);
|
$base_key = implode($key_parts);
|
||||||
|
|
||||||
$result_type = $result_type->setPossiblyUndefined(count($array_key_offsets) > 1);
|
$result_type = $result_type->setPossiblyUndefined(
|
||||||
|
$result_type->possibly_undefined || count($array_key_offsets) > 1,
|
||||||
|
);
|
||||||
|
|
||||||
foreach ($array_key_offsets as $array_key_offset) {
|
foreach ($array_key_offsets as $array_key_offset) {
|
||||||
if (isset($existing_types[$base_key]) && $array_key_offset !== false) {
|
if (isset($existing_types[$base_key]) && $array_key_offset !== false) {
|
||||||
|
@ -55,6 +55,24 @@ class ArrayAssignmentTest extends TestCase
|
|||||||
'$resultOpt===' => 'array{a?: true, b?: true}',
|
'$resultOpt===' => 'array{a?: true, b?: true}',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
'assignUnionOfLiteralsClassKeys' => [
|
||||||
|
'code' => '<?php
|
||||||
|
class a {}
|
||||||
|
class b {}
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
foreach ([a::class, b::class] as $k) {
|
||||||
|
$result[$k] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($result as $k => $v) {
|
||||||
|
$vv = new $k;
|
||||||
|
}',
|
||||||
|
'assertions' => [
|
||||||
|
'$result===' => 'array{a::class: true, b::class: true}',
|
||||||
|
],
|
||||||
|
],
|
||||||
'genericArrayCreationWithSingleIntValue' => [
|
'genericArrayCreationWithSingleIntValue' => [
|
||||||
'code' => '<?php
|
'code' => '<?php
|
||||||
$out = [];
|
$out = [];
|
||||||
|
Loading…
Reference in New Issue
Block a user