mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
Fix #911 - properly substitute alias types
Also improve handling of array_splice
This commit is contained in:
parent
97bca6d762
commit
7c10a09ead
@ -346,6 +346,84 @@ class CallChecker
|
||||
return;
|
||||
}
|
||||
|
||||
if ($method_id && $method_id === 'array_splice' && $function_params && count($args) > 1) {
|
||||
$array_arg = $args[0]->value;
|
||||
|
||||
if (ExpressionChecker::analyze(
|
||||
$statements_checker,
|
||||
$array_arg,
|
||||
$context
|
||||
) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$offset_arg = $args[1]->value;
|
||||
|
||||
if (ExpressionChecker::analyze(
|
||||
$statements_checker,
|
||||
$offset_arg,
|
||||
$context
|
||||
) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($args[2]) || !isset($args[3])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$length_arg = $args[2]->value;
|
||||
|
||||
if (ExpressionChecker::analyze(
|
||||
$statements_checker,
|
||||
$length_arg,
|
||||
$context
|
||||
) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$replacement_arg = $args[3]->value;
|
||||
|
||||
if (ExpressionChecker::analyze(
|
||||
$statements_checker,
|
||||
$replacement_arg,
|
||||
$context
|
||||
) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($array_arg->inferredType)
|
||||
&& $array_arg->inferredType->hasArray()
|
||||
&& isset($replacement_arg->inferredType)
|
||||
&& $replacement_arg->inferredType->hasArray()
|
||||
) {
|
||||
/** @var TArray|ObjectLike */
|
||||
$array_type = $array_arg->inferredType->getTypes()['array'];
|
||||
|
||||
if ($array_type instanceof ObjectLike) {
|
||||
$array_type = $array_type->getGenericArrayType();
|
||||
}
|
||||
|
||||
/** @var TArray|ObjectLike */
|
||||
$replacement_array_type = $replacement_arg->inferredType->getTypes()['array'];
|
||||
|
||||
if ($replacement_array_type instanceof ObjectLike) {
|
||||
$replacement_array_type = $replacement_array_type->getGenericArrayType();
|
||||
}
|
||||
|
||||
$by_ref_type = Type\TypeCombination::combineTypes([$array_type, $replacement_array_type]);
|
||||
|
||||
ExpressionChecker::assignByRefParam(
|
||||
$statements_checker,
|
||||
$array_arg,
|
||||
$by_ref_type,
|
||||
$context,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($args as $argument_offset => $arg) {
|
||||
if ($function_params !== null) {
|
||||
$by_ref = $argument_offset < count($function_params)
|
||||
@ -712,7 +790,7 @@ class CallChecker
|
||||
'shuffle', 'sort', 'rsort', 'usort', 'ksort', 'asort',
|
||||
'krsort', 'arsort', 'natcasesort', 'natsort', 'reset',
|
||||
'end', 'next', 'prev', 'array_pop', 'array_shift',
|
||||
'array_push', 'array_unshift', 'socket_select',
|
||||
'array_push', 'array_unshift', 'socket_select', 'array_splice',
|
||||
],
|
||||
true
|
||||
)) {
|
||||
|
@ -245,8 +245,9 @@ class ReturnChecker
|
||||
} else {
|
||||
if (IssueBuffer::accepts(
|
||||
new InvalidReturnStatement(
|
||||
'The type \'' . $stmt->inferredType . '\' does not match the declared return '
|
||||
. 'type \'' . $local_return_type . '\' for ' . $cased_method_id,
|
||||
'The type \'' . $stmt->inferredType->getId()
|
||||
. '\' does not match the declared return '
|
||||
. 'type \'' . $local_return_type->getId() . '\' for ' . $cased_method_id,
|
||||
new CodeLocation($source, $stmt)
|
||||
),
|
||||
$statements_checker->getSuppressedIssues()
|
||||
|
@ -643,11 +643,12 @@ abstract class Type
|
||||
if (isset($type_aliases[$string_type_token])) {
|
||||
$replacement_tokens = $type_aliases[$string_type_token];
|
||||
|
||||
array_unshift($replacement_tokens, '(');
|
||||
array_push($replacement_tokens, ')');
|
||||
|
||||
$diff = count($replacement_tokens) - 1;
|
||||
|
||||
for ($j = 0; $j < $diff + 1; $j++) {
|
||||
$type_tokens[$i + $j] = $replacement_tokens[$j];
|
||||
}
|
||||
array_splice($type_tokens, $i, 1, $replacement_tokens);
|
||||
|
||||
$i += $diff;
|
||||
$l += $diff;
|
||||
|
Loading…
Reference in New Issue
Block a user