FIR checker: warn useless elvis
This commit is contained in:
committed by
TeamCityServer
parent
b2005302dc
commit
24d792fb49
@@ -4,7 +4,7 @@ fun a(): Int {
|
|||||||
if (c == null ||
|
if (c == null ||
|
||||||
0 < c // FE 1.0: smart cast impossible, see KT-10240
|
0 < c // FE 1.0: smart cast impossible, see KT-10240
|
||||||
) c = 0
|
) c = 0
|
||||||
return c ?: 0
|
return c <!USELESS_ELVIS!>?: 0<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
var c: Int = 0
|
var c: Int = 0
|
||||||
|
|||||||
+1
@@ -52,6 +52,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
|||||||
CONST_MODIFIER,
|
CONST_MODIFIER,
|
||||||
ARRAY_ACCESS,
|
ARRAY_ACCESS,
|
||||||
SAFE_ACCESS,
|
SAFE_ACCESS,
|
||||||
|
USELESS_ELVIS,
|
||||||
NAME_OF_NAMED_ARGUMENT,
|
NAME_OF_NAMED_ARGUMENT,
|
||||||
VALUE_ARGUMENTS,
|
VALUE_ARGUMENTS,
|
||||||
SUPERTYPES_LIST,
|
SUPERTYPES_LIST,
|
||||||
|
|||||||
+4
@@ -638,6 +638,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
|||||||
}
|
}
|
||||||
val NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION by warning<KtExpression>(PositioningStrategy.OPERATOR)
|
val NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION by warning<KtExpression>(PositioningStrategy.OPERATOR)
|
||||||
val NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE by warning<KtExpression>(PositioningStrategy.OPERATOR)
|
val NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE by warning<KtExpression>(PositioningStrategy.OPERATOR)
|
||||||
|
val USELESS_ELVIS by warning<KtBinaryExpression>(PositioningStrategy.USELESS_ELVIS) {
|
||||||
|
parameter<ConeKotlinType>("receiverType")
|
||||||
|
}
|
||||||
|
val USELESS_ELVIS_RIGHT_IS_NULL by warning<KtBinaryExpression>(PositioningStrategy.USELESS_ELVIS)
|
||||||
}
|
}
|
||||||
|
|
||||||
val WHEN_EXPRESSIONS by object : DiagnosticGroup("When expressions") {
|
val WHEN_EXPRESSIONS by object : DiagnosticGroup("When expressions") {
|
||||||
|
|||||||
@@ -378,6 +378,8 @@ object FirErrors {
|
|||||||
val UNNECESSARY_NOT_NULL_ASSERTION by warning1<KtExpression, ConeKotlinType>(SourceElementPositioningStrategies.OPERATOR)
|
val UNNECESSARY_NOT_NULL_ASSERTION by warning1<KtExpression, ConeKotlinType>(SourceElementPositioningStrategies.OPERATOR)
|
||||||
val NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION by warning0<KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
val NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION by warning0<KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
||||||
val NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE by warning0<KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
val NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE by warning0<KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
||||||
|
val USELESS_ELVIS by warning1<KtBinaryExpression, ConeKotlinType>(SourceElementPositioningStrategies.USELESS_ELVIS)
|
||||||
|
val USELESS_ELVIS_RIGHT_IS_NULL by warning0<KtBinaryExpression>(SourceElementPositioningStrategies.USELESS_ELVIS)
|
||||||
|
|
||||||
// When expressions
|
// When expressions
|
||||||
val NO_ELSE_IN_WHEN by error1<KtWhenExpression, List<WhenMissingCase>>(SourceElementPositioningStrategies.WHEN_EXPRESSION)
|
val NO_ELSE_IN_WHEN by error1<KtWhenExpression, List<WhenMissingCase>>(SourceElementPositioningStrategies.WHEN_EXPRESSION)
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirElvisExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
|
import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType
|
||||||
|
import org.jetbrains.kotlin.fir.types.canBeNull
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.fir.types.isNullLiteral
|
||||||
|
|
||||||
|
object FirElvisExpressionChecker : FirBasicExpressionChecker() {
|
||||||
|
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (expression !is FirElvisExpression) return
|
||||||
|
// If the overall expression is not resolved/completed, the corresponding error will be reported separately.
|
||||||
|
// See [FirControlFlowStatementsResolveTransformer#transformElvisExpression],
|
||||||
|
// where an error type is recorded as the expression's return type.
|
||||||
|
if (expression.typeRef.coneType is ConeKotlinErrorType) return
|
||||||
|
|
||||||
|
val lhsType = expression.lhs.typeRef.coneType
|
||||||
|
if (lhsType is ConeKotlinErrorType) return
|
||||||
|
if (!lhsType.canBeNull) {
|
||||||
|
reporter.reportOn(expression.source, FirErrors.USELESS_ELVIS, lhsType, context)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expression.rhs.isNullLiteral) {
|
||||||
|
reporter.reportOn(expression.source, FirErrors.USELESS_ELVIS_RIGHT_IS_NULL, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -77,6 +77,10 @@ class ExpressionCheckersDiagnosticComponent(
|
|||||||
checkers.allBasicExpressionCheckers.check(checkNotNullCall, data, reporter)
|
checkers.allBasicExpressionCheckers.check(checkNotNullCall, data, reporter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitElvisExpression(elvisExpression: FirElvisExpression, data: CheckerContext) {
|
||||||
|
checkers.allBasicExpressionCheckers.check(elvisExpression, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: CheckerContext) {
|
override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: CheckerContext) {
|
||||||
checkers.basicExpressionCheckers.check(safeCallExpression, data, reporter)
|
checkers.basicExpressionCheckers.check(safeCallExpression, data, reporter)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -263,6 +263,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_FEATU
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UPPER_BOUND_VIOLATED
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_ELVIS
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_ELVIS_RIGHT_IS_NULL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_VARARG_ON_PARAMETER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_VARARG_ON_PARAMETER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_BE_CLONEABLE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_BE_CLONEABLE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION
|
||||||
@@ -836,6 +838,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
|||||||
map.put(NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE, "Non-null assertion (!!) is called on a callable reference expression")
|
map.put(NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE, "Non-null assertion (!!) is called on a callable reference expression")
|
||||||
map.put(UNNECESSARY_SAFE_CALL, "Unnecessary safe call on a non-null receiver of type {0}", RENDER_TYPE)
|
map.put(UNNECESSARY_SAFE_CALL, "Unnecessary safe call on a non-null receiver of type {0}", RENDER_TYPE)
|
||||||
map.put(UNEXPECTED_SAFE_CALL, "Safe-call is not allowed here")
|
map.put(UNEXPECTED_SAFE_CALL, "Safe-call is not allowed here")
|
||||||
|
map.put(USELESS_ELVIS, "Elvis operator (?:) always returns the left operand of non-nullable type {0}", RENDER_TYPE)
|
||||||
|
map.put(USELESS_ELVIS_RIGHT_IS_NULL, "Right operand of elvis operator (?:) is useless if it is null")
|
||||||
|
|
||||||
// When expressions
|
// When expressions
|
||||||
map.put(NO_ELSE_IN_WHEN, "''when'' expression must be exhaustive, add necessary {0}", WHEN_MISSING_CASES)
|
map.put(NO_ELSE_IN_WHEN, "''when'' expression must be exhaustive, add necessary {0}", WHEN_MISSING_CASES)
|
||||||
|
|||||||
+11
@@ -555,6 +555,17 @@ object LightTreePositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val USELESS_ELVIS = object : LightTreePositioningStrategy() {
|
||||||
|
override fun mark(
|
||||||
|
node: LighterASTNode,
|
||||||
|
startOffset: Int,
|
||||||
|
endOffset: Int,
|
||||||
|
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||||
|
): List<TextRange> {
|
||||||
|
return markRange(tree.operationReference(node) ?: node, tree.lastChild(node) ?: node, startOffset, endOffset, tree, node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val RETURN_WITH_LABEL = object : LightTreePositioningStrategy() {
|
val RETURN_WITH_LABEL = object : LightTreePositioningStrategy() {
|
||||||
override fun mark(
|
override fun mark(
|
||||||
node: LighterASTNode,
|
node: LighterASTNode,
|
||||||
|
|||||||
+5
@@ -178,6 +178,11 @@ object SourceElementPositioningStrategies {
|
|||||||
PositioningStrategies.SAFE_ACCESS
|
PositioningStrategies.SAFE_ACCESS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val USELESS_ELVIS = SourceElementPositioningStrategy(
|
||||||
|
LightTreePositioningStrategies.USELESS_ELVIS,
|
||||||
|
PositioningStrategies.USELESS_ELVIS
|
||||||
|
)
|
||||||
|
|
||||||
val RETURN_WITH_LABEL = SourceElementPositioningStrategy(
|
val RETURN_WITH_LABEL = SourceElementPositioningStrategy(
|
||||||
LightTreePositioningStrategies.RETURN_WITH_LABEL,
|
LightTreePositioningStrategies.RETURN_WITH_LABEL,
|
||||||
PositioningStrategies.RETURN_WITH_LABEL
|
PositioningStrategies.RETURN_WITH_LABEL
|
||||||
|
|||||||
+2
-1
@@ -17,6 +17,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
get() = setOf(
|
get() = setOf(
|
||||||
FirAnonymousFunctionChecker,
|
FirAnonymousFunctionChecker,
|
||||||
FirCheckNotNullCallChecker,
|
FirCheckNotNullCallChecker,
|
||||||
|
FirElvisExpressionChecker,
|
||||||
FirGetClassCallChecker,
|
FirGetClassCallChecker,
|
||||||
FirSafeCallExpressionChecker,
|
FirSafeCallExpressionChecker,
|
||||||
)
|
)
|
||||||
@@ -36,7 +37,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
FirSealedClassConstructorCallChecker,
|
FirSealedClassConstructorCallChecker,
|
||||||
FirUninitializedEnumChecker,
|
FirUninitializedEnumChecker,
|
||||||
FirFunInterfaceConstructorReferenceChecker,
|
FirFunInterfaceConstructorReferenceChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val functionCallCheckers: Set<FirFunctionCallChecker>
|
override val functionCallCheckers: Set<FirFunctionCallChecker>
|
||||||
get() = setOf(
|
get() = setOf(
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.render
|
import org.jetbrains.kotlin.fir.render
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
@@ -43,7 +42,12 @@ val FirTypeRef.isArrayType: Boolean
|
|||||||
get() =
|
get() =
|
||||||
isBuiltinType(StandardClassIds.Array, false) ||
|
isBuiltinType(StandardClassIds.Array, false) ||
|
||||||
StandardClassIds.primitiveArrayTypeByElementType.values.any { isBuiltinType(it, false) }
|
StandardClassIds.primitiveArrayTypeByElementType.values.any { isBuiltinType(it, false) }
|
||||||
val FirExpression.isNullLiteral: Boolean get() = this is FirConstExpression<*> && this.value == null && this.source != null
|
|
||||||
|
val FirExpression.isNullLiteral: Boolean
|
||||||
|
get() = this is FirConstExpression<*> &&
|
||||||
|
this.kind == ConstantValueKind.Null &&
|
||||||
|
this.value == null &&
|
||||||
|
this.source != null
|
||||||
|
|
||||||
private val FirTypeRef.classLikeTypeOrNull: ConeClassLikeType?
|
private val FirTypeRef.classLikeTypeOrNull: ConeClassLikeType?
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
|
|||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER, -UNUSED_VARIABLE
|
|
||||||
|
|
||||||
fun baz(i: Int) = i
|
|
||||||
fun <T> bar(x: T): T = TODO()
|
|
||||||
|
|
||||||
fun nullableFun(): ((Int) -> Int)? = null
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
val x1: (Int) -> Int = bar(if (true) ::baz else ::baz)
|
|
||||||
val x2: (Int) -> Int = bar(nullableFun() ?: ::baz)
|
|
||||||
val x3: (Int) -> Int = bar(::baz ?: ::baz)
|
|
||||||
|
|
||||||
val i = 0
|
|
||||||
val x4: (Int) -> Int = bar(when (i) {
|
|
||||||
10 -> ::baz
|
|
||||||
20 -> ::baz
|
|
||||||
else -> ::baz
|
|
||||||
})
|
|
||||||
|
|
||||||
val x5: (Int) -> Int = bar(::baz<!NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE!>!!<!>)
|
|
||||||
|
|
||||||
(if (true) ::baz else ::baz)(1)
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER, -UNUSED_VARIABLE
|
// !DIAGNOSTICS: -UNUSED_PARAMETER, -UNUSED_VARIABLE
|
||||||
|
|
||||||
fun baz(i: Int) = i
|
fun baz(i: Int) = i
|
||||||
|
|||||||
+2
-2
@@ -24,8 +24,8 @@ fun main() {
|
|||||||
val x17 = <!UNRESOLVED_REFERENCE!>logger<!>::info<!NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE!>!!<!>?::<!UNRESOLVED_REFERENCE!>print<!>?::<!UNRESOLVED_REFERENCE!>print<!>
|
val x17 = <!UNRESOLVED_REFERENCE!>logger<!>::info<!NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE!>!!<!>?::<!UNRESOLVED_REFERENCE!>print<!>?::<!UNRESOLVED_REFERENCE!>print<!>
|
||||||
|
|
||||||
// It must be OK
|
// It must be OK
|
||||||
val x18 = String?::hashCode ?: ::foo
|
val x18 = String?::hashCode <!USELESS_ELVIS!>?: ::foo<!>
|
||||||
val x19 = String::hashCode ?: ::foo
|
val x19 = String::hashCode <!USELESS_ELVIS!>?: ::foo<!>
|
||||||
val x20 = String?::hashCode::hashCode
|
val x20 = String?::hashCode::hashCode
|
||||||
val x21 = kotlin.String?::hashCode::hashCode
|
val x21 = kotlin.String?::hashCode::hashCode
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ fun testBinary2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testElvis1() {
|
fun testElvis1() {
|
||||||
todo() ?: ""
|
todo() <!USELESS_ELVIS!>?: ""<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testElvis2(s: String?) {
|
fun testElvis2(s: String?) {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -50,6 +50,6 @@ fun test(arr: Array<Int>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
break ?: null
|
break <!USELESS_ELVIS!>?: null<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -2,20 +2,20 @@
|
|||||||
// See KT-8277
|
// See KT-8277
|
||||||
// NI_EXPECTED_FILE
|
// NI_EXPECTED_FILE
|
||||||
|
|
||||||
val v = { true } ?: ( { true } ?:null!! )
|
val v = { true } <!USELESS_ELVIS!>?: ( { true } <!USELESS_ELVIS!>?:null!!<!> )<!>
|
||||||
|
|
||||||
val w = if (true) {
|
val w = if (true) {
|
||||||
{ true }
|
{ true }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
{ true } ?: null!!
|
{ true } <!USELESS_ELVIS!>?: null!!<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
val ww = if (true) {
|
val ww = if (true) {
|
||||||
{ true } ?: null!!
|
{ true } <!USELESS_ELVIS!>?: null!!<!>
|
||||||
}
|
}
|
||||||
else if (true) {
|
else if (true) {
|
||||||
{ true } ?: null!!
|
{ true } <!USELESS_ELVIS!>?: null!!<!>
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
null!!
|
null!!
|
||||||
@@ -29,11 +29,11 @@ val b = null ?: ( l() ?: false)
|
|||||||
|
|
||||||
val bb = null ?: ( l() ?: null!!)
|
val bb = null ?: ( l() ?: null!!)
|
||||||
|
|
||||||
val bbb = null ?: ( l() ?: null)
|
val bbb = null ?: ( l() <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>)
|
||||||
|
|
||||||
val bbbb = ( l() ?: null) ?: ( l() ?: null)
|
val bbbb = ( l() <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>) ?: ( l() <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>)
|
||||||
|
|
||||||
fun f(x : Long?): Long {
|
fun f(x : Long?): Long {
|
||||||
var a = x ?: (fun() {} ?: fun() {})
|
var a = x ?: (fun() {} <!USELESS_ELVIS!>?: fun() {}<!>)
|
||||||
return <!RETURN_TYPE_MISMATCH!>a<!>
|
return <!RETURN_TYPE_MISMATCH!>a<!>
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -7,6 +7,6 @@ fun foo(): String {
|
|||||||
}
|
}
|
||||||
fun bar(): String {
|
fun bar(): String {
|
||||||
val x = fn() ?: return ""
|
val x = fn() ?: return ""
|
||||||
val y = x<!UNNECESSARY_SAFE_CALL!>?.<!>let { throw Exception() } ?: "unreachable"
|
val y = x<!UNNECESSARY_SAFE_CALL!>?.<!>let { throw Exception() } <!USELESS_ELVIS!>?: "unreachable"<!>
|
||||||
return y
|
return y
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -8,9 +8,9 @@ fun test() {
|
|||||||
use({ }<!NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION!>!!<!>);
|
use({ }<!NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION!>!!<!>);
|
||||||
|
|
||||||
// KT-KT-9070
|
// KT-KT-9070
|
||||||
{ } ?: 1
|
{ } <!USELESS_ELVIS!>?: 1<!>
|
||||||
use({ 2 } ?: 1);
|
use({ 2 } <!USELESS_ELVIS!>?: 1<!>);
|
||||||
|
|
||||||
1 ?: { }
|
1 <!USELESS_ELVIS!>?: { }<!>
|
||||||
use(1 ?: { })
|
use(1 <!USELESS_ELVIS!>?: { }<!>)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ fun foo() {
|
|||||||
val x: Int? = null
|
val x: Int? = null
|
||||||
|
|
||||||
bar(x ?: 0)
|
bar(x ?: 0)
|
||||||
if (x != null) bar(x ?: x)
|
if (x != null) bar(x <!USELESS_ELVIS!>?: x<!>)
|
||||||
bar(<!ARGUMENT_TYPE_MISMATCH!>x<!>)
|
bar(<!ARGUMENT_TYPE_MISMATCH!>x<!>)
|
||||||
}
|
}
|
||||||
Vendored
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
fun <D> makeDefinitelyNotNull(arg: D?): D = TODO()
|
fun <D> makeDefinitelyNotNull(arg: D?): D = TODO()
|
||||||
|
|
||||||
fun <N : Number?> test(arg: N) {
|
fun <N : Number?> test(arg: N) {
|
||||||
makeDefinitelyNotNull(arg) ?: 1
|
makeDefinitelyNotNull(arg) <!USELESS_ELVIS!>?: 1<!>
|
||||||
|
|
||||||
makeDefinitelyNotNull(arg)<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
makeDefinitelyNotNull(arg)<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ fun <T: Any?> test1(t: Any?): Any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun <T: Any> test2(t: Any?): Any {
|
fun <T: Any> test2(t: Any?): Any {
|
||||||
return t as T ?: ""
|
return t as T <!USELESS_ELVIS!>?: ""<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T: Any?> test3(t: Any?): Any {
|
fun <T: Any?> test3(t: Any?): Any {
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
return t ?: ""
|
return t <!USELESS_ELVIS!>?: ""<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
@@ -28,11 +28,11 @@ fun test() {
|
|||||||
val x: String? = null
|
val x: String? = null
|
||||||
takeNotNull(dependOn(x) ?: "")
|
takeNotNull(dependOn(x) ?: "")
|
||||||
takeNotNull(dependOn(dependOn(x)) ?: "")
|
takeNotNull(dependOn(dependOn(x)) ?: "")
|
||||||
takeNotNull(dependOn(dependOn(x as String)) ?: "")
|
takeNotNull(dependOn(dependOn(x as String)) <!USELESS_ELVIS!>?: ""<!>)
|
||||||
|
|
||||||
if (x != null) {
|
if (x != null) {
|
||||||
takeNotNull(dependOn(x) ?: "")
|
takeNotNull(dependOn(x) <!USELESS_ELVIS!>?: ""<!>)
|
||||||
takeNotNull(dependOn(dependOn(x)) ?: "")
|
takeNotNull(dependOn(dependOn(x)) <!USELESS_ELVIS!>?: ""<!>)
|
||||||
takeNotNull(dependOn(dependOn(x) as? String) ?: "")
|
takeNotNull(dependOn(dependOn(x) as? String) ?: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-7
@@ -36,28 +36,28 @@ fun test() {
|
|||||||
// platform type with no annotation
|
// platform type with no annotation
|
||||||
val platformJ = J.staticJ
|
val platformJ = J.staticJ
|
||||||
|
|
||||||
val v0 = platformNN ?: J()
|
val v0 = platformNN <!USELESS_ELVIS!>?: J()<!>
|
||||||
platformNN ?: J()
|
platformNN <!USELESS_ELVIS!>?: J()<!>
|
||||||
platformN ?: J()
|
platformN ?: J()
|
||||||
platformJ ?: J()
|
platformJ ?: J()
|
||||||
|
|
||||||
if (platformNN != null) {
|
if (platformNN != null) {
|
||||||
platformNN ?: J()
|
platformNN <!USELESS_ELVIS!>?: J()<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
if (platformN != null) {
|
if (platformN != null) {
|
||||||
platformN ?: J()
|
platformN <!USELESS_ELVIS!>?: J()<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
if (platformJ != null) {
|
if (platformJ != null) {
|
||||||
platformJ ?: J()
|
platformJ <!USELESS_ELVIS!>?: J()<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
takeNotNull(J.staticNN ?: J())
|
takeNotNull(J.staticNN <!USELESS_ELVIS!>?: J()<!>)
|
||||||
takeNotNull(J.staticN ?: J())
|
takeNotNull(J.staticN ?: J())
|
||||||
takeNotNull(J.staticJ ?: J())
|
takeNotNull(J.staticJ ?: J())
|
||||||
takeNotNull(J.getAny() ?: J())
|
takeNotNull(J.getAny() ?: J())
|
||||||
takeNotNull(J.getNNAny() ?: J())
|
takeNotNull(J.getNNAny() <!USELESS_ELVIS!>?: J()<!>)
|
||||||
takeNotNull(J.getNAny() ?: J())
|
takeNotNull(J.getNAny() ?: J())
|
||||||
|
|
||||||
val x = <!UNRESOLVED_REFERENCE!>unresolved<!> ?: null
|
val x = <!UNRESOLVED_REFERENCE!>unresolved<!> ?: null
|
||||||
|
|||||||
Vendored
-28
@@ -1,28 +0,0 @@
|
|||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
|
||||||
|
|
||||||
// FILE: J.java
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.*;
|
|
||||||
|
|
||||||
public class J {
|
|
||||||
@NotNull
|
|
||||||
public static J staticNN;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: k.kt
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
// @NotNull platform type
|
|
||||||
val platformNN = J.staticNN
|
|
||||||
|
|
||||||
foo(platformNN ?: "")
|
|
||||||
|
|
||||||
val bar = Bar()
|
|
||||||
bar(platformNN ?: "")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun foo(a: Any) {}
|
|
||||||
|
|
||||||
class Bar {
|
|
||||||
operator fun invoke(a: Any) {}
|
|
||||||
}
|
|
||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
|
||||||
// FILE: J.java
|
// FILE: J.java
|
||||||
|
|||||||
compiler/testData/diagnostics/tests/platformTypes/nullabilityWarnings/uselessElvisRightIsNull.fir.kt
Vendored
+4
-4
@@ -33,15 +33,15 @@ public interface JJJJ<R> {
|
|||||||
// FILE: k.kt
|
// FILE: k.kt
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val a = J.staticN ?: null
|
val a = J.staticN <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>
|
||||||
foo(a)
|
foo(a)
|
||||||
val b = JJ.staticNN ?: null
|
val b = JJ.staticNN <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>
|
||||||
foo(b)
|
foo(b)
|
||||||
val c = JJJ.staticNNN ?: null
|
val c = JJJ.staticNNN <!USELESS_ELVIS!>?: null<!>
|
||||||
foo(c)
|
foo(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo(a: Any?) {
|
fun foo(a: Any?) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <R> test2(j: JJJJ<R>) = j.get() ?: null
|
fun <R> test2(j: JJJJ<R>) = j.get() <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>
|
||||||
|
|||||||
+1
-1
@@ -6,5 +6,5 @@ operator fun String.invoke(i: Int) {}
|
|||||||
fun foo(s: String?) {
|
fun foo(s: String?) {
|
||||||
<!UNSAFE_IMPLICIT_INVOKE_CALL!>s<!>(1)
|
<!UNSAFE_IMPLICIT_INVOKE_CALL!>s<!>(1)
|
||||||
|
|
||||||
<!UNSAFE_IMPLICIT_INVOKE_CALL!>(s ?: null)<!>(1)
|
<!UNSAFE_IMPLICIT_INVOKE_CALL!>(s <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>)<!>(1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ fun baz(s: String?, r: String?): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun withNull(s: String?): String {
|
fun withNull(s: String?): String {
|
||||||
val t = s ?: null
|
val t = s <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>
|
||||||
// Error: nullable
|
// Error: nullable
|
||||||
return <!RETURN_TYPE_MISMATCH!>t<!>
|
return <!RETURN_TYPE_MISMATCH!>t<!>
|
||||||
}
|
}
|
||||||
+1
-1
@@ -62,5 +62,5 @@ fun k() {
|
|||||||
fun invokeTest(goodArgs: Array<String>) {
|
fun invokeTest(goodArgs: Array<String>) {
|
||||||
J.staticFun(*goodArgs)
|
J.staticFun(*goodArgs)
|
||||||
J.staticFun(*args)
|
J.staticFun(*args)
|
||||||
J.staticFun(*args ?: null)
|
J.staticFun(*args <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -27,6 +27,6 @@ fun case3() {
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 4
|
// TESTCASE NUMBER: 4
|
||||||
fun case4() {
|
fun case4() {
|
||||||
val x = null ?: null
|
val x = null <!USELESS_ELVIS_RIGHT_IS_NULL!>?: null<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing?")!>x<!>
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -122,7 +122,7 @@ fun case_10(value_1: Int, value_2: String?, value_3: String?) {
|
|||||||
when {
|
when {
|
||||||
value_1 == 1 -> value_2 ?: true
|
value_1 == 1 -> value_2 ?: true
|
||||||
value_1 == 2 -> value_2 ?: value_3 ?: true
|
value_1 == 2 -> value_2 ?: value_3 ?: true
|
||||||
value_1 == 3 -> value_2!! ?: true
|
value_1 == 3 -> value_2!! <!USELESS_ELVIS!>?: true<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -125,7 +125,7 @@ fun case_10(value_1: Int, value_2: String?, value_3: String?) {
|
|||||||
when (value_1) {
|
when (value_1) {
|
||||||
1 -> value_2 ?: true
|
1 -> value_2 ?: true
|
||||||
2 -> value_2 ?: value_3 ?: true
|
2 -> value_2 ?: value_3 ?: true
|
||||||
3 -> value_2!! ?: true
|
3 -> value_2!! <!USELESS_ELVIS!>?: true<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -87,7 +87,7 @@ fun case_8(value_1: Int, value_2: Int?, value_3: Int?) {
|
|||||||
when (value_1) {
|
when (value_1) {
|
||||||
value_2 ?: 0 -> {}
|
value_2 ?: 0 -> {}
|
||||||
value_2 ?: value_3 ?: 0 -> {}
|
value_2 ?: value_3 ?: 0 -> {}
|
||||||
value_2!! ?: 0 -> {}
|
value_2!! <!USELESS_ELVIS!>?: 0<!> -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -66,7 +66,7 @@ fun case_7(value_1: Any, value_2: String, value_3: String) {
|
|||||||
// TESTCASE NUMBER: 8
|
// TESTCASE NUMBER: 8
|
||||||
fun case_8(value_1: Int, value_2: Int?, value_3: Int?) {
|
fun case_8(value_1: Int, value_2: Int?, value_3: Int?) {
|
||||||
when (value_1) {
|
when (value_1) {
|
||||||
value_2 ?: 0, value_2 ?: value_3 ?: 0, value_2!! ?: 0 -> {}
|
value_2 ?: 0, value_2 ?: value_3 ?: 0, value_2!! <!USELESS_ELVIS!>?: 0<!> -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 1
|
// TESTCASE NUMBER: 1
|
||||||
fun case_1(x: Int?) {
|
fun case_1(x: Int?) {
|
||||||
if ((x is Int) ?: (x is Int)) {
|
if ((x is Int) <!USELESS_ELVIS!>?: (x is Int)<!>) {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x<!><!UNSAFE_CALL!>.<!>inv()
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x<!><!UNSAFE_CALL!>.<!>inv()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 1
|
// TESTCASE NUMBER: 1
|
||||||
fun case_1(x: Int?) {
|
fun case_1(x: Int?) {
|
||||||
if ((x is Int) ?: (x is Int)) {
|
if ((x is Int) <!USELESS_ELVIS!>?: (x is Int)<!>) {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x<!><!UNSAFE_CALL!>.<!>inv()
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x<!><!UNSAFE_CALL!>.<!>inv()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
fun <T: Any, K: Any> case_1(x: T?, y: K?) {
|
fun <T: Any, K: Any> case_1(x: T?, y: K?) {
|
||||||
x as T
|
x as T
|
||||||
y as K
|
y as K
|
||||||
val z = <!DEBUG_INFO_EXPRESSION_TYPE("T? & T?!!")!>x<!> ?: <!DEBUG_INFO_EXPRESSION_TYPE("K? & K?!!")!>y<!>
|
val z = <!DEBUG_INFO_EXPRESSION_TYPE("T? & T?!!")!>x<!> <!USELESS_ELVIS!>?: <!DEBUG_INFO_EXPRESSION_TYPE("K? & K?!!")!>y<!><!>
|
||||||
|
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("T? & T?!!")!>x<!>.equals(10)
|
<!DEBUG_INFO_EXPRESSION_TYPE("T? & T?!!")!>x<!>.equals(10)
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>z<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>z<!>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ fun case_2(x: Any?) {
|
|||||||
*/
|
*/
|
||||||
fun case_3(x: Any?) {
|
fun case_3(x: Any?) {
|
||||||
while (true) {
|
while (true) {
|
||||||
x ?: return ?: <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
|
x ?: return <!USELESS_ELVIS!>?: <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!><!>
|
||||||
}
|
}
|
||||||
|
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ fun case_10(x: Any?, z: Any, b: Boolean?) {
|
|||||||
// TESTCASE NUMBER: 11
|
// TESTCASE NUMBER: 11
|
||||||
fun case_11(x: Any?, z: Any, b: Boolean?) {
|
fun case_11(x: Any?, z: Any, b: Boolean?) {
|
||||||
while (true) {
|
while (true) {
|
||||||
var y = x ?: if (b == true) continue<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!> else if (!(b != false)) return else break ?: break::class
|
var y = x ?: if (b == true) continue<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!> else if (!(b != false)) return else break <!USELESS_ELVIS!>?: break::class<!>
|
||||||
z !== y && if (b == true) return else if (b === false) null!!else throw Exception()
|
z !== y && if (b == true) return else if (b === false) null!!else throw Exception()
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Any")!>x<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>y<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>y<!>
|
||||||
@@ -148,7 +148,7 @@ fun case_11(x: Any?, z: Any, b: Boolean?) {
|
|||||||
// TESTCASE NUMBER: 12
|
// TESTCASE NUMBER: 12
|
||||||
fun case_12(x: Any?, z: Any, b: Boolean?) {
|
fun case_12(x: Any?, z: Any, b: Boolean?) {
|
||||||
while (true) {
|
while (true) {
|
||||||
var y = select(x) ?: if (b == true) continue<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!> else if (!(b != false)) return else break ?: break::class
|
var y = select(x) ?: if (b == true) continue<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!> else if (!(b != false)) return else break <!USELESS_ELVIS!>?: break::class<!>
|
||||||
select(z) !== y && if (b == true) return else if (b === false) null!!else throw Exception()
|
select(z) !== y && if (b == true) return else if (b === false) null!!else throw Exception()
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>y<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any")!>y<!>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ fun case_2(a: Any?) {
|
|||||||
*/
|
*/
|
||||||
fun case_3(x: Int?) {
|
fun case_3(x: Int?) {
|
||||||
while (true) {
|
while (true) {
|
||||||
x ?: return ?: <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>x<!>
|
x ?: return <!USELESS_ELVIS!>?: <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>x<!><!>
|
||||||
}
|
}
|
||||||
|
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int?")!>x<!>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ fun case_2(): Int {
|
|||||||
var c: Int? = null
|
var c: Int? = null
|
||||||
if (c == null || 0 < c) c = 0
|
if (c == null || 0 < c) c = 0
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>c<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Int? & kotlin.Int")!>c<!>
|
||||||
return c ?: 0
|
return c <!USELESS_ELVIS!>?: 0<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
var c: Int = 0
|
var c: Int = 0
|
||||||
|
|||||||
+13
@@ -1798,6 +1798,19 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.USELESS_ELVIS) { firDiagnostic ->
|
||||||
|
UselessElvisImpl(
|
||||||
|
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.USELESS_ELVIS_RIGHT_IS_NULL) { firDiagnostic ->
|
||||||
|
UselessElvisRightIsNullImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.NO_ELSE_IN_WHEN) { firDiagnostic ->
|
add(FirErrors.NO_ELSE_IN_WHEN) { firDiagnostic ->
|
||||||
NoElseInWhenImpl(
|
NoElseInWhenImpl(
|
||||||
firDiagnostic.a.map { whenMissingCase ->
|
firDiagnostic.a.map { whenMissingCase ->
|
||||||
|
|||||||
+9
@@ -1265,6 +1265,15 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = NotNullAssertionOnCallableReference::class
|
override val diagnosticClass get() = NotNullAssertionOnCallableReference::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class UselessElvis : KtFirDiagnostic<KtBinaryExpression>() {
|
||||||
|
override val diagnosticClass get() = UselessElvis::class
|
||||||
|
abstract val receiverType: KtType
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class UselessElvisRightIsNull : KtFirDiagnostic<KtBinaryExpression>() {
|
||||||
|
override val diagnosticClass get() = UselessElvisRightIsNull::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class NoElseInWhen : KtFirDiagnostic<KtWhenExpression>() {
|
abstract class NoElseInWhen : KtFirDiagnostic<KtWhenExpression>() {
|
||||||
override val diagnosticClass get() = NoElseInWhen::class
|
override val diagnosticClass get() = NoElseInWhen::class
|
||||||
abstract val missingWhenCases: List<WhenMissingCase>
|
abstract val missingWhenCases: List<WhenMissingCase>
|
||||||
|
|||||||
+15
@@ -2049,6 +2049,21 @@ internal class NotNullAssertionOnCallableReferenceImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class UselessElvisImpl(
|
||||||
|
override val receiverType: KtType,
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.UselessElvis(), KtAbstractFirDiagnostic<KtBinaryExpression> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class UselessElvisRightIsNullImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.UselessElvisRightIsNull(), KtAbstractFirDiagnostic<KtBinaryExpression> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class NoElseInWhenImpl(
|
internal class NoElseInWhenImpl(
|
||||||
override val missingWhenCases: List<WhenMissingCase>,
|
override val missingWhenCases: List<WhenMissingCase>,
|
||||||
firDiagnostic: FirPsiDiagnostic<*>,
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
|||||||
Reference in New Issue
Block a user