Skip to content

Commit a1b24db

Browse files
committed
More fixes
1 parent f9250d5 commit a1b24db

File tree

4 files changed

+174
-169
lines changed

4 files changed

+174
-169
lines changed

src/Psalm/Internal/Analyzer/Statements/Expression/Call/ArrayFunctionArgumentsAnalyzer.php

+75-74
Original file line numberDiff line numberDiff line change
@@ -204,100 +204,101 @@ public static function handleAddition(
204204
if (($array_arg_type = $statements_analyzer->node_data->getType($array_arg))
205205
&& $array_arg_type->hasArray()
206206
) {
207-
$array_type = $array_arg_type->getArray();
207+
$array_types = $array_arg_type->getArrays();
208+
$by_ref_type = new Union([$array_types]);
208209

209-
$objectlike_list = null;
210+
foreach ($array_types as $array_type) {
211+
$objectlike_list = null;
210212

211-
if ($array_type instanceof TKeyedArray) {
212-
if ($array_type->is_list) {
213-
$objectlike_list = $array_type;
213+
if ($array_type instanceof TKeyedArray) {
214+
if ($array_type->is_list) {
215+
$objectlike_list = $array_type;
216+
}
214217
}
215-
}
216218

217-
$by_ref_type = new Union([$array_type]);
218-
219-
foreach ($args as $argument_offset => $arg) {
220-
if ($argument_offset === 0) {
221-
continue;
222-
}
219+
foreach ($args as $argument_offset => $arg) {
220+
if ($argument_offset === 0) {
221+
continue;
222+
}
223223

224-
if (ExpressionAnalyzer::analyze(
225-
$statements_analyzer,
226-
$arg->value,
227-
$context,
228-
) === false) {
229-
return false;
230-
}
224+
if (ExpressionAnalyzer::analyze(
225+
$statements_analyzer,
226+
$arg->value,
227+
$context,
228+
) === false) {
229+
return false;
230+
}
231231

232-
if ($method_id === 'array_unshift' && $nb_args === 2 && !$unpacked_args) {
233-
$new_offset_type = Type::getInt(false, 0);
234-
} else {
235-
$new_offset_type = Type::getInt();
236-
}
232+
if ($method_id === 'array_unshift' && $nb_args === 2 && !$unpacked_args) {
233+
$new_offset_type = Type::getInt(false, 0);
234+
} else {
235+
$new_offset_type = Type::getInt();
236+
}
237237

238-
if (!($arg_value_type = $statements_analyzer->node_data->getType($arg->value))
238+
if (!($arg_value_type = $statements_analyzer->node_data->getType($arg->value))
239239
|| $arg_value_type->hasMixed()
240-
) {
241-
$by_ref_type = Type::combineUnionTypes(
242-
$by_ref_type,
243-
new Union([new TArray([$new_offset_type, Type::getMixed()])]),
244-
);
245-
} elseif ($arg->unpack) {
246-
$arg_value_type = $arg_value_type->getBuilder();
247-
248-
foreach ($arg_value_type->getAtomicTypes() as $arg_value_atomic_type) {
249-
if ($arg_value_atomic_type instanceof TKeyedArray) {
250-
$was_list = $arg_value_atomic_type->is_list;
251-
252-
$arg_value_atomic_type = $arg_value_atomic_type->getGenericArrayType();
253-
254-
if ($was_list) {
255-
if ($arg_value_atomic_type instanceof TNonEmptyArray) {
256-
$arg_value_atomic_type = Type::getNonEmptyListAtomic(
257-
$arg_value_atomic_type->type_params[1],
258-
);
259-
} else {
260-
$arg_value_atomic_type = Type::getListAtomic(
261-
$arg_value_atomic_type->type_params[1],
262-
);
240+
) {
241+
$by_ref_type = Type::combineUnionTypes(
242+
$by_ref_type,
243+
new Union([new TArray([$new_offset_type, Type::getMixed()])]),
244+
);
245+
} elseif ($arg->unpack) {
246+
$arg_value_type = $arg_value_type->getBuilder();
247+
248+
foreach ($arg_value_type->getAtomicTypes() as $arg_value_atomic_type) {
249+
if ($arg_value_atomic_type instanceof TKeyedArray) {
250+
$was_list = $arg_value_atomic_type->is_list;
251+
252+
$arg_value_atomic_type = $arg_value_atomic_type->getGenericArrayType();
253+
254+
if ($was_list) {
255+
if ($arg_value_atomic_type instanceof TNonEmptyArray) {
256+
$arg_value_atomic_type = Type::getNonEmptyListAtomic(
257+
$arg_value_atomic_type->type_params[1],
258+
);
259+
} else {
260+
$arg_value_atomic_type = Type::getListAtomic(
261+
$arg_value_atomic_type->type_params[1],
262+
);
263+
}
263264
}
264-
}
265265

266-
$arg_value_type->addType($arg_value_atomic_type);
266+
$arg_value_type->addType($arg_value_atomic_type);
267+
}
267268
}
268-
}
269-
$arg_value_type = $arg_value_type->freeze();
269+
$arg_value_type = $arg_value_type->freeze();
270270

271-
$by_ref_type = Type::combineUnionTypes(
272-
$by_ref_type,
273-
$arg_value_type,
274-
);
275-
} else {
276-
if ($objectlike_list) {
277-
$properties = $objectlike_list->properties;
278-
array_unshift($properties, $arg_value_type);
279-
280-
$by_ref_type = new Union([$objectlike_list->setProperties($properties)]);
281-
} elseif ($array_type instanceof TArray && $array_type->isEmpty()) {
282-
$by_ref_type = new Union([new TKeyedArray([
283-
$arg_value_type,
284-
], null, null, true)]);
285-
} else {
286271
$by_ref_type = Type::combineUnionTypes(
287272
$by_ref_type,
288-
new Union(
289-
[
273+
$arg_value_type,
274+
);
275+
} else {
276+
if ($objectlike_list) {
277+
$properties = $objectlike_list->properties;
278+
array_unshift($properties, $arg_value_type);
279+
280+
$by_ref_type = new Union([$objectlike_list->setProperties($properties)]);
281+
} elseif ($array_type instanceof TArray && $array_type->isEmpty()) {
282+
$by_ref_type = new Union([new TKeyedArray([
283+
$arg_value_type,
284+
], null, null, true)]);
285+
} else {
286+
$by_ref_type = Type::combineUnionTypes(
287+
$by_ref_type,
288+
new Union(
289+
[
290290
new TNonEmptyArray(
291291
[
292292
$new_offset_type,
293293
$arg_value_type,
294294
],
295295
),
296-
],
297-
),
298-
null,
299-
true,
300-
);
296+
],
297+
),
298+
null,
299+
true,
300+
);
301+
}
301302
}
302303
}
303304
}

src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallReturnTypeFetcher.php

+1-9
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
use Psalm\Storage\FunctionLikeStorage;
2727
use Psalm\Type;
2828
use Psalm\Type\Atomic\ArrayInterface;
29-
use Psalm\Type\Atomic\TArray;
3029
use Psalm\Type\Atomic\TCallable;
3130
use Psalm\Type\Atomic\TCallableKeyedArray;
3231
use Psalm\Type\Atomic\TClassString;
@@ -429,14 +428,7 @@ private static function getReturnTypeFromCallMapWithArgs(
429428

430429
if ($first_arg_type = $statements_analyzer->node_data->getType($first_arg)) {
431430
if ($first_arg_type->hasArray()) {
432-
$array_type = $first_arg_type->getArray();
433-
if ($array_type instanceof TKeyedArray) {
434-
return $array_type->getGenericValueType();
435-
}
436-
437-
if ($array_type instanceof TArray) {
438-
return $array_type->type_params[1];
439-
}
431+
return $first_arg_type->getArrayValueType($codebase);
440432
} elseif ($first_arg_type->hasScalarType()
441433
&& ($second_arg = ($call_args[1]->value ?? null))
442434
&& ($second_arg_type = $statements_analyzer->node_data->getType($second_arg))

src/Psalm/Internal/Provider/ReturnTypeProvider/ArrayCombineReturnTypeProvider.php

+78-64
Original file line numberDiff line numberDiff line change
@@ -47,85 +47,99 @@ public static function getFunctionReturnType(FunctionReturnTypeProviderEvent $ev
4747
return null;
4848
}
4949

50-
$keys = $keys_type->getArray();
51-
if ($keys instanceof TArray && $keys->isEmptyArray()) {
52-
$keys = [];
53-
} elseif (!$keys instanceof TKeyedArray || $keys->fallback_params) {
54-
return null;
55-
} else {
56-
$keys = $keys->properties;
57-
}
58-
5950
if (!$values_type = $statements_source->node_data->getType($call_args[1]->value)) {
6051
return null;
6152
}
6253
if (!$values_type->isArray()) {
6354
return null;
6455
}
6556

66-
$values = $values_type->getArray();
67-
if ($values instanceof TArray && $values->isEmptyArray()) {
68-
$values = [];
69-
} elseif (!$values instanceof TKeyedArray || $values->fallback_params) {
70-
return null;
71-
} else {
72-
$values = $values->properties;
73-
}
74-
75-
76-
$keys_array = [];
77-
$is_list = true;
78-
$prev_key = -1;
79-
foreach ($keys as $key) {
80-
if ($key->possibly_undefined) {
81-
return null;
82-
}
83-
if ($key->isSingleIntLiteral()) {
84-
$key = $key->getSingleIntLiteral()->value;
85-
$keys_array []= $key;
86-
if ($is_list && $key-1 !== $prev_key) {
87-
$is_list = false;
88-
}
89-
$prev_key = $key;
90-
} elseif ($key->isSingleStringLiteral()) {
91-
$keys_array []= $key->getSingleStringLiteral()->value;
92-
$is_list = false;
57+
$has_fallback = false;
58+
$result = [];
59+
foreach ($values_type->getArrays() as $values) {
60+
if ($values instanceof TArray && $values->isEmptyArray()) {
61+
$values = [];
62+
} elseif (!$values instanceof TKeyedArray || $values->fallback_params) {
63+
$has_fallback = true;
64+
continue;
9365
} else {
94-
return null;
66+
$values = $values->properties;
67+
foreach ($values as $value) {
68+
if ($value->possibly_undefined) {
69+
$has_fallback = true;
70+
continue;
71+
}
72+
}
9573
}
96-
}
9774

98-
foreach ($values as $value) {
99-
if ($value->possibly_undefined) {
100-
return null;
101-
}
102-
}
75+
foreach ($keys_type->getArrays() as $keys) {
76+
$keys_array = [];
77+
78+
if ($keys instanceof TArray && $keys->isEmptyArray()) {
79+
$keys = [];
80+
} elseif (!$keys instanceof TKeyedArray || $keys->fallback_params) {
81+
$has_fallback = true;
82+
continue;
83+
} else {
84+
$keys = $keys->properties;
85+
$is_list = true;
86+
$prev_key = -1;
87+
88+
foreach ($keys as $key) {
89+
if ($key->possibly_undefined) {
90+
$has_fallback = true;
91+
continue;
92+
}
93+
if ($key->isSingleIntLiteral()) {
94+
$key = $key->getSingleIntLiteral()->value;
95+
$keys_array []= $key;
96+
if ($is_list && $key-1 !== $prev_key) {
97+
$is_list = false;
98+
}
99+
$prev_key = $key;
100+
} elseif ($key->isSingleStringLiteral()) {
101+
$keys_array []= $key->getSingleStringLiteral()->value;
102+
$is_list = false;
103+
} else {
104+
$has_fallback = true;
105+
continue;
106+
}
107+
}
108+
}
103109

104-
if (count($keys_array) !== count($values)) {
105-
IssueBuffer::maybeAdd(
106-
new InvalidArgument(
107-
'The keys array ' . $keys_type->getId() . ' must have exactly the same '
108-
. 'number of elements as the values array '
110+
if (count($keys_array) !== count($values)) {
111+
IssueBuffer::maybeAdd(
112+
new InvalidArgument(
113+
'The keys array ' . $keys_type->getId() . ' must have exactly the same '
114+
. 'number of elements as the values array '
109115
. $values_type->getId(),
110-
$event->getCodeLocation(),
111-
'array_combine',
112-
),
113-
$statements_source->getSuppressedIssues(),
114-
);
115-
return $statements_source->getCodebase()->analysis_php_version_id >= 8_00_00
116-
? Type::getNever()
117-
: Type::getFalse();
118-
}
116+
$event->getCodeLocation(),
117+
'array_combine',
118+
),
119+
$statements_source->getSuppressedIssues(),
120+
);
121+
return $statements_source->getCodebase()->analysis_php_version_id >= 8_00_00
122+
? Type::getNever()
123+
: Type::getFalse();
124+
}
125+
126+
$temp = array_combine(
127+
$keys_array,
128+
$values,
129+
);
119130

120-
$result = array_combine(
121-
$keys_array,
122-
$values,
123-
);
131+
if ($temp) {
132+
$result []= Type::getEmptyArrayAtomic();
133+
} else {
134+
$result []= new TKeyedArray($result, null, null, $is_list);
135+
}
136+
}
137+
}
124138

125-
if (!$result) {
126-
return Type::getEmptyArray();
139+
if ($has_fallback) {
140+
$result []= new TArray([Type::getArrayKey(), Type::getMixed()]);
127141
}
128142

129-
return new Union([new TKeyedArray($result, null, null, $is_list)]);
143+
return new Union($result);
130144
}
131145
}

0 commit comments

Comments
 (0)