From 438096ee774c6606c8a5df4fb313bfcbe97477f0 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Tue, 27 Feb 2024 17:52:37 +0100 Subject: [PATCH] mFixes --- .../Expression/Call/ArgumentAnalyzer.php | 17 +------ .../Call/ArrayFunctionArgumentsAnalyzer.php | 6 +-- .../Expression/Fetch/ArrayFetchAnalyzer.php | 19 ++++---- .../Codebase/InternalCallMapHandler.php | 1 - .../Reflector/FunctionLikeDocblockScanner.php | 11 +---- src/Psalm/Type/UnionTrait.php | 47 ++++++++++++++++++- 6 files changed, 58 insertions(+), 43 deletions(-) diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php index 9bb21d65e97..e687818a467 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArgumentAnalyzer.php @@ -127,13 +127,7 @@ public static function checkArgumentMatches( && $param_type && $param_type->hasArray() ) { - foreach ($param_type->getArrays() as $array_type) { - if ($array_type instanceof TKeyedArray && $array_type->is_list) { - $param_types []= $array_type->getGenericValueType(); - } elseif ($array_type instanceof TArray) { - $param_types []= $array_type->type_params[1]; - } - } + $param_types = $param_type->getArrayValueTypes(); } elseif ($param_type) { $param_types = [$param_type]; } @@ -1251,14 +1245,7 @@ private static function verifyExplicitParam( } elseif ($param_type_part instanceof TCallable) { $can_be_callable_like_array = false; - foreach ($param_type->getArrays() as $param_array_type) { - $row_type = null; - if ($param_array_type instanceof TArray) { - $row_type = $param_array_type->type_params[1]; - } elseif ($param_array_type instanceof TKeyedArray) { - $row_type = $param_array_type->getGenericValueType(); - } - + foreach ($param_type->getArrayValueTypes() as $row_type) { if ($row_type && ($row_type->hasMixed() || $row_type->hasString()) ) { diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php index 2bee3430904..63b27577499 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php @@ -951,11 +951,7 @@ private static function checkClosureTypeArgs( continue; } - foreach ($array_arg_types[$i]->getArrays() as $array_arg_type) { - $input_type = $array_arg_type instanceof TKeyedArray - ? $array_arg_type->getGenericValueType() - : $array_arg_type->type_params[1]; - + foreach ($array_arg_types[$i]->getArrayValueTypes() as $input_type) { if ($input_type->hasMixed()) { continue; } diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php index b6a3ec6d85e..9afcc869afd 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/ArrayFetchAnalyzer.php @@ -229,18 +229,15 @@ public static function analyze( null, ); - if ($stmt->dim && $stmt_var_type->hasArray()) { - $array_type = $stmt_var_type->getArray(); - - if ($array_type instanceof TClassStringMap) { - $array_value_type = Type::getMixed(); - } elseif ($array_type instanceof TArray) { - $array_value_type = $array_type->type_params[1]; - } else { - $array_value_type = $array_type->getGenericValueType(); + if ($stmt->dim && ($array_value_type = $stmt_var_type->getArrayValueTypes())) { + $has_non_mixed = false; + foreach ($array_value_type as $t) { + if (!$t->isMixed()) { + $has_non_mixed = true; + break; + } } - - if ($context->inside_assignment || !$array_value_type->isMixed()) { + if ($context->inside_assignment || $has_non_mixed) { $can_store_result = true; } } diff --git a/src/Psalm/Internal/Codebase/InternalCallMapHandler.php b/src/Psalm/Internal/Codebase/InternalCallMapHandler.php index 98511b72244..88c742b57cf 100644 --- a/src/Psalm/Internal/Codebase/InternalCallMapHandler.php +++ b/src/Psalm/Internal/Codebase/InternalCallMapHandler.php @@ -13,7 +13,6 @@ use Psalm\NodeTypeProvider; use Psalm\Storage\FunctionLikeParameter; use Psalm\Type; -use Psalm\Type\Atomic\TArray; use Psalm\Type\Atomic\TCallable; use Psalm\Type\Atomic\TKeyedArray; use Psalm\Type\TaintKind; diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php index b1311e82029..afcae5e88b0 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/FunctionLikeDocblockScanner.php @@ -841,16 +841,9 @@ private static function improveParamsFromDocblock( } if (!$docblock_param_variadic && $storage_param->is_variadic) { - $array_param_types = []; - foreach ($new_param_type->getArrays() as $array_type) { - if ($array_type instanceof TKeyedArray) { - $array_param_types []= $array_type->getGenericValueType(); - } else { - $array_param_types []= $array_type->type_params[1]; - } - } + $array_param_types = $new_param_type->getArrayValueTypes(); if ($array_param_types) { - $new_param_type = new Union($array_param_types); + $new_param_type = Type::combineUnionTypeArray($array_param_types, $codebase); } } diff --git a/src/Psalm/Type/UnionTrait.php b/src/Psalm/Type/UnionTrait.php index dba995f26fb..1e31d1c8d70 100644 --- a/src/Psalm/Type/UnionTrait.php +++ b/src/Psalm/Type/UnionTrait.php @@ -7,6 +7,7 @@ use InvalidArgumentException; use Psalm\CodeLocation; use Psalm\Codebase; +use Psalm\Internal\Type\TypeCombiner; use Psalm\Internal\TypeVisitor\CanContainObjectTypeVisitor; use Psalm\Internal\TypeVisitor\ClasslikeReplacer; use Psalm\Internal\TypeVisitor\ContainsClassLikeVisitor; @@ -16,6 +17,7 @@ use Psalm\Internal\TypeVisitor\TypeScanner; use Psalm\StatementsSource; use Psalm\Storage\FileStorage; +use Psalm\Type; use Psalm\Type\Atomic\TArray; use Psalm\Type\Atomic\TCallable; use Psalm\Type\Atomic\TClassString; @@ -411,19 +413,59 @@ public function hasArray(): bool } /** - * @return list<(TArray|TKeyedArray)> + * @return list<(TArray|TKeyedArray|TClassStringMap)> */ public function getArrays(): array { $result = []; foreach ($this->types as $t) { - if ($t instanceof TKeyedArray || $t instanceof TArray) { + if ($t instanceof TKeyedArray || $t instanceof TArray || $t instanceof TClassStringMap) { $result []= $t; } } return $result; } + + /** + * @return list + */ + public function getArrayKeyTypes(): array + { + $result = []; + foreach ($this->types as $t) { + if ($t instanceof TKeyedArray) { + $result []= $t->getGenericKeyType(); + } elseif ($t instanceof TArray) { + $result []= $t->type_params[0]; + } elseif ($t instanceof TClassStringMap) { + $result []= Type::getClassString($t->as_type?->value ?? 'object'); + } + } + return $result; + } + + /** + * @return list + */ + public function getArrayValueTypes(): array + { + $result = []; + foreach ($this->types as $t) { + if ($t instanceof TKeyedArray) { + $result []= $t->getGenericValueType(); + } elseif ($t instanceof TArray) { + $result []= $t->type_params[1]; + } elseif ($t instanceof TClassStringMap) { + if ($t->as_type) { + $result []= new Union([$t->as_type]); + } else { + $result []= Type::getObject(); + } + } + } + return $result; + } /** * @psalm-mutation-free */ @@ -1090,6 +1132,7 @@ public function isArray(): bool foreach ($this->types as $t) { if (!$t instanceof TKeyedArray && !$t instanceof TArray + && !$t instanceof TClassStringMap ) { return false; }