mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
Fix #947 - interpret type hints of unpacked args
This commit is contained in:
parent
14e336e69a
commit
8814dff3c1
@ -397,6 +397,33 @@ class AssignmentChecker
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($var_comments as $var_comment) {
|
||||
try {
|
||||
if ($var_comment->var_id === $list_var_id) {
|
||||
$var_comment_type = ExpressionChecker::fleshOutType(
|
||||
$statements_checker->getFileChecker()->project_checker,
|
||||
$var_comment->type,
|
||||
$context->self,
|
||||
$context->self
|
||||
);
|
||||
|
||||
$var_comment_type->setFromDocblock();
|
||||
|
||||
$new_assign_type = $var_comment_type;
|
||||
break;
|
||||
}
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
if (IssueBuffer::accepts(
|
||||
new InvalidDocblock(
|
||||
(string)$e->getMessage(),
|
||||
new CodeLocation($statements_checker->getSource(), $assign_var)
|
||||
)
|
||||
)) {
|
||||
// fall through
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$context->vars_in_scope[$list_var_id] = $new_assign_type ?: Type::getMixed();
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ use Psalm\Type\Atomic\TGenericParam;
|
||||
use Psalm\Type\Atomic\TInt;
|
||||
use Psalm\Type\Atomic\TMixed;
|
||||
use Psalm\Type\Atomic\TNamedObject;
|
||||
use Psalm\Type\Atomic\TNull;
|
||||
use Psalm\Type\Atomic\TObject;
|
||||
use Psalm\Type\Atomic\TString;
|
||||
use Psalm\Type\TypeCombination;
|
||||
@ -428,11 +429,13 @@ class ExpressionChecker
|
||||
|
||||
foreach ($stmt->expr->inferredType->getTypes() as $type) {
|
||||
if ($type instanceof Scalar) {
|
||||
$permissible_atomic_types[] = new TArray([Type::getInt(), new Type\Union([$type])]);
|
||||
$permissible_atomic_types[] = new ObjectLike([new Type\Union([$type])]);
|
||||
} elseif ($type instanceof TNull) {
|
||||
$permissible_atomic_types[] = new TArray([Type::getEmpty(), Type::getEmpty()]);
|
||||
} elseif ($type instanceof TArray) {
|
||||
$permissible_atomic_types[] = $type;
|
||||
$permissible_atomic_types[] = clone $type;
|
||||
} elseif ($type instanceof ObjectLike) {
|
||||
$permissible_atomic_types[] = $type->getGenericArrayType();
|
||||
$permissible_atomic_types[] = clone $type;
|
||||
} else {
|
||||
$all_permissible = false;
|
||||
break;
|
||||
|
@ -1127,6 +1127,24 @@ class AnnotationTest extends TestCase
|
||||
|
||||
bar(foo());'
|
||||
],
|
||||
'listUnpackWithDocblock' => [
|
||||
'<?php
|
||||
interface I {}
|
||||
|
||||
class A implements I {
|
||||
public function bar() : void {}
|
||||
}
|
||||
|
||||
/** @return I[] */
|
||||
function foo() : array {
|
||||
return [new A()];
|
||||
}
|
||||
|
||||
/** @var A $a1 */
|
||||
[$a1, $a2] = foo();
|
||||
|
||||
$a1->bar();',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -932,6 +932,15 @@ class ArrayAssignmentTest extends TestCase
|
||||
$arr[BAR] = [6];
|
||||
$bar = $arr[BAR][0];',
|
||||
],
|
||||
'castToArray' => [
|
||||
'<?php
|
||||
$a = (array) (rand(0, 1) ? [1 => "one"] : 0);
|
||||
$b = (array) null;',
|
||||
'assertions' => [
|
||||
'$a' => 'array{1?:string, 0?:int}',
|
||||
'$b' => 'array<empty, empty>',
|
||||
],
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user