mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
Add ability to detect invalid callable functions
This commit is contained in:
parent
396d214e3c
commit
17a900ab54
@ -1759,7 +1759,8 @@ class CallChecker
|
||||
$fleshed_out_type,
|
||||
$cased_method_id,
|
||||
$argument_offset,
|
||||
new CodeLocation($statements_checker->getSource(), $arg->value)
|
||||
new CodeLocation($statements_checker->getSource(), $arg->value),
|
||||
$arg->value
|
||||
) === false) {
|
||||
return false;
|
||||
}
|
||||
@ -2014,7 +2015,8 @@ class CallChecker
|
||||
Type\Union $param_type,
|
||||
$cased_method_id,
|
||||
$argument_offset,
|
||||
CodeLocation $code_location
|
||||
CodeLocation $code_location,
|
||||
PhpParser\Node\Expr $input_expr = null
|
||||
) {
|
||||
if ($param_type->isMixed()) {
|
||||
return null;
|
||||
@ -2151,6 +2153,34 @@ class CallChecker
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
} elseif ($input_expr instanceof PhpParser\Node\Scalar\String_) {
|
||||
foreach ($param_type->types as $param_type_part) {
|
||||
if ($param_type_part instanceof TCallable) {
|
||||
$function_name = $input_expr->value;
|
||||
|
||||
if (strpos($function_name, '::') !== false) {
|
||||
if (MethodChecker::checkMethodExists(
|
||||
$project_checker,
|
||||
$function_name,
|
||||
$code_location,
|
||||
$statements_checker->getSuppressedIssues()
|
||||
) === false
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (self::checkFunctionExists(
|
||||
$project_checker,
|
||||
$statements_checker,
|
||||
$function_name,
|
||||
$code_location
|
||||
) === false
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -398,7 +398,7 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
|
||||
$this->aliases = $this->file_aliases;
|
||||
} elseif ($node instanceof PhpParser\Node\Stmt\ClassLike) {
|
||||
if (!$this->fq_classlike_name) {
|
||||
throw new \LogicException('$this->fq_classlike_name should bot be null');
|
||||
throw new \LogicException('$this->fq_classlike_name should not be null');
|
||||
}
|
||||
|
||||
$fq_classlike_name = $this->fq_classlike_name;
|
||||
@ -473,7 +473,7 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
|
||||
}
|
||||
} elseif ($stmt instanceof PhpParser\Node\Stmt\ClassMethod) {
|
||||
if (!$this->fq_classlike_name) {
|
||||
throw new \LogicException('$this->fq_classlike_name should bot be null');
|
||||
throw new \LogicException('$this->fq_classlike_name should not be null');
|
||||
}
|
||||
|
||||
$fq_classlike_name = $this->fq_classlike_name;
|
||||
@ -978,7 +978,7 @@ class DependencyFinderVisitor extends PhpParser\NodeVisitorAbstract implements P
|
||||
Config $config
|
||||
) {
|
||||
if (!$this->fq_classlike_name) {
|
||||
throw new \LogicException('$this->fq_classlike_name should bot be null');
|
||||
throw new \LogicException('$this->fq_classlike_name should not be null');
|
||||
}
|
||||
|
||||
$comment = $stmt->getDocComment();
|
||||
|
@ -103,6 +103,24 @@ class ClosureTest extends TestCase
|
||||
$take_string = function(string $s) : string { return $s; };
|
||||
$take_string("string");',
|
||||
],
|
||||
'callableMethod' => [
|
||||
'<?php
|
||||
class A {
|
||||
public static function bar(string $a) : string {
|
||||
return $a . "b";
|
||||
}
|
||||
}
|
||||
|
||||
public function foo(callable $c) : void {}
|
||||
|
||||
foo("A::bar");',
|
||||
],
|
||||
'callableFunction' => [
|
||||
'<?php
|
||||
function foo(callable $c) : void {}
|
||||
|
||||
foo("trim");',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@ -151,6 +169,26 @@ class ClosureTest extends TestCase
|
||||
'error_message' => 'InvalidFunctionCall',
|
||||
'error_levels' => ['UndefinedClass'],
|
||||
],
|
||||
'undefinedCallableMethod' => [
|
||||
'<?php
|
||||
class A {
|
||||
public static function bar(string $a) : string {
|
||||
return $a . "b";
|
||||
}
|
||||
}
|
||||
|
||||
public function foo(callable $c) : void {}
|
||||
|
||||
foo("A::barr");',
|
||||
'error_message' => 'UndefinedMethod',
|
||||
],
|
||||
'undefinedCallableFunction' => [
|
||||
'<?php
|
||||
function foo(callable $c) : void {}
|
||||
|
||||
foo("trime");',
|
||||
'error_message' => 'UndefinedFunction',
|
||||
],
|
||||
'possiblyNullFunctionCall' => [
|
||||
'<?php
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user