1
0
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:
Matt Brown 2018-04-17 15:39:09 -04:00
parent 5a2f6ff0e0
commit 5b7d190640
3 changed files with 74 additions and 3 deletions

View File

@ -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],

View File

@ -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 [];
}

View File

@ -764,6 +764,13 @@ class TypeAlgebraTest extends TestCase
}',
'error_message' => 'ParadoxicalCondition',
],
'typeDoesntEqualType' => [
'<?php
$a = "hello";
$b = 5;
if ($a !== $b) {}',
'error_message' => 'RedundantCondition',
],
];
}
}