diff --git a/src/Psalm/Checker/FunctionChecker.php b/src/Psalm/Checker/FunctionChecker.php index 73d874afd..3018192e1 100644 --- a/src/Psalm/Checker/FunctionChecker.php +++ b/src/Psalm/Checker/FunctionChecker.php @@ -248,17 +248,23 @@ class FunctionChecker extends FunctionLikeChecker foreach ($call_map_function_args as $arg_name => $arg_type) { $by_reference = false; + $optional = false; if ($arg_name[0] === '&') { $arg_name = substr($arg_name, 1); $by_reference = true; } + if (substr($arg_name, -1) === '=') { + $arg_name = substr($arg_name, 0, -1); + $optional = true; + } + $function_types[] = new FunctionLikeParameter( $arg_name, $by_reference, $arg_type ? Type::parseString($arg_type) : Type::getMixed(), - true // @todo - need to have non-optional parameters + $optional ); } diff --git a/src/Psalm/Checker/FunctionLikeChecker.php b/src/Psalm/Checker/FunctionLikeChecker.php index bf144d82c..e1657c6db 100644 --- a/src/Psalm/Checker/FunctionLikeChecker.php +++ b/src/Psalm/Checker/FunctionLikeChecker.php @@ -827,8 +827,21 @@ abstract class FunctionLikeChecker implements StatementsSource $last_param = count($possible_function_params) ? $possible_function_params[count($possible_function_params) - 1] : null; + $mandatory_param_count = count($possible_function_params); + + foreach ($possible_function_params as $i => $possible_function_param) { + if ($possible_function_param->is_optional) { + $mandatory_param_count = $i; + break; + } + } + + if ($mandatory_param_count > count($args)) { + continue; + } + foreach ($args as $argument_offset => $arg) { - if (count($possible_function_params) <= $argument_offset && (!$last_param || $last_param->name !== '...')) { + if (count($possible_function_params) <= $argument_offset && (!$last_param || substr($last_param->name, 0, 3) !== '...')) { $all_args_match = false; break; }