From d31b9be5fb22a3f82eadf83c5f254879ee24cd32 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 5 Feb 2015 18:58:12 +0300 Subject: [PATCH] SenselessComparisonChecker extracted --- .../BasicExpressionTypingVisitor.java | 53 ++++++----------- .../expressions/SenselessComparisonChecker.kt | 59 +++++++++++++++++++ 2 files changed, 76 insertions(+), 36 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/types/expressions/SenselessComparisonChecker.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index c367d5ac54e..e4282901ef8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -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() { + @Override + public JetType invoke(JetExpression expression) { + return facade.getTypeInfo(expression, context).getType(); + } + }, + new Function1() { + @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); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/SenselessComparisonChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/SenselessComparisonChecker.kt new file mode 100644 index 00000000000..24eaa0064e4 --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/SenselessComparisonChecker.kt @@ -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)) + } +} \ No newline at end of file