mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Fix #97 - is_callable shouldn’t prevent evaluation of calls to existing functions
This commit is contained in:
parent
2d58531631
commit
9579460c59
@ -131,7 +131,7 @@ class CallChecker
|
||||
$code_location = new CodeLocation($statements_checker->getSource(), $stmt);
|
||||
$defined_constants = [];
|
||||
|
||||
if ($context->check_functions) {
|
||||
$function_exists = false;
|
||||
|
||||
if ($stmt->name instanceof PhpParser\Node\Expr) {
|
||||
if (ExpressionChecker::analyze($statements_checker, $stmt->name, $context) === false) {
|
||||
@ -153,6 +153,8 @@ class CallChecker
|
||||
$stmt->inferredType = $var_type_part->return_type;
|
||||
}
|
||||
}
|
||||
|
||||
$function_exists = true;
|
||||
} elseif (!$var_type_part instanceof TMixed &&
|
||||
(!$var_type_part instanceof TNamedObject || $var_type_part->value !== 'Closure') &&
|
||||
!$var_type_part instanceof TCallable &&
|
||||
@ -202,11 +204,8 @@ class CallChecker
|
||||
$method_id = FunctionChecker::getFQFunctionNameFromString($method_id, $statements_checker);
|
||||
}
|
||||
|
||||
if ($context->self) {
|
||||
//$method_id = $statements_checker->getFQCLN() . '::' . $method_id;
|
||||
}
|
||||
|
||||
if (!$in_call_map && !$is_stubbed) {
|
||||
if ($context->check_functions) {
|
||||
if (self::checkFunctionExists(
|
||||
$statements_checker,
|
||||
$method_id,
|
||||
@ -217,6 +216,15 @@ class CallChecker
|
||||
}
|
||||
}
|
||||
|
||||
$function_exists = FunctionChecker::functionExists(
|
||||
strtolower($method_id),
|
||||
$statements_checker->getFilePath()
|
||||
);
|
||||
} else {
|
||||
$function_exists = true;
|
||||
}
|
||||
|
||||
if ($function_exists) {
|
||||
if (!$in_call_map || $is_stubbed) {
|
||||
$function_storage = FunctionChecker::getStorage(
|
||||
strtolower($method_id),
|
||||
@ -249,7 +257,7 @@ class CallChecker
|
||||
// fall through
|
||||
}
|
||||
|
||||
if ($context->check_functions) {
|
||||
if ($function_exists) {
|
||||
$generic_params = null;
|
||||
|
||||
if ($stmt->name instanceof PhpParser\Node\Name && $method_id) {
|
||||
|
@ -481,4 +481,32 @@ class FunctionCallTest extends PHPUnit_Framework_TestCase
|
||||
$context = new Context();
|
||||
$file_checker->visitAndAnalyzeMethods($context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Psalm\Exception\CodeException
|
||||
* @expectedExceptionMessage InvalidScalarArgument
|
||||
* @return void
|
||||
*/
|
||||
public function testInvalidArgAfterCallable()
|
||||
{
|
||||
Config::getInstance()->setCustomErrorLevel('MixedAssignment', Config::REPORT_SUPPRESS);
|
||||
Config::getInstance()->setCustomErrorLevel('MixedArrayAccess', Config::REPORT_SUPPRESS);
|
||||
|
||||
$stmts = self::$parser->parse('<?php
|
||||
/**
|
||||
* @param callable $callback
|
||||
* @return void
|
||||
*/
|
||||
function route($callback) {
|
||||
if (!is_callable($callback)) { }
|
||||
takes_int("string");
|
||||
}
|
||||
|
||||
function takes_int(int $i) {}
|
||||
');
|
||||
|
||||
$file_checker = new FileChecker('somefile.php', $this->project_checker, $stmts);
|
||||
$context = new Context();
|
||||
$file_checker->visitAndAnalyzeMethods($context);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user