Skip to content

Commit

Permalink
Merge pull request #10772 from weirdan/10766-named-parameters-for-cal…
Browse files Browse the repository at this point in the history
…lables
  • Loading branch information
weirdan committed Mar 2, 2024
2 parents cabcb02 + ceb2908 commit 20e8604
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 2 deletions.
7 changes: 7 additions & 0 deletions src/Psalm/Internal/Type/ParseTree/CallableParamTree.php
Expand Up @@ -12,4 +12,11 @@ final class CallableParamTree extends ParseTree
public bool $variadic = false;

public bool $has_default = false;

/**
* Param name, without the $ prefix
*
* @var null|non-empty-string
*/
public ?string $name = null;
}
7 changes: 6 additions & 1 deletion src/Psalm/Internal/Type/ParseTreeCreator.php
Expand Up @@ -30,6 +30,7 @@
use function preg_match;
use function strlen;
use function strtolower;
use function substr;

/**
* @internal
Expand Down Expand Up @@ -258,13 +259,17 @@ private function parseCallableParam(array $current_token, ParseTree $current_par
$current_token = $this->t < $this->type_token_count ? $this->type_tokens[$this->t] : null;
}

if (!$current_token || $current_token[0][0] !== '$') {
if (!$current_token || $current_token[0][0] !== '$' || strlen($current_token[0]) < 2) {
throw new TypeParseTreeException('Unexpected token after space');
}

$new_leaf = new CallableParamTree($current_parent);
$new_leaf->has_default = $has_default;
$new_leaf->variadic = $variadic;
$potential_name = substr($current_token[0], 1);
if ($potential_name !== false && $potential_name !== '') {
$new_leaf->name = $potential_name;
}

if ($current_parent !== $this->current_leaf) {
$new_leaf->children = [$this->current_leaf];
Expand Down
4 changes: 3 additions & 1 deletion src/Psalm/Internal/Type/TypeParser.php
Expand Up @@ -1277,6 +1277,7 @@ private static function getTypeFromCallableTree(
foreach ($parse_tree->children as $child_tree) {
$is_variadic = false;
$is_optional = false;
$param_name = '';

if ($child_tree instanceof CallableParamTree) {
if (isset($child_tree->children[0])) {
Expand All @@ -1294,6 +1295,7 @@ private static function getTypeFromCallableTree(

$is_variadic = $child_tree->variadic;
$is_optional = $child_tree->has_default;
$param_name = $child_tree->name ?? '';
} else {
if ($child_tree instanceof Value && strpos($child_tree->value, '$') > 0) {
$child_tree->value = preg_replace('/(.+)\$.*/', '$1', $child_tree->value);
Expand All @@ -1310,7 +1312,7 @@ private static function getTypeFromCallableTree(
}

$param = new FunctionLikeParameter(
'',
$param_name,
false,
$tree_type instanceof Union ? $tree_type : new Union([$tree_type]),
null,
Expand Down
2 changes: 2 additions & 0 deletions src/Psalm/Storage/FunctionLikeParameter.php
Expand Up @@ -15,6 +15,8 @@ final class FunctionLikeParameter implements HasAttributesInterface, TypeNode
use UnserializeMemoryUsageSuppressionTrait;

/**
* Parameter name, without `$`
*
* @var string
*/
public $name;
Expand Down
24 changes: 24 additions & 0 deletions tests/CallableTest.php
Expand Up @@ -1908,6 +1908,18 @@ function bar($cb_arg) {}
foo("bar");',
],
'callableWithNamedArguments' => [
'code' => <<<'PHP'
<?php
/** @param callable(int $i) $c */
function f(callable $c): void {
$c(i: 1);
}
PHP,
'assertions' => [],
'ignored_issues' => [],
'php_version' => '8.0',
],
];
}

Expand Down Expand Up @@ -2494,6 +2506,18 @@ function int_int_int_int_string(Closure $f): void {}
'ignored_issues' => [],
'php_version' => '8.0',
],
'callableWithInvalidNamedArguments' => [
'code' => <<<'PHP'
<?php
/** @param callable(int $a) $c */
function f(callable $c): void {
$c(b: 1);
}
PHP,
'error_message' => 'InvalidNamedArgument',
'ignored_issues' => [],
'php_version' => '8.0',
],
];
}
}

0 comments on commit 20e8604

Please sign in to comment.