KT-13521 Warning right part of "expression ?: null" is useless
#KT-13521 Fixed
This commit is contained in:
@@ -686,6 +686,8 @@ public interface Errors {
|
|||||||
|
|
||||||
DiagnosticFactory1<KtBinaryExpression, KotlinType> USELESS_ELVIS = DiagnosticFactory1.create(WARNING, PositioningStrategies.USELESS_ELVIS);
|
DiagnosticFactory1<KtBinaryExpression, KotlinType> USELESS_ELVIS = DiagnosticFactory1.create(WARNING, PositioningStrategies.USELESS_ELVIS);
|
||||||
DiagnosticFactory0<PsiElement> USELESS_ELVIS_ON_LAMBDA_EXPRESSION = DiagnosticFactory0.create(WARNING);
|
DiagnosticFactory0<PsiElement> USELESS_ELVIS_ON_LAMBDA_EXPRESSION = DiagnosticFactory0.create(WARNING);
|
||||||
|
DiagnosticFactory0<KtBinaryExpression> USELESS_ELVIS_RIGHT_IS_NULL =
|
||||||
|
DiagnosticFactory0.create(WARNING, PositioningStrategies.USELESS_ELVIS);
|
||||||
|
|
||||||
// Compile-time values
|
// Compile-time values
|
||||||
|
|
||||||
|
|||||||
+1
@@ -418,6 +418,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(DYNAMIC_UPPER_BOUND, "Dynamic type can not be used as an upper bound");
|
MAP.put(DYNAMIC_UPPER_BOUND, "Dynamic type can not be used as an upper bound");
|
||||||
MAP.put(USELESS_ELVIS, "Elvis operator (?:) always returns the left operand of non-nullable type {0}", RENDER_TYPE);
|
MAP.put(USELESS_ELVIS, "Elvis operator (?:) always returns the left operand of non-nullable type {0}", RENDER_TYPE);
|
||||||
MAP.put(USELESS_ELVIS_ON_LAMBDA_EXPRESSION, "Left operand of elvis operator (?:) is a lambda expression");
|
MAP.put(USELESS_ELVIS_ON_LAMBDA_EXPRESSION, "Left operand of elvis operator (?:) is a lambda expression");
|
||||||
|
MAP.put(USELESS_ELVIS_RIGHT_IS_NULL, "Right operand of elvis operator (?:) is useless if it is null");
|
||||||
MAP.put(CONFLICTING_UPPER_BOUNDS, "Upper bounds of {0} have empty intersection", NAME);
|
MAP.put(CONFLICTING_UPPER_BOUNDS, "Upper bounds of {0} have empty intersection", NAME);
|
||||||
|
|
||||||
MAP.put(UNSUPPORTED_TYPEALIAS, "Type aliases are unsupported (min Kotlin language level: 1.1)");
|
MAP.put(UNSUPPORTED_TYPEALIAS, "Type aliases are unsupported (min Kotlin language level: 1.1)");
|
||||||
|
|||||||
+3
@@ -1198,6 +1198,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
assert rightTypeInfo != null : "Right expression was not processed: " + expression;
|
assert rightTypeInfo != null : "Right expression was not processed: " + expression;
|
||||||
boolean loopBreakContinuePossible = leftTypeInfo.getJumpOutPossible() || rightTypeInfo.getJumpOutPossible();
|
boolean loopBreakContinuePossible = leftTypeInfo.getJumpOutPossible() || rightTypeInfo.getJumpOutPossible();
|
||||||
KotlinType rightType = rightTypeInfo.getType();
|
KotlinType rightType = rightTypeInfo.getType();
|
||||||
|
if (rightType != null && KtPsiUtil.isNullConstant(right)) {
|
||||||
|
context.trace.report(USELESS_ELVIS_RIGHT_IS_NULL.on(expression));
|
||||||
|
}
|
||||||
|
|
||||||
// Only left argument DFA is taken into account here: we cannot be sure that right argument is joined
|
// Only left argument DFA is taken into account here: we cannot be sure that right argument is joined
|
||||||
// (we merge it with right DFA if right argument contains no jump outside)
|
// (we merge it with right DFA if right argument contains no jump outside)
|
||||||
|
|||||||
Vendored
+20
@@ -0,0 +1,20 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
|
// FILE: J.java
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.*;
|
||||||
|
|
||||||
|
public class J {
|
||||||
|
@Nullable
|
||||||
|
public static J staticN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: k.kt
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
val a = J.staticN <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>
|
||||||
|
foo(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(a: Any?) {
|
||||||
|
}
|
||||||
Vendored
+14
@@ -0,0 +1,14 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun foo(/*0*/ a: kotlin.Any?): kotlin.Unit
|
||||||
|
public fun test(): kotlin.Unit
|
||||||
|
|
||||||
|
public open class J {
|
||||||
|
public constructor J()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
@org.jetbrains.annotations.Nullable() public final var staticN: J?
|
||||||
|
}
|
||||||
@@ -13855,6 +13855,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/uselessElvisInCall.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/uselessElvisInCall.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("uselessElvisRightIsNull.kt")
|
||||||
|
public void testUselessElvisRightIsNull() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/uselessElvisRightIsNull.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/platformTypes/rawTypes")
|
@TestMetadata("compiler/testData/diagnostics/tests/platformTypes/rawTypes")
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ class QuickFixRegistrar : QuickFixContributor {
|
|||||||
WRONG_GETTER_RETURN_TYPE.registerFactory(ChangeAccessorTypeFix)
|
WRONG_GETTER_RETURN_TYPE.registerFactory(ChangeAccessorTypeFix)
|
||||||
|
|
||||||
USELESS_ELVIS.registerFactory(RemoveUselessElvisFix)
|
USELESS_ELVIS.registerFactory(RemoveUselessElvisFix)
|
||||||
|
USELESS_ELVIS_RIGHT_IS_NULL.registerFactory(RemoveUselessElvisFix)
|
||||||
|
|
||||||
val removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true)
|
val removeRedundantModifierFactory = RemoveModifierFix.createRemoveModifierFactory(true)
|
||||||
REDUNDANT_MODIFIER.registerFactory(removeRedundantModifierFactory)
|
REDUNDANT_MODIFIER.registerFactory(removeRedundantModifierFactory)
|
||||||
|
|||||||
Reference in New Issue
Block a user