diff --git a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php index 368886122..b7ebb0b6b 100644 --- a/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php +++ b/src/Psalm/Internal/Analyzer/Statements/Expression/Call/MethodCallAnalyzer.php @@ -801,64 +801,64 @@ class MethodCallAnalyzer extends \Psalm\Internal\Analyzer\Statements\Expression\ $context->calling_method_id, $method_id !== $source_method_id ? new CodeLocation($source, $stmt->name) : null )) { - if ($config->use_phpdoc_method_without_magic_or_parent) { - $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); + $class_storage = $codebase->classlike_storage_provider->get($fq_class_name); - if (isset($class_storage->pseudo_methods[$method_name_lc])) { - $has_valid_method_call_type = true; - $existent_method_ids[] = $method_id; + if (($is_interface || $config->use_phpdoc_method_without_magic_or_parent) + && isset($class_storage->pseudo_methods[$method_name_lc]) + ) { + $has_valid_method_call_type = true; + $existent_method_ids[] = $method_id; - $pseudo_method_storage = $class_storage->pseudo_methods[$method_name_lc]; + $pseudo_method_storage = $class_storage->pseudo_methods[$method_name_lc]; - if (self::checkFunctionArguments( - $statements_analyzer, - $args, - $pseudo_method_storage->params, - $method_id, - $context - ) === false) { - return false; + if (self::checkFunctionArguments( + $statements_analyzer, + $args, + $pseudo_method_storage->params, + $method_id, + $context + ) === false) { + return false; + } + + $generic_params = []; + + if (self::checkFunctionLikeArgumentsMatch( + $statements_analyzer, + $args, + null, + $pseudo_method_storage->params, + $pseudo_method_storage, + null, + $generic_params, + new CodeLocation($source, $stmt->name), + $context + ) === false) { + return false; + } + + if ($pseudo_method_storage->return_type) { + $return_type_candidate = clone $pseudo_method_storage->return_type; + + if ($all_intersection_return_type) { + $return_type_candidate = Type::intersectUnionTypes( + $all_intersection_return_type, + $return_type_candidate + ); } - $generic_params = []; - - if (self::checkFunctionLikeArgumentsMatch( - $statements_analyzer, - $args, - null, - $pseudo_method_storage->params, - $pseudo_method_storage, - null, - $generic_params, - new CodeLocation($source, $stmt->name), - $context - ) === false) { - return false; + if (!$return_type) { + $return_type = $return_type_candidate; + } else { + $return_type = Type::combineUnionTypes($return_type_candidate, $return_type); } - if ($pseudo_method_storage->return_type) { - $return_type_candidate = clone $pseudo_method_storage->return_type; - - if ($all_intersection_return_type) { - $return_type_candidate = Type::intersectUnionTypes( - $all_intersection_return_type, - $return_type_candidate - ); - } - - if (!$return_type) { - $return_type = $return_type_candidate; - } else { - $return_type = Type::combineUnionTypes($return_type_candidate, $return_type); - } - - return; - } - - $return_type = Type::getMixed(); - return; } + + $return_type = Type::getMixed(); + + return; } if ($all_intersection_return_type && $all_intersection_existent_method_ids) { diff --git a/src/Psalm/Internal/Codebase/Methods.php b/src/Psalm/Internal/Codebase/Methods.php index 3c26d8f0d..08e15fd0d 100644 --- a/src/Psalm/Internal/Codebase/Methods.php +++ b/src/Psalm/Internal/Codebase/Methods.php @@ -528,20 +528,14 @@ class Methods */ public function getMethodReturnType($method_id, &$self_class, array $args = null) { - $checked_for_pseudo_method = false; + list($original_fq_class_name, $original_method_name) = explode('::', $method_id); - if ($this->config->use_phpdoc_method_without_magic_or_parent) { - list($original_fq_class_name, $original_method_name) = explode('::', $method_id); + $original_fq_class_name = $this->classlikes->getUnAliasedName($original_fq_class_name); - $original_fq_class_name = $this->classlikes->getUnAliasedName($original_fq_class_name); + $original_class_storage = $this->classlike_storage_provider->get($original_fq_class_name); - $original_class_storage = $this->classlike_storage_provider->get($original_fq_class_name); - - if (isset($original_class_storage->pseudo_methods[strtolower($original_method_name)])) { - return $original_class_storage->pseudo_methods[strtolower($original_method_name)]->return_type; - } - - $checked_for_pseudo_method = true; + if (isset($original_class_storage->pseudo_methods[strtolower($original_method_name)])) { + return $original_class_storage->pseudo_methods[strtolower($original_method_name)]->return_type; } $declaring_method_id = $this->getDeclaringMethodId($method_id); @@ -550,18 +544,6 @@ class Methods return null; } - if (!$checked_for_pseudo_method) { - list($original_fq_class_name, $original_method_name) = explode('::', $method_id); - - $original_fq_class_name = $this->classlikes->getUnAliasedName($original_fq_class_name); - - $original_class_storage = $this->classlike_storage_provider->get($original_fq_class_name); - - if (isset($original_class_storage->pseudo_methods[strtolower($original_method_name)])) { - return $original_class_storage->pseudo_methods[strtolower($original_method_name)]->return_type; - } - } - $appearing_method_id = $this->getAppearingMethodId($method_id); if (!$appearing_method_id) { diff --git a/tests/MagicMethodAnnotationTest.php b/tests/MagicMethodAnnotationTest.php index 2ab33e2f1..e29ecbc4b 100644 --- a/tests/MagicMethodAnnotationTest.php +++ b/tests/MagicMethodAnnotationTest.php @@ -396,6 +396,23 @@ class MagicMethodAnnotationTest extends TestCase '$a' => 'string', ], ], + 'alwaysAllowAnnotationOnInterface' => [ + 'sayHello();' + ], ]; }