mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
Fix #1692 - allow magic annotations on all interfaces without config flag
This commit is contained in:
parent
5e8acf0b0e
commit
c356c452ec
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -396,6 +396,23 @@ class MagicMethodAnnotationTest extends TestCase
|
||||
'$a' => 'string',
|
||||
],
|
||||
],
|
||||
'alwaysAllowAnnotationOnInterface' => [
|
||||
'<?php
|
||||
/**
|
||||
* @method string sayHello()
|
||||
*/
|
||||
interface A {}
|
||||
|
||||
function makeConcrete() : A {
|
||||
return new class implements A {
|
||||
function sayHello() : string {
|
||||
return "Hello";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
echo makeConcrete()->sayHello();'
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user