forked from qt-creator/qt-creator
qmljs: add check for comparisons not depending on values
currently we mainly try to warn about primitive == null/undefined or primitive === non primitive. There are other that we could warn about null==null null==undefined, but I feel that they might be triggered too much by clean code. Change-Id: Id43d838d60a4e13f361be34e4bb38211777a081e Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
@@ -1275,6 +1275,30 @@ static bool shouldAvoidNonStrictEqualityCheck(const Value *lhs, const Value *rhs
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool equalIsAlwaysFalse(const Value *lhs, const Value *rhs)
|
||||
{
|
||||
if ((lhs->asNullValue() || lhs->asUndefinedValue())
|
||||
&& (rhs->asNumberValue() || rhs->asBooleanValue() || rhs->asStringValue()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool strictCompareConstant(const Value *lhs, const Value *rhs)
|
||||
{
|
||||
if (lhs->asUnknownValue() || rhs->asUnknownValue())
|
||||
return false;
|
||||
if (lhs->asBooleanValue() && !rhs->asBooleanValue())
|
||||
return true;
|
||||
if (lhs->asNumberValue() && !rhs->asNumberValue())
|
||||
return true;
|
||||
if (lhs->asStringValue() && !rhs->asStringValue())
|
||||
return true;
|
||||
if (lhs->asObjectValue() && (!rhs->asObjectValue() || !rhs->asNullValue() || !rhs->asUndefinedValue()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Check::visit(BinaryExpression *ast)
|
||||
{
|
||||
const QString source = _doc->source();
|
||||
@@ -1300,6 +1324,18 @@ bool Check::visit(BinaryExpression *ast)
|
||||
|| shouldAvoidNonStrictEqualityCheck(rhsValue, lhsValue)) {
|
||||
addMessage(MaybeWarnEqualityTypeCoercion, ast->operatorToken);
|
||||
}
|
||||
if (equalIsAlwaysFalse(lhsValue, rhsValue)
|
||||
|| equalIsAlwaysFalse(rhsValue, lhsValue))
|
||||
addMessage(WarnLogicalValueDoesNotDependOnValues, ast->operatorToken);
|
||||
}
|
||||
if (ast->op == QSOperator::StrictEqual || ast->op == QSOperator::StrictNotEqual) {
|
||||
Evaluate eval(&_scopeChain);
|
||||
const Value *lhsValue = eval(ast->left);
|
||||
const Value *rhsValue = eval(ast->right);
|
||||
if (strictCompareConstant(lhsValue, rhsValue)
|
||||
|| strictCompareConstant(rhsValue, lhsValue)) {
|
||||
addMessage(WarnLogicalValueDoesNotDependOnValues, ast->operatorToken);
|
||||
}
|
||||
}
|
||||
|
||||
// check odd + ++ combinations
|
||||
|
||||
@@ -247,6 +247,8 @@ StaticAnalysisMessages::StaticAnalysisMessages()
|
||||
tr("Hit maximum recursion limit when visiting AST."));
|
||||
newMsg(ErrTypeIsInstantiatedRecursively, Error,
|
||||
tr("Type cannot be instantiated recursively (%1)."), 1);
|
||||
newMsg(WarnLogicalValueDoesNotDependOnValues, Warning,
|
||||
tr("Logical value does not depend on actual values"));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
@@ -131,6 +131,7 @@ enum Type
|
||||
ErrShorterStringValueExpected = 322,
|
||||
ErrInvalidArrayValueLength = 323,
|
||||
ErrHitMaximumRecursion = 324,
|
||||
WarnLogicalValueDoesNotDependOnValues = 325,
|
||||
WarnDuplicateImport = 400
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user