mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
Add PossiblyFalseReference and PossiblyFalseArgument issues
Useful for catching error cases
This commit is contained in:
parent
a34de5b79c
commit
c850ef644d
@ -991,6 +991,7 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
|
||||
$inferred_return_type,
|
||||
$declared_return_type,
|
||||
$ignore_nullable_issues,
|
||||
false,
|
||||
$has_scalar_match,
|
||||
$type_coerced
|
||||
)) {
|
||||
|
@ -32,6 +32,8 @@ use Psalm\Issue\NullArgument;
|
||||
use Psalm\Issue\NullFunctionCall;
|
||||
use Psalm\Issue\NullReference;
|
||||
use Psalm\Issue\ParentNotFound;
|
||||
use Psalm\Issue\PossiblyFalseArgument;
|
||||
use Psalm\Issue\PossiblyFalseReference;
|
||||
use Psalm\Issue\PossiblyInvalidArgument;
|
||||
use Psalm\Issue\PossiblyNullArgument;
|
||||
use Psalm\Issue\PossiblyNullFunctionCall;
|
||||
@ -740,6 +742,21 @@ class CallChecker
|
||||
}
|
||||
}
|
||||
|
||||
if ($class_type &&
|
||||
is_string($stmt->name) &&
|
||||
$class_type->isFalsable()
|
||||
) {
|
||||
if (IssueBuffer::accepts(
|
||||
new PossiblyFalseReference(
|
||||
'Cannot call method ' . $stmt->name . ' on possibly false variable ' . $var_id,
|
||||
new CodeLocation($statements_checker->getSource(), $stmt->var)
|
||||
),
|
||||
$statements_checker->getSuppressedIssues()
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$config = Config::getInstance();
|
||||
$project_checker = $statements_checker->getFileChecker()->project_checker;
|
||||
|
||||
@ -750,12 +767,12 @@ class CallChecker
|
||||
if (!$class_type_part instanceof TNamedObject) {
|
||||
switch (get_class($class_type_part)) {
|
||||
case 'Psalm\\Type\\Atomic\\TNull':
|
||||
case 'Psalm\\Type\\Atomic\\TFalse':
|
||||
// handled above
|
||||
break;
|
||||
|
||||
case 'Psalm\\Type\\Atomic\\TInt':
|
||||
case 'Psalm\\Type\\Atomic\\TBool':
|
||||
case 'Psalm\\Type\\Atomic\\TFalse':
|
||||
case 'Psalm\\Type\\Atomic\\TArray':
|
||||
case 'Psalm\\Type\\Atomic\\TString':
|
||||
case 'Psalm\\Type\\Atomic\\TNumericString':
|
||||
@ -2014,6 +2031,7 @@ class CallChecker
|
||||
$input_type,
|
||||
$closure_param_type,
|
||||
false,
|
||||
false,
|
||||
$scalar_type_match_found,
|
||||
$coerced_type
|
||||
);
|
||||
@ -2163,6 +2181,19 @@ class CallChecker
|
||||
}
|
||||
}
|
||||
|
||||
if ($input_type->isFalsable() && !$param_type->hasBool()) {
|
||||
if (IssueBuffer::accepts(
|
||||
new PossiblyFalseArgument(
|
||||
'Argument ' . ($argument_offset + 1) . $method_identifier . ' cannot be false, possibly ' .
|
||||
'false value provided',
|
||||
$code_location
|
||||
),
|
||||
$statements_checker->getSuppressedIssues()
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$param_type = TypeChecker::simplifyUnionType(
|
||||
$project_checker,
|
||||
$param_type
|
||||
@ -2173,6 +2204,7 @@ class CallChecker
|
||||
$input_type,
|
||||
$param_type,
|
||||
true,
|
||||
true,
|
||||
$scalar_type_match_found,
|
||||
$coerced_type,
|
||||
$to_string_cast
|
||||
|
@ -322,6 +322,7 @@ class ExpressionChecker
|
||||
$stmt->expr->inferredType,
|
||||
$container_type,
|
||||
true,
|
||||
false,
|
||||
$has_scalar_match
|
||||
)
|
||||
&& !$has_scalar_match
|
||||
@ -1544,6 +1545,7 @@ class ExpressionChecker
|
||||
$left_type,
|
||||
Type::getString(),
|
||||
true,
|
||||
false,
|
||||
$left_has_scalar_match
|
||||
);
|
||||
|
||||
@ -1552,6 +1554,7 @@ class ExpressionChecker
|
||||
$right_type,
|
||||
Type::getString(),
|
||||
true,
|
||||
false,
|
||||
$right_has_scalar_match
|
||||
);
|
||||
|
||||
|
@ -475,6 +475,7 @@ class TypeChecker
|
||||
* @param Type\Union $container_type
|
||||
* @param ProjectChecker $project_checker
|
||||
* @param bool $ignore_null
|
||||
* @param bool $ignore_false
|
||||
* @param bool &$has_scalar_match
|
||||
* @param bool &$type_coerced whether or not there was type coercion involved
|
||||
* @param bool &$to_string_cast
|
||||
@ -486,6 +487,7 @@ class TypeChecker
|
||||
Type\Union $input_type,
|
||||
Type\Union $container_type,
|
||||
$ignore_null = false,
|
||||
$ignore_false = false,
|
||||
&$has_scalar_match = null,
|
||||
&$type_coerced = null,
|
||||
&$to_string_cast = null
|
||||
@ -503,6 +505,10 @@ class TypeChecker
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($input_type_part instanceof TFalse && $ignore_false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$type_match_found = false;
|
||||
$scalar_type_match_found = false;
|
||||
$all_to_string_cast = true;
|
||||
@ -682,6 +688,7 @@ class TypeChecker
|
||||
$input_param,
|
||||
$container_param,
|
||||
false,
|
||||
false,
|
||||
$has_scalar_match,
|
||||
$type_coerced
|
||||
)
|
||||
|
6
src/Psalm/Issue/PossiblyFalseArgument.php
Normal file
6
src/Psalm/Issue/PossiblyFalseArgument.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace Psalm\Issue;
|
||||
|
||||
class PossiblyFalseArgument extends CodeError
|
||||
{
|
||||
}
|
6
src/Psalm/Issue/PossiblyFalseReference.php
Normal file
6
src/Psalm/Issue/PossiblyFalseReference.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
namespace Psalm\Issue;
|
||||
|
||||
class PossiblyFalseReference extends CodeError
|
||||
{
|
||||
}
|
@ -185,6 +185,22 @@ class Union
|
||||
return isset($this->types['null']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isFalsable()
|
||||
{
|
||||
return isset($this->types['false']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasBool()
|
||||
{
|
||||
return isset($this->types['bool']) || isset($this->types['false']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -398,6 +398,14 @@ class FunctionCallTest extends TestCase
|
||||
'MixedArrayAccess',
|
||||
],
|
||||
],
|
||||
'undefinedFunctionInArrayMap' => [
|
||||
'<?php
|
||||
array_map(
|
||||
"undefined_function",
|
||||
[1, 2, 3]
|
||||
);',
|
||||
'error_message' => 'UndefinedFunction',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -181,6 +181,7 @@ class ScopeTest extends TestCase
|
||||
'assertions' => [
|
||||
'$a' => 'string|null',
|
||||
],
|
||||
'error_levels' => ['PossiblyFalseArgument'],
|
||||
],
|
||||
'refineOredType' => [
|
||||
'<?php
|
||||
|
Loading…
Reference in New Issue
Block a user