mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
Fix #1044 - allow templated params in assert
This commit is contained in:
parent
2eb0122549
commit
d1baff4b92
@ -481,6 +481,7 @@ class FunctionCallChecker extends \Psalm\Checker\Statements\Expression\CallCheck
|
||||
self::applyAssertionsToContext(
|
||||
$function_storage->assertions,
|
||||
$stmt->args,
|
||||
$function_storage->template_typeof_params ?: [],
|
||||
$context,
|
||||
$statements_checker
|
||||
);
|
||||
|
@ -694,6 +694,7 @@ class MethodCallChecker extends \Psalm\Checker\Statements\Expression\CallChecker
|
||||
self::applyAssertionsToContext(
|
||||
$method_storage->assertions,
|
||||
$args,
|
||||
$method_storage->template_typeof_params ?: [],
|
||||
$context,
|
||||
$statements_checker
|
||||
);
|
||||
|
@ -512,6 +512,7 @@ class StaticCallChecker extends \Psalm\Checker\Statements\Expression\CallChecker
|
||||
self::applyAssertionsToContext(
|
||||
$method_storage->assertions,
|
||||
$stmt->args,
|
||||
$method_storage->template_typeof_params ?: [],
|
||||
$context,
|
||||
$statements_checker
|
||||
);
|
||||
|
@ -2092,6 +2092,7 @@ class CallChecker
|
||||
* @param \Psalm\Storage\Assertion[] $assertions
|
||||
* @param array<int, PhpParser\Node\Arg> $args
|
||||
* @param Context $context
|
||||
* @param array<int, string> $template_typeof_params
|
||||
* @param StatementsChecker $statements_checker
|
||||
*
|
||||
* @return void
|
||||
@ -2099,12 +2100,15 @@ class CallChecker
|
||||
protected static function applyAssertionsToContext(
|
||||
array $assertions,
|
||||
array $args,
|
||||
array $template_typeof_params,
|
||||
Context $context,
|
||||
StatementsChecker $statements_checker
|
||||
) {
|
||||
$type_assertions = [];
|
||||
|
||||
foreach ($assertions as $assertion) {
|
||||
$assertion_var_id = null;
|
||||
|
||||
if (is_int($assertion->var_id)) {
|
||||
if (!isset($args[$assertion->var_id])) {
|
||||
continue;
|
||||
@ -2115,10 +2119,26 @@ class CallChecker
|
||||
$arg_var_id = ExpressionChecker::getArrayVarId($arg_value, null, $statements_checker);
|
||||
|
||||
if ($arg_var_id) {
|
||||
$type_assertions[$arg_var_id] = $assertion->rule;
|
||||
$assertion_var_id = $arg_var_id;
|
||||
}
|
||||
} else {
|
||||
$type_assertions[$assertion->var_id] = $assertion->rule;
|
||||
$assertion_var_id = $assertion->var_id;
|
||||
}
|
||||
|
||||
if ($assertion_var_id) {
|
||||
$offset = array_search($assertion->rule[0][0], $template_typeof_params, true);
|
||||
|
||||
if ($offset !== false) {
|
||||
if (isset($args[$offset]->value->inferredType)) {
|
||||
$templated_type = $args[$offset]->value->inferredType;
|
||||
|
||||
if ($templated_type->isSingleStringLiteral()) {
|
||||
$type_assertions[$assertion_var_id] = [[$templated_type->getSingleStringLiteral()->value]];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$type_assertions[$assertion_var_id] = $assertion->rule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,6 +204,37 @@ class AssertTest extends TestCase
|
||||
$i = substr($_SERVER["abc"], 1, 2);
|
||||
}',
|
||||
],
|
||||
'assertTemplatedType' => [
|
||||
'<?php
|
||||
interface Foo {}
|
||||
|
||||
class Bar implements Foo {
|
||||
public function sayHello(): void {
|
||||
echo "Hello";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param class-string $type
|
||||
* @template T
|
||||
* @template-typeof T $type
|
||||
* @psalm-assert T $value
|
||||
*/
|
||||
function assertInstanceOf($value, string $type): void {
|
||||
// some code
|
||||
}
|
||||
|
||||
// Returns concreate implmenetation of Foo, which in this case is Bar
|
||||
function getImplementationOfFoo(): Foo {
|
||||
return new Bar();
|
||||
}
|
||||
|
||||
$bar = getImplementationOfFoo();
|
||||
assertInstanceOf($bar, Bar::class);
|
||||
|
||||
$bar->sayHello();'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user