1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Require callable() have a return type when in conditional

Fixes #3260
This commit is contained in:
Brown 2020-04-30 23:35:13 -04:00
parent bb1c8a9d74
commit 117a4d4d40
3 changed files with 41 additions and 1 deletions

View File

@ -340,6 +340,10 @@ class ParseTree
}
if ($current_parent && $current_parent instanceof ParseTree\ConditionalTree) {
if (count($current_parent->children) > 1) {
throw new TypeParseTreeException('Cannot process colon in conditional twice');
}
$current_leaf = $current_parent;
$current_parent = $current_parent->parent;
break;

View File

@ -859,6 +859,10 @@ abstract class Type
throw new TypeParseTreeException('Unrecognized template \'' . $template_param_name . '\'');
}
if (count($parse_tree->children) !== 2) {
throw new TypeParseTreeException('Invalid conditional');
}
$first_class = array_keys($template_type_map[$template_param_name])[0];
$conditional_type = self::getTypeFromTree(

View File

@ -714,6 +714,26 @@ class TypeParseTest extends TestCase
);
}
/**
* @return void
*/
public function testConditionalTypeWithCallableElseBool()
{
$this->expectException(\Psalm\Exception\TypeParseTreeException::class);
Type::parseString('(T is string ? callable() : bool)', null, ['T' => ['' => [Type::getArray()]]]);
}
/**
* @return void
*/
public function testConditionalTypeWithCallableReturningBoolElseBool()
{
$this->assertSame(
'(T is string ? callable():bool : bool)',
(string) Type::parseString('(T is string ? (callable() : bool) : bool)', null, ['T' => ['' => [Type::getArray()]]])
);
}
public function testConditionalTypeWithGenerics() : void
{
$this->assertSame(
@ -726,7 +746,19 @@ class TypeParseTest extends TestCase
);
}
public function testConditionalTypeWithCallable() : void
public function testConditionalTypeWithCallableBracketed() : void
{
$this->assertSame(
'(T is string ? callable(string, string):string : callable(mixed...):mixed)',
(string) Type::parseString(
'(T is string ? (callable(string, string):string) : (callable(mixed...):mixed))',
null,
['T' => ['' => [Type::getArray()]]]
)
);
}
public function testConditionalTypeWithCallableNotBracketed() : void
{
$this->assertSame(
'(T is string ? callable(string, string):string : callable(mixed...):mixed)',