mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Add PossibyInvalidFunctionCall, emitted when function call may not be valid
This commit is contained in:
parent
5afe3b10fa
commit
7418d6685f
@ -172,6 +172,7 @@
|
|||||||
<xs:element name="PossiblyInvalidArrayAccess" type="IssueHandlerType" minOccurs="0" />
|
<xs:element name="PossiblyInvalidArrayAccess" type="IssueHandlerType" minOccurs="0" />
|
||||||
<xs:element name="PossiblyInvalidArrayAssignment" type="IssueHandlerType" minOccurs="0" />
|
<xs:element name="PossiblyInvalidArrayAssignment" type="IssueHandlerType" minOccurs="0" />
|
||||||
<xs:element name="PossiblyInvalidArrayOffset" type="IssueHandlerType" minOccurs="0" />
|
<xs:element name="PossiblyInvalidArrayOffset" type="IssueHandlerType" minOccurs="0" />
|
||||||
|
<xs:element name="PossiblyInvalidFunctionCall" type="IssueHandlerType" minOccurs="0" />
|
||||||
<xs:element name="PossiblyInvalidMethodCall" type="IssueHandlerType" minOccurs="0" />
|
<xs:element name="PossiblyInvalidMethodCall" type="IssueHandlerType" minOccurs="0" />
|
||||||
<xs:element name="PossiblyInvalidPropertyAssignment" type="IssueHandlerType" minOccurs="0" />
|
<xs:element name="PossiblyInvalidPropertyAssignment" type="IssueHandlerType" minOccurs="0" />
|
||||||
<xs:element name="PossiblyInvalidPropertyFetch" type="IssueHandlerType" minOccurs="0" />
|
<xs:element name="PossiblyInvalidPropertyFetch" type="IssueHandlerType" minOccurs="0" />
|
||||||
|
@ -881,10 +881,19 @@ $arr[0] = "hello";
|
|||||||
Emitted when it’s possible that the array offset is not applicable to the value you’re trying to access.
|
Emitted when it’s possible that the array offset is not applicable to the value you’re trying to access.
|
||||||
|
|
||||||
```php
|
```php
|
||||||
$arr = rand(0, 5) > 2 ? ["a" => 5] : "hello";
|
$arr = rand(0, 1) ? ["a" => 5] : "hello";
|
||||||
echo $arr[0];
|
echo $arr[0];
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### PossiblyInvalidFunctionCall
|
||||||
|
|
||||||
|
Emitted when trying to call a function on a value that may not be callable
|
||||||
|
|
||||||
|
```php
|
||||||
|
$a = rand(0, 1) ? 5 : function() : int { return 5; };
|
||||||
|
$b = $a();
|
||||||
|
```
|
||||||
|
|
||||||
### PossiblyInvalidMethodCall
|
### PossiblyInvalidMethodCall
|
||||||
|
|
||||||
Emitted when trying to call a method on a value that may not be an object
|
Emitted when trying to call a method on a value that may not be an object
|
||||||
|
@ -36,6 +36,7 @@ use Psalm\Issue\ParentNotFound;
|
|||||||
use Psalm\Issue\PossiblyFalseArgument;
|
use Psalm\Issue\PossiblyFalseArgument;
|
||||||
use Psalm\Issue\PossiblyFalseReference;
|
use Psalm\Issue\PossiblyFalseReference;
|
||||||
use Psalm\Issue\PossiblyInvalidArgument;
|
use Psalm\Issue\PossiblyInvalidArgument;
|
||||||
|
use Psalm\Issue\PossiblyInvalidFunctionCall;
|
||||||
use Psalm\Issue\PossiblyInvalidMethodCall;
|
use Psalm\Issue\PossiblyInvalidMethodCall;
|
||||||
use Psalm\Issue\PossiblyNullArgument;
|
use Psalm\Issue\PossiblyNullArgument;
|
||||||
use Psalm\Issue\PossiblyNullFunctionCall;
|
use Psalm\Issue\PossiblyNullFunctionCall;
|
||||||
@ -168,6 +169,9 @@ class CallChecker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$invalid_function_call_types = [];
|
||||||
|
$has_valid_function_call_type = false;
|
||||||
|
|
||||||
foreach ($stmt->name->inferredType->types as $var_type_part) {
|
foreach ($stmt->name->inferredType->types as $var_type_part) {
|
||||||
if ($var_type_part instanceof Type\Atomic\Fn) {
|
if ($var_type_part instanceof Type\Atomic\Fn) {
|
||||||
$function_params = $var_type_part->params;
|
$function_params = $var_type_part->params;
|
||||||
@ -182,11 +186,14 @@ class CallChecker
|
|||||||
}
|
}
|
||||||
|
|
||||||
$function_exists = true;
|
$function_exists = true;
|
||||||
|
$has_valid_function_call_type = true;
|
||||||
} elseif ($var_type_part instanceof TMixed) {
|
} elseif ($var_type_part instanceof TMixed) {
|
||||||
|
$has_valid_function_call_type = true;
|
||||||
// @todo maybe emit issue here
|
// @todo maybe emit issue here
|
||||||
} elseif (($var_type_part instanceof TNamedObject && $var_type_part->value === 'Closure') ||
|
} elseif (($var_type_part instanceof TNamedObject && $var_type_part->value === 'Closure') ||
|
||||||
$var_type_part instanceof TCallable
|
$var_type_part instanceof TCallable
|
||||||
) {
|
) {
|
||||||
|
$has_valid_function_call_type = true;
|
||||||
// this is fine
|
// this is fine
|
||||||
} elseif ($var_type_part instanceof TNull) {
|
} elseif ($var_type_part instanceof TNull) {
|
||||||
// handled above
|
// handled above
|
||||||
@ -206,9 +213,27 @@ class CallChecker
|
|||||||
$statements_checker
|
$statements_checker
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$invalid_function_call_types[] = (string)$var_type_part;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($invalid_function_call_types) {
|
||||||
|
$var_type_part = reset($invalid_function_call_types);
|
||||||
|
|
||||||
|
if ($has_valid_function_call_type) {
|
||||||
|
if (IssueBuffer::accepts(
|
||||||
|
new PossiblyInvalidFunctionCall(
|
||||||
|
'Cannot treat type ' . $var_type_part . ' as callable',
|
||||||
|
new CodeLocation($statements_checker->getSource(), $stmt)
|
||||||
|
),
|
||||||
|
$statements_checker->getSuppressedIssues()
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (IssueBuffer::accepts(
|
if (IssueBuffer::accepts(
|
||||||
new InvalidFunctionCall(
|
new InvalidFunctionCall(
|
||||||
'Cannot treat ' . $var_id . ' of type ' . $var_type_part . ' as function',
|
'Cannot treat type ' . $var_type_part . ' as callable',
|
||||||
new CodeLocation($statements_checker->getSource(), $stmt)
|
new CodeLocation($statements_checker->getSource(), $stmt)
|
||||||
),
|
),
|
||||||
$statements_checker->getSuppressedIssues()
|
$statements_checker->getSuppressedIssues()
|
||||||
|
6
src/Psalm/Issue/PossiblyInvalidFunctionCall.php
Normal file
6
src/Psalm/Issue/PossiblyInvalidFunctionCall.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
namespace Psalm\Issue;
|
||||||
|
|
||||||
|
class PossiblyInvalidFunctionCall extends CodeError
|
||||||
|
{
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user