mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
Emit RedundantCondition when asserting two variables can never be equal
This commit is contained in:
parent
5a2f6ff0e0
commit
5b7d190640
@ -275,9 +275,9 @@ class TryChecker
|
||||
|
||||
if ($catch_actions[$i] !== [ScopeChecker::ACTION_END]) {
|
||||
foreach ($catch_context->vars_in_scope as $var_id => $type) {
|
||||
if ($catch->var !== $var_id &&
|
||||
$context->hasVariable($var_id) &&
|
||||
$context->vars_in_scope[$var_id]->getId() !== $type->getId()
|
||||
if ((!is_string($catch->var->name) || ('$' . $catch->var->name) !== $var_id)
|
||||
&& $context->hasVariable($var_id)
|
||||
&& $context->vars_in_scope[$var_id]->getId() !== $type->getId()
|
||||
) {
|
||||
$context->vars_in_scope[$var_id] = Type::combineUnionTypes(
|
||||
$context->vars_in_scope[$var_id],
|
||||
|
@ -7,6 +7,7 @@ use Psalm\Checker\Statements\ExpressionChecker;
|
||||
use Psalm\Checker\TypeChecker;
|
||||
use Psalm\CodeLocation;
|
||||
use Psalm\FileSource;
|
||||
use Psalm\Issue\RedundantCondition;
|
||||
use Psalm\Issue\TypeDoesNotContainNull;
|
||||
use Psalm\Issue\TypeDoesNotContainType;
|
||||
use Psalm\Issue\UnevaluatedCode;
|
||||
@ -442,6 +443,7 @@ class AssertionFinder
|
||||
$true_position = self::hasTrueVariable($conditional);
|
||||
$gettype_position = self::hasGetTypeCheck($conditional);
|
||||
$getclass_position = self::hasGetClassCheck($conditional);
|
||||
$typed_value_position = self::hasTypedValueComparison($conditional);
|
||||
|
||||
if ($null_position !== null) {
|
||||
if ($null_position === self::ASSIGNMENT_TO_RIGHT) {
|
||||
@ -621,6 +623,68 @@ class AssertionFinder
|
||||
return $if_types;
|
||||
}
|
||||
|
||||
if ($typed_value_position) {
|
||||
if ($typed_value_position === self::ASSIGNMENT_TO_RIGHT) {
|
||||
/** @var PhpParser\Node\Expr $conditional->right */
|
||||
$var_name = ExpressionChecker::getArrayVarId(
|
||||
$conditional->left,
|
||||
$this_class_name,
|
||||
$source
|
||||
);
|
||||
|
||||
$other_type = isset($conditional->left->inferredType) ? $conditional->left->inferredType : null;
|
||||
$var_type = isset($conditional->right->inferredType) ? $conditional->right->inferredType : null;
|
||||
} elseif ($typed_value_position === self::ASSIGNMENT_TO_LEFT) {
|
||||
/** @var PhpParser\Node\Expr $conditional->left */
|
||||
$var_name = ExpressionChecker::getArrayVarId(
|
||||
$conditional->right,
|
||||
$this_class_name,
|
||||
$source
|
||||
);
|
||||
|
||||
$var_type = isset($conditional->left->inferredType) ? $conditional->left->inferredType : null;
|
||||
$other_type = isset($conditional->right->inferredType) ? $conditional->right->inferredType : null;
|
||||
} else {
|
||||
throw new \UnexpectedValueException('$typed_value_position value');
|
||||
}
|
||||
|
||||
if ($var_type) {
|
||||
if ($var_name) {
|
||||
$if_types[$var_name] = '!^' . $var_type;
|
||||
}
|
||||
|
||||
if ($other_type
|
||||
&& $conditional instanceof PhpParser\Node\Expr\BinaryOp\NotIdentical
|
||||
&& $source instanceof StatementsSource
|
||||
&& $project_checker
|
||||
) {
|
||||
if (!TypeChecker::isContainedBy(
|
||||
$project_checker->codebase,
|
||||
$var_type,
|
||||
$other_type,
|
||||
true
|
||||
) && !TypeChecker::isContainedBy(
|
||||
$project_checker->codebase,
|
||||
$other_type,
|
||||
$var_type,
|
||||
true
|
||||
)) {
|
||||
if (IssueBuffer::accepts(
|
||||
new RedundantCondition(
|
||||
$var_type . ' can never contain ' . $other_type,
|
||||
new CodeLocation($source, $conditional)
|
||||
),
|
||||
$source->getSuppressedIssues()
|
||||
)) {
|
||||
// fall through
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $if_types;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
@ -764,6 +764,13 @@ class TypeAlgebraTest extends TestCase
|
||||
}',
|
||||
'error_message' => 'ParadoxicalCondition',
|
||||
],
|
||||
'typeDoesntEqualType' => [
|
||||
'<?php
|
||||
$a = "hello";
|
||||
$b = 5;
|
||||
if ($a !== $b) {}',
|
||||
'error_message' => 'RedundantCondition',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user