mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 04:45:20 +01:00
Remove object-like array under falsy assertion when it contains a sure key
This commit is contained in:
parent
cf02e9c22c
commit
a001616753
@ -190,6 +190,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
$codebase,
|
||||
$context,
|
||||
$lhs_type_part,
|
||||
$lhs_type_part instanceof Type\Atomic\TNamedObject ? $lhs_type_part : null,
|
||||
$lhs_var_id,
|
||||
$return_type,
|
||||
$returns_by_ref,
|
||||
@ -393,6 +394,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
Codebase $codebase,
|
||||
Context $context,
|
||||
Type\Atomic $lhs_type_part,
|
||||
?Type\Atomic\TNamedObject $static_type,
|
||||
$lhs_var_id,
|
||||
&$return_type,
|
||||
&$returns_by_ref,
|
||||
@ -591,6 +593,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
$codebase,
|
||||
$context,
|
||||
$intersection_type,
|
||||
$lhs_type_part,
|
||||
$lhs_var_id,
|
||||
$intersection_return_type,
|
||||
$returns_by_ref,
|
||||
@ -1025,7 +1028,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
$codebase,
|
||||
$return_type_candidate,
|
||||
$fq_class_name,
|
||||
$lhs_type_part,
|
||||
$static_type,
|
||||
$class_storage->parent_class
|
||||
);
|
||||
} else {
|
||||
@ -1096,7 +1099,7 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\
|
||||
$codebase,
|
||||
$return_type_candidate,
|
||||
$self_fq_class_name,
|
||||
$lhs_type_part,
|
||||
$static_type,
|
||||
$class_storage->parent_class
|
||||
);
|
||||
|
||||
|
@ -98,7 +98,7 @@ class TypeCombination
|
||||
private $floats = [];
|
||||
|
||||
/**
|
||||
* @var array<int, TNamedObject|TTemplateParam|TIterable>|null
|
||||
* @var array<string, TNamedObject|TTemplateParam|TIterable>|null
|
||||
*/
|
||||
private $extra_types;
|
||||
|
||||
@ -400,7 +400,7 @@ class TypeCombination
|
||||
|
||||
if ($combination->extra_types) {
|
||||
$combination->extra_types = array_values(
|
||||
self::combineTypes($combination->extra_types, $codebase)->getTypes()
|
||||
self::combineTypes(array_values($combination->extra_types), $codebase)->getTypes()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -359,6 +359,8 @@ abstract class Type
|
||||
$parse_tree->children
|
||||
);
|
||||
|
||||
$keyed_intersection_types = [];
|
||||
|
||||
foreach ($intersection_types as $intersection_type) {
|
||||
if (!$intersection_type instanceof TNamedObject
|
||||
&& !$intersection_type instanceof TTemplateParam
|
||||
@ -368,13 +370,13 @@ abstract class Type
|
||||
'Intersection types must all be objects, ' . get_class($intersection_type) . ' provided'
|
||||
);
|
||||
}
|
||||
|
||||
$keyed_intersection_types[$intersection_type->getKey()] = $intersection_type;
|
||||
}
|
||||
|
||||
/** @var TNamedObject|TTemplateParam */
|
||||
$first_type = array_shift($intersection_types);
|
||||
$first_type = array_shift($keyed_intersection_types);
|
||||
|
||||
/** @var array<int, TNamedObject|TTemplateParam> $intersection_types */
|
||||
$first_type->extra_types = $intersection_types;
|
||||
$first_type->extra_types = $keyed_intersection_types;
|
||||
|
||||
return $first_type;
|
||||
}
|
||||
@ -1357,13 +1359,14 @@ abstract class Type
|
||||
|
||||
$type_2_atomic_clone->extra_types = [];
|
||||
|
||||
$type_1_atomic->extra_types[] = $type_2_atomic_clone;
|
||||
$type_1_atomic->extra_types[$type_2_atomic_clone->getKey()] = $type_2_atomic_clone;
|
||||
|
||||
$type_2_atomic_intersection_types = $type_2_atomic->getIntersectionTypes();
|
||||
|
||||
if ($type_2_atomic_intersection_types) {
|
||||
foreach ($type_2_atomic_intersection_types as $type_2_intersection_type) {
|
||||
$type_1_atomic->extra_types[] = clone $type_2_intersection_type;
|
||||
$type_1_atomic->extra_types[$type_2_intersection_type->getKey()]
|
||||
= clone $type_2_intersection_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use Psalm\Codebase;
|
||||
trait HasIntersectionTrait
|
||||
{
|
||||
/**
|
||||
* @var array<int, TNamedObject|TTemplateParam|TIterable>|null
|
||||
* @var array<string, TNamedObject|TTemplateParam|TIterable>|null
|
||||
*/
|
||||
public $extra_types;
|
||||
|
||||
@ -58,11 +58,11 @@ trait HasIntersectionTrait
|
||||
*/
|
||||
public function addIntersectionType(TNamedObject $type)
|
||||
{
|
||||
$this->extra_types[] = $type;
|
||||
$this->extra_types[$type->getKey()] = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, TNamedObject|TTemplateParam|TIterable>|null
|
||||
* @return array<string, TNamedObject|TTemplateParam|TIterable>|null
|
||||
*/
|
||||
public function getIntersectionTypes()
|
||||
{
|
||||
@ -88,12 +88,12 @@ trait HasIntersectionTrait
|
||||
|
||||
foreach ($template_type->getTypes() as $template_type_part) {
|
||||
if ($template_type_part instanceof TNamedObject) {
|
||||
$new_types[] = $template_type_part;
|
||||
$new_types[$template_type_part->getKey()] = $template_type_part;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$extra_type->replaceTemplateTypesWithArgTypes($template_types, $codebase);
|
||||
$new_types[] = $extra_type;
|
||||
$new_types[$extra_type->getKey()] = $extra_type;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -558,7 +558,13 @@ class Reconciler
|
||||
$array_atomic_type = $existing_var_atomic_types['array'];
|
||||
|
||||
if ($array_atomic_type instanceof Type\Atomic\TNonEmptyArray
|
||||
|| ($array_atomic_type instanceof Type\Atomic\ObjectLike && $array_atomic_type->sealed)
|
||||
|| ($array_atomic_type instanceof Type\Atomic\ObjectLike
|
||||
&& array_filter(
|
||||
$array_atomic_type->properties,
|
||||
function (Type\Union $t) {
|
||||
return !$t->possibly_undefined;
|
||||
}
|
||||
))
|
||||
) {
|
||||
$did_remove_type = true;
|
||||
|
||||
|
@ -1321,6 +1321,18 @@ class TypeReconciliationTest extends TestCase
|
||||
$a = false;
|
||||
}',
|
||||
],
|
||||
'dontRewriteNullableArrayAfterEmptyCheck' => [
|
||||
'<?php
|
||||
/**
|
||||
* @param array{x:int,y:int}|null $start_pos
|
||||
* @return array{x:int,y:int}|null
|
||||
*/
|
||||
function foo(?array $start_pos) : ?array {
|
||||
if ($start_pos) {}
|
||||
|
||||
return $start_pos;
|
||||
}',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user