mirror of
https://github.com/danog/psalm.git
synced 2024-12-02 09:37:59 +01:00
Avoid TooManyArguments issues on mock classes
This commit is contained in:
parent
a8cbb89ce7
commit
900f86507d
@ -3062,12 +3062,18 @@ class StatementsChecker
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$has_mock = false;
|
||||||
|
|
||||||
if ($class_type && is_string($stmt->name)) {
|
if ($class_type && is_string($stmt->name)) {
|
||||||
$return_type = null;
|
$return_type = null;
|
||||||
|
|
||||||
foreach ($class_type->types as $type) {
|
foreach ($class_type->types as $type) {
|
||||||
$absolute_class = $type->value;
|
$absolute_class = $type->value;
|
||||||
|
|
||||||
|
$is_mock = self::isMock($absolute_class);
|
||||||
|
|
||||||
|
$has_mock = $has_mock || $is_mock;
|
||||||
|
|
||||||
switch ($absolute_class) {
|
switch ($absolute_class) {
|
||||||
case 'null':
|
case 'null':
|
||||||
if (IssueBuffer::accepts(
|
if (IssueBuffer::accepts(
|
||||||
@ -3118,66 +3124,66 @@ class StatementsChecker
|
|||||||
// fall through to default
|
// fall through to default
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (!method_exists($absolute_class, '__call') && !self::isMock($absolute_class) && !$this->isPhantomClass($absolute_class)) {
|
if (method_exists($absolute_class, '__call') || $is_mock || $this->isPhantomClass($absolute_class)) {
|
||||||
$does_class_exist = ClassLikeChecker::checkAbsoluteClassOrInterface(
|
$return_type = Type::getMixed();
|
||||||
$absolute_class,
|
continue;
|
||||||
$this->checked_file_name,
|
}
|
||||||
$stmt->getLine(),
|
|
||||||
$this->suppressed_issues
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!$does_class_exist) {
|
$does_class_exist = ClassLikeChecker::checkAbsoluteClassOrInterface(
|
||||||
return $does_class_exist;
|
$absolute_class,
|
||||||
}
|
$this->checked_file_name,
|
||||||
|
$stmt->getLine(),
|
||||||
|
$this->suppressed_issues
|
||||||
|
);
|
||||||
|
|
||||||
$method_id = $absolute_class . '::' . strtolower($stmt->name);
|
if (!$does_class_exist) {
|
||||||
$cased_method_id = $absolute_class . '::' . $stmt->name;
|
return $does_class_exist;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isset(self::$method_call_index[$method_id])) {
|
$method_id = $absolute_class . '::' . strtolower($stmt->name);
|
||||||
self::$method_call_index[$method_id] = [];
|
$cased_method_id = $absolute_class . '::' . $stmt->name;
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->source instanceof MethodChecker) {
|
if (!isset(self::$method_call_index[$method_id])) {
|
||||||
self::$method_call_index[$method_id][] = $this->source->getMethodId();
|
self::$method_call_index[$method_id] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->source instanceof MethodChecker) {
|
||||||
|
self::$method_call_index[$method_id][] = $this->source->getMethodId();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self::$method_call_index[$method_id][] = $this->source->getFileName();
|
||||||
|
}
|
||||||
|
|
||||||
|
$does_method_exist = MethodChecker::checkMethodExists($cased_method_id, $this->checked_file_name, $stmt->getLine(), $this->suppressed_issues);
|
||||||
|
|
||||||
|
if (!$does_method_exist) {
|
||||||
|
return $does_method_exist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
if (ClassLikeChecker::getThisClass() && ClassChecker::classExtends(ClassLikeChecker::getThisClass(), $this->absolute_class)) {
|
||||||
|
$calling_context = $context->self;
|
||||||
|
}
|
||||||
|
**/
|
||||||
|
|
||||||
|
if (MethodChecker::checkMethodVisibility($method_id, $context->self, $this->source, $stmt->getLine(), $this->suppressed_issues) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MethodChecker::checkMethodNotDeprecated($method_id, $this->checked_file_name, $stmt->getLine(), $this->suppressed_issues) === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$return_type_candidate = MethodChecker::getMethodReturnTypes($method_id);
|
||||||
|
|
||||||
|
if ($return_type_candidate) {
|
||||||
|
$return_type_candidate = self::fleshOutTypes($return_type_candidate, $stmt->args, $absolute_class, $method_id);
|
||||||
|
|
||||||
|
if (!$return_type) {
|
||||||
|
$return_type = $return_type_candidate;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self::$method_call_index[$method_id][] = $this->source->getFileName();
|
$return_type = Type::combineUnionTypes($return_type_candidate, $return_type);
|
||||||
}
|
|
||||||
|
|
||||||
$does_method_exist = MethodChecker::checkMethodExists($cased_method_id, $this->checked_file_name, $stmt->getLine(), $this->suppressed_issues);
|
|
||||||
|
|
||||||
if (!$does_method_exist) {
|
|
||||||
return $does_method_exist;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
if (ClassLikeChecker::getThisClass() && ClassChecker::classExtends(ClassLikeChecker::getThisClass(), $this->absolute_class)) {
|
|
||||||
$calling_context = $context->self;
|
|
||||||
}
|
|
||||||
**/
|
|
||||||
|
|
||||||
if (MethodChecker::checkMethodVisibility($method_id, $context->self, $this->source, $stmt->getLine(), $this->suppressed_issues) === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MethodChecker::checkMethodNotDeprecated($method_id, $this->checked_file_name, $stmt->getLine(), $this->suppressed_issues) === false) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$return_type_candidate = MethodChecker::getMethodReturnTypes($method_id);
|
|
||||||
|
|
||||||
if ($return_type_candidate) {
|
|
||||||
$return_type_candidate = self::fleshOutTypes($return_type_candidate, $stmt->args, $absolute_class, $method_id);
|
|
||||||
|
|
||||||
if (!$return_type) {
|
|
||||||
$return_type = $return_type_candidate;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$return_type = Type::combineUnionTypes($return_type_candidate, $return_type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$return_type = Type::getMixed();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -3189,7 +3195,7 @@ class StatementsChecker
|
|||||||
$stmt->inferredType = $return_type;
|
$stmt->inferredType = $return_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->checkFunctionArguments($stmt->args, $method_id, $context, $stmt->getLine()) === false) {
|
if ($this->checkFunctionArguments($stmt->args, $method_id, $context, $stmt->getLine(), $has_mock) === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3369,10 +3375,16 @@ class StatementsChecker
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$has_mock = false;
|
||||||
|
|
||||||
foreach ($lhs_type->types as $lhs_type_part) {
|
foreach ($lhs_type->types as $lhs_type_part) {
|
||||||
$absolute_class = $lhs_type_part->value;
|
$absolute_class = $lhs_type_part->value;
|
||||||
|
|
||||||
if (is_string($stmt->name) && !method_exists($absolute_class, '__callStatic') && !self::isMock($absolute_class)) {
|
$is_mock = self::isMock($absolute_class);
|
||||||
|
|
||||||
|
$has_mock = $has_mock || $is_mock;
|
||||||
|
|
||||||
|
if (is_string($stmt->name) && !method_exists($absolute_class, '__callStatic') && !$is_mock) {
|
||||||
$method_id = $absolute_class . '::' . strtolower($stmt->name);
|
$method_id = $absolute_class . '::' . strtolower($stmt->name);
|
||||||
$cased_method_id = $absolute_class . '::' . $stmt->name;
|
$cased_method_id = $absolute_class . '::' . $stmt->name;
|
||||||
|
|
||||||
@ -3428,7 +3440,7 @@ class StatementsChecker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->checkFunctionArguments($stmt->args, $method_id, $context, $stmt->getLine()) === false) {
|
if ($this->checkFunctionArguments($stmt->args, $method_id, $context, $stmt->getLine(), $has_mock) === false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3540,9 +3552,10 @@ class StatementsChecker
|
|||||||
* @param string $method_id
|
* @param string $method_id
|
||||||
* @param Context $context
|
* @param Context $context
|
||||||
* @param int $line_number
|
* @param int $line_number
|
||||||
|
* @param boolean $is_mock
|
||||||
* @return false|null
|
* @return false|null
|
||||||
*/
|
*/
|
||||||
protected function checkFunctionArguments(array $args, $method_id, Context $context, $line_number)
|
protected function checkFunctionArguments(array $args, $method_id, Context $context, $line_number, $is_mock = false)
|
||||||
{
|
{
|
||||||
$function_params = null;
|
$function_params = null;
|
||||||
|
|
||||||
@ -3552,7 +3565,7 @@ class StatementsChecker
|
|||||||
$function_params = FunctionLikeChecker::getParamsById($method_id, $args, $this->file_name);
|
$function_params = FunctionLikeChecker::getParamsById($method_id, $args, $this->file_name);
|
||||||
|
|
||||||
if (strpos($method_id, '::')) {
|
if (strpos($method_id, '::')) {
|
||||||
$is_variadic = MethodChecker::isVariadic($method_id);
|
$is_variadic = $is_mock || MethodChecker::isVariadic($method_id);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$is_variadic = FunctionChecker::isVariadic(strtolower($method_id), $this->file_name);
|
$is_variadic = FunctionChecker::isVariadic(strtolower($method_id), $this->file_name);
|
||||||
|
Loading…
Reference in New Issue
Block a user