SenselessComparisonChecker extracted
This commit is contained in:
+17
-36
@@ -20,6 +20,7 @@ import com.google.common.collect.Lists;
|
|||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import com.intellij.psi.tree.TokenSet;
|
import com.intellij.psi.tree.TokenSet;
|
||||||
|
import kotlin.Function1;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
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);
|
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();
|
JetExpression left = expression.getLeft();
|
||||||
if (left == null) return;
|
if (left == null) return;
|
||||||
|
|
||||||
@@ -1150,45 +1151,25 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
if (TypeUtils.isIntersectionEmpty(leftType, rightType)) {
|
if (TypeUtils.isIntersectionEmpty(leftType, rightType)) {
|
||||||
context.trace.report(EQUALITY_NOT_APPLICABLE.on(expression, expression.getOperationReference(), 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
|
@NotNull
|
||||||
private JetTypeInfo visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) {
|
private JetTypeInfo visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) {
|
||||||
return assignmentIsNotAnExpressionError(expression, context);
|
return assignmentIsNotAnExpressionError(expression, context);
|
||||||
|
|||||||
+59
@@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user