1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Add ability to infer return type for method calls

This commit is contained in:
Matthew Brown 2018-05-20 12:47:18 -04:00
parent be522c623e
commit cdcba6152d
4 changed files with 33 additions and 4 deletions

View File

@ -573,7 +573,8 @@ class MethodCallChecker extends \Psalm\Checker\Statements\Expression\CallChecker
$return_type_candidate = $codebase->methods->getMethodReturnType(
$method_id,
$self_fq_class_name
$self_fq_class_name,
$stmt->args
);
if (isset($stmt->inferredType)) {

View File

@ -341,7 +341,8 @@ class StaticCallChecker extends \Psalm\Checker\Statements\Expression\CallChecker
$return_type_candidate = $codebase->methods->getMethodReturnType(
$method_id,
$self_fq_class_name
$self_fq_class_name,
$stmt->args
);
if ($return_type_candidate) {

View File

@ -1,6 +1,7 @@
<?php
namespace Psalm\Codebase;
use PhpParser;
use Psalm\Checker\MethodChecker;
use Psalm\CodeLocation;
use Psalm\Provider\ClassLikeStorageProvider;
@ -157,10 +158,11 @@ class Methods
/**
* @param string $method_id
* @param string $self_class
* @param array<int, PhpParser\Node\Arg>|null $args
*
* @return Type\Union|null
*/
public function getMethodReturnType($method_id, &$self_class)
public function getMethodReturnType($method_id, &$self_class, array $args = null)
{
if ($this->config->use_phpdoc_methods_without_call) {
list($original_fq_class_name, $original_method_name) = explode('::', $method_id);
@ -189,6 +191,22 @@ class Methods
$appearing_fq_class_storage = $this->classlike_storage_provider->get($appearing_fq_class_name);
if (!$appearing_fq_class_storage->user_defined && CallMap::inCallMap($appearing_method_id)) {
if ($appearing_method_id === 'Closure::fromcallable'
&& isset($args[0]->value->inferredType)
&& $args[0]->value->inferredType->isSingle()
) {
foreach ($args[0]->value->inferredType->getTypes() as $atomic_type) {
if ($atomic_type instanceof Type\Atomic\TCallable || $atomic_type instanceof Type\Atomic\Fn) {
$callable_type = clone $atomic_type;
return new Type\Union([new Type\Atomic\Fn(
'Closure',
$callable_type->params,
$callable_type->return_type
)]);
}
}
}
return CallMap::getReturnTypeFromCallMap($appearing_method_id);
}

View File

@ -531,7 +531,16 @@ class CallableTest extends TestCase
return $r();
}
}',
]
],
'mirrorCallableParams' => [
'<?php
namespace NS;
use Closure;
/** @param Closure(int):bool $c */
function acceptsIntToBool(Closure $c): void {}
acceptsIntToBool(Closure::fromCallable(function(int $n): bool { return $n > 0 }));',
],
];
}