SenselessComparisonChecker extracted

This commit is contained in:
Andrey Breslav
2015-02-05 18:58:12 +03:00
parent f36d6ce5b2
commit d31b9be5fb
2 changed files with 76 additions and 36 deletions
@@ -20,6 +20,7 @@ import com.google.common.collect.Lists;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import kotlin.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
@@ -1135,7 +1136,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return JetTypeInfo.create(resolutionResult.isSuccess() ? components.builtIns.getBooleanType() : null, dataFlowInfo);
}
private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, ExpressionTypingContext context) {
private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, final ExpressionTypingContext context) {
JetExpression left = expression.getLeft();
if (left == null) return;
@@ -1150,45 +1151,25 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (TypeUtils.isIntersectionEmpty(leftType, rightType)) {
context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), leftType, rightType));
}
checkSenselessComparisonWithNull(expression, left, right, context);
SenselessComparisonChecker.checkSenselessComparisonWithNull(
expression, left, right, context,
new Function1<JetExpression, JetType>() {
@Override
public JetType invoke(JetExpression expression) {
return facade.getTypeInfo(expression, context).getType();
}
},
new Function1<DataFlowValue, Nullability>() {
@Override
public Nullability invoke(DataFlowValue value) {
return context.dataFlowInfo.getNullability(value);
}
}
);
}
}
}
private void checkSenselessComparisonWithNull(@NotNull JetBinaryExpression expression, @NotNull JetExpression left, @NotNull JetExpression right, @NotNull ExpressionTypingContext context) {
JetExpression expr;
if (JetPsiUtil.isNullConstant(left)) {
expr = right;
}
else if (JetPsiUtil.isNullConstant(right)) {
expr = left;
}
else return;
JetSimpleNameExpression operationSign = expression.getOperationReference();
JetType type = facade.getTypeInfo(expr, context).getType();
if (type == null || type.isError()) return;
DataFlowValue value = createDataFlowValue(expr, type, context.trace.getBindingContext());
Nullability nullability = context.dataFlowInfo.getNullability(value);
boolean expressionIsAlways;
boolean equality = operationSign.getReferencedNameElementType() == JetTokens.EQEQ || operationSign.getReferencedNameElementType() == JetTokens.EQEQEQ;
if (nullability == Nullability.NULL) {
expressionIsAlways = equality;
}
else if (nullability == Nullability.NOT_NULL) {
expressionIsAlways = !equality;
}
else if (nullability == Nullability.IMPOSSIBLE) {
expressionIsAlways = false;
}
else return;
context.trace.report(SENSELESS_COMPARISON.on(expression, expression, expressionIsAlways));
}
@NotNull
private JetTypeInfo visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) {
return assignmentIsNotAnExpressionError(expression, context);
@@ -0,0 +1,59 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.types.expressions
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.resolve.calls.smartcasts.Nullability
import org.jetbrains.kotlin.diagnostics.Errors
import kotlin.platform.platformStatic
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue
object SenselessComparisonChecker {
platformStatic fun checkSenselessComparisonWithNull(
expression: JetBinaryExpression,
left: JetExpression,
right: JetExpression,
context: ExpressionTypingContext,
getType: (JetExpression) -> JetType?,
getNullability: (DataFlowValue) -> Nullability
) {
val expr =
if (JetPsiUtil.isNullConstant(left)) right
else if (JetPsiUtil.isNullConstant(right)) left
else return
val type = getType(expr)
if (type == null || type.isError()) return
val operationSign = expression.getOperationReference()
val value = DataFlowValueFactory.createDataFlowValue(expr, type, context.trace.getBindingContext())
val nullability = getNullability(value)
val equality = operationSign.getReferencedNameElementType() == JetTokens.EQEQ || operationSign.getReferencedNameElementType() == JetTokens.EQEQEQ
val expressionIsAlways =
if (nullability == Nullability.NULL) equality
else if (nullability == Nullability.NOT_NULL) !equality
else if (nullability == Nullability.IMPOSSIBLE) false
else return
context.trace.report(Errors.SENSELESS_COMPARISON.on(expression, expression, expressionIsAlways))
}
}