mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
Allow @psalm-variadic to denote functions that use func_call_args
This commit is contained in:
parent
068dc41173
commit
a1acaa231a
@ -56,7 +56,7 @@ class CommentChecker
|
||||
|
||||
/**
|
||||
* @param string $comment
|
||||
* @psalm-return object-like{return_type:null|string,params:array<object-like{name:string,type:string},deprecated:bool,suppress:array<string>}
|
||||
* @psalm-return object-like{return_type:null|string,params:array<object-like{name:string,type:string},deprecated:bool,suppress:array<string>,variadic:boolean}
|
||||
*/
|
||||
public static function extractDocblockInfo($comment)
|
||||
{
|
||||
@ -108,6 +108,8 @@ class CommentChecker
|
||||
}
|
||||
}
|
||||
|
||||
$info['variadic'] = isset($comments['specials']['psalm-variadic']);
|
||||
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,12 @@ class FunctionChecker extends FunctionLikeChecker
|
||||
* @var array<string,array<string,array<FunctionLikeParameter>>>
|
||||
*/
|
||||
protected static $file_function_params = [];
|
||||
|
||||
/**
|
||||
* @var array<string,bool>
|
||||
*/
|
||||
protected static $variadic_functions = [];
|
||||
|
||||
protected static $builtin_function_params = [];
|
||||
protected static $builtin_functions = [];
|
||||
protected static $call_map = null;
|
||||
@ -74,6 +80,16 @@ class FunctionChecker extends FunctionLikeChecker
|
||||
return self::$file_function_params[$file_name][$function_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $function_id
|
||||
* @param string $file_name
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isVariadic($function_id, $file_name)
|
||||
{
|
||||
return isset(self::$variadic_functions[$file_name][$function_id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $function_id
|
||||
* @return void
|
||||
@ -153,6 +169,10 @@ class FunctionChecker extends FunctionLikeChecker
|
||||
self::$deprecated_functions[$file_name][$function_id] = true;
|
||||
}
|
||||
|
||||
if ($docblock_info['variadic']) {
|
||||
self::$variadic_functions[$file_name][$function_id] = true;
|
||||
}
|
||||
|
||||
$this->suppressed_issues = $docblock_info['suppress'];
|
||||
|
||||
if ($config->use_docblock_types) {
|
||||
|
@ -53,6 +53,12 @@ class MethodChecker extends FunctionLikeChecker
|
||||
protected static $method_suppress = [];
|
||||
protected static $deprecated_methods = [];
|
||||
|
||||
/**
|
||||
* A dictionary of variadic methods
|
||||
* @var array<string,bool>
|
||||
*/
|
||||
protected static $variadic_methods = [];
|
||||
|
||||
const VISIBILITY_PUBLIC = 1;
|
||||
const VISIBILITY_PROTECTED = 2;
|
||||
const VISIBILITY_PRIVATE = 3;
|
||||
@ -82,6 +88,19 @@ class MethodChecker extends FunctionLikeChecker
|
||||
return self::$method_params[$method_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method_id
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isVariadic($method_id)
|
||||
{
|
||||
self::registerClassMethod($method_id);
|
||||
|
||||
$method_id = self::getDeclaringMethodId($method_id);
|
||||
|
||||
return isset(self::$variadic_methods[$method_id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method_id
|
||||
* @return Type\Union|null
|
||||
@ -237,6 +256,10 @@ class MethodChecker extends FunctionLikeChecker
|
||||
self::$deprecated_methods[$method_id] = true;
|
||||
}
|
||||
|
||||
if ($docblock_info['variadic']) {
|
||||
self::$variadic_methods[$method_id] = true;
|
||||
}
|
||||
|
||||
$this->suppressed_issues = $docblock_info['suppress'];
|
||||
self::$method_suppress[$method_id] = $this->suppressed_issues;
|
||||
|
||||
@ -329,7 +352,8 @@ class MethodChecker extends FunctionLikeChecker
|
||||
|
||||
$cased_method_id = $method_id;
|
||||
$method_parts = explode('::', $method_id);
|
||||
$method_id = $method_parts[0] . '::' . strtolower($method_parts[1]);
|
||||
$method_parts[1] = strtolower($method_parts[1]);
|
||||
$method_id = implode('::', $method_parts);
|
||||
|
||||
self::registerClassMethod($method_id);
|
||||
|
||||
@ -337,6 +361,10 @@ class MethodChecker extends FunctionLikeChecker
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($method_parts[1] === '__construct') {
|
||||
|
||||
}
|
||||
|
||||
if (IssueBuffer::accepts(
|
||||
new UndefinedMethod('Method ' . $cased_method_id . ' does not exist', $file_name, $line_number),
|
||||
$suppresssed_issues
|
||||
|
@ -3546,8 +3546,17 @@ class StatementsChecker
|
||||
{
|
||||
$function_params = null;
|
||||
|
||||
$is_variadic = false;
|
||||
|
||||
if ($method_id) {
|
||||
$function_params = FunctionLikeChecker::getParamsById($method_id, $args, $this->file_name);
|
||||
|
||||
if (strpos($method_id, '::')) {
|
||||
$is_variadic = MethodChecker::isVariadic($method_id);
|
||||
}
|
||||
else {
|
||||
$is_variadic = FunctionChecker::isVariadic(strtolower($method_id), $this->file_name);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($args as $argument_offset => $arg) {
|
||||
@ -3640,7 +3649,10 @@ class StatementsChecker
|
||||
}
|
||||
|
||||
if ($method_id) {
|
||||
if (count($args) > count($function_params) && (!count($function_params) || $function_params[count($function_params) - 1]->name !== '...=')) {
|
||||
if (!$is_variadic
|
||||
&& count($args) > count($function_params)
|
||||
&& (!count($function_params) || $function_params[count($function_params) - 1]->name !== '...=')
|
||||
) {
|
||||
if (IssueBuffer::accepts(
|
||||
new TooManyArguments('Too many arguments for method ' . ($cased_method_id ?: $method_id), $this->checked_file_name, $line_number),
|
||||
$this->suppressed_issues
|
||||
|
Loading…
x
Reference in New Issue
Block a user