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();
|
$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\TInt;
|
||||||
use Psalm\Type\Atomic\TMixed;
|
use Psalm\Type\Atomic\TMixed;
|
||||||
use Psalm\Type\Atomic\TNamedObject;
|
use Psalm\Type\Atomic\TNamedObject;
|
||||||
|
use Psalm\Type\Atomic\TNull;
|
||||||
use Psalm\Type\Atomic\TObject;
|
use Psalm\Type\Atomic\TObject;
|
||||||
use Psalm\Type\Atomic\TString;
|
use Psalm\Type\Atomic\TString;
|
||||||
use Psalm\Type\TypeCombination;
|
use Psalm\Type\TypeCombination;
|
||||||
@ -428,11 +429,13 @@ class ExpressionChecker
|
|||||||
|
|
||||||
foreach ($stmt->expr->inferredType->getTypes() as $type) {
|
foreach ($stmt->expr->inferredType->getTypes() as $type) {
|
||||||
if ($type instanceof Scalar) {
|
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) {
|
} elseif ($type instanceof TArray) {
|
||||||
$permissible_atomic_types[] = $type;
|
$permissible_atomic_types[] = clone $type;
|
||||||
} elseif ($type instanceof ObjectLike) {
|
} elseif ($type instanceof ObjectLike) {
|
||||||
$permissible_atomic_types[] = $type->getGenericArrayType();
|
$permissible_atomic_types[] = clone $type;
|
||||||
} else {
|
} else {
|
||||||
$all_permissible = false;
|
$all_permissible = false;
|
||||||
break;
|
break;
|
||||||
|
@ -1127,6 +1127,24 @@ class AnnotationTest extends TestCase
|
|||||||
|
|
||||||
bar(foo());'
|
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];
|
$arr[BAR] = [6];
|
||||||
$bar = $arr[BAR][0];',
|
$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