1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-27 04:45:20 +01:00

Fix #911 - properly substitute alias types

Also improve handling of array_splice
This commit is contained in:
Matthew Brown 2018-08-08 22:33:31 -04:00
parent 97bca6d762
commit 7c10a09ead
3 changed files with 86 additions and 6 deletions

View File

@ -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
)) {

View File

@ -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()

View File

@ -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;