FIR checker: warn unnecessary safe calls
This commit is contained in:
committed by
Mikhail Glukhikh
parent
2ecb6733ed
commit
5a0b75bd89
@@ -16,7 +16,7 @@ fun test(ordinal: Int) {
|
|||||||
buildString {
|
buildString {
|
||||||
insert(KDocTemplate()) {
|
insert(KDocTemplate()) {
|
||||||
definition {
|
definition {
|
||||||
ordinal?.let {}
|
ordinal<!UNNECESSARY_SAFE_CALL!>?.<!>let {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -69,8 +69,8 @@ fun test_6(d1: D) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test_7(d1: D, d2: D) {
|
fun test_7(d1: D, d2: D) {
|
||||||
val a = d1?.any
|
val a = d1<!UNNECESSARY_SAFE_CALL!>?.<!>any
|
||||||
val b = d2?.any
|
val b = d2<!UNNECESSARY_SAFE_CALL!>?.<!>any
|
||||||
a as A
|
a as A
|
||||||
a.foo() // should be OK
|
a.foo() // should be OK
|
||||||
b as B
|
b as B
|
||||||
|
|||||||
+1
@@ -51,6 +51,7 @@ enum class PositioningStrategy(private val strategy: String? = null) {
|
|||||||
COMPANION_OBJECT,
|
COMPANION_OBJECT,
|
||||||
CONST_MODIFIER,
|
CONST_MODIFIER,
|
||||||
ARRAY_ACCESS,
|
ARRAY_ACCESS,
|
||||||
|
SAFE_ACCESS,
|
||||||
NAME_OF_NAMED_ARGUMENT,
|
NAME_OF_NAMED_ARGUMENT,
|
||||||
VALUE_ARGUMENTS,
|
VALUE_ARGUMENTS,
|
||||||
SUPERTYPES_LIST,
|
SUPERTYPES_LIST,
|
||||||
|
|||||||
+4
-1
@@ -559,7 +559,10 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
|||||||
parameter<String>("operator")
|
parameter<String>("operator")
|
||||||
parameter<FirExpression>("rhs")
|
parameter<FirExpression>("rhs")
|
||||||
}
|
}
|
||||||
// TODO: val UNEXPECTED_SAFE_CALL by ...
|
val UNNECESSARY_SAFE_CALL by warning<FirSourceElement, PsiElement>(PositioningStrategy.SAFE_ACCESS) {
|
||||||
|
parameter<ConeKotlinType>("receiverType")
|
||||||
|
}
|
||||||
|
val UNEXPECTED_SAFE_CALL by error<FirSourceElement, PsiElement>(PositioningStrategy.SAFE_ACCESS)
|
||||||
val UNNECESSARY_NOT_NULL_ASSERTION by warning<FirSourceElement, KtExpression>(PositioningStrategy.OPERATOR) {
|
val UNNECESSARY_NOT_NULL_ASSERTION by warning<FirSourceElement, KtExpression>(PositioningStrategy.OPERATOR) {
|
||||||
parameter<ConeKotlinType>("receiverType")
|
parameter<ConeKotlinType>("receiverType")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -331,6 +331,8 @@ object FirErrors {
|
|||||||
val UNSAFE_IMPLICIT_INVOKE_CALL by error1<FirSourceElement, PsiElement, ConeKotlinType>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
val UNSAFE_IMPLICIT_INVOKE_CALL by error1<FirSourceElement, PsiElement, ConeKotlinType>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
val UNSAFE_INFIX_CALL by error3<FirSourceElement, KtExpression, FirExpression, String, FirExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
val UNSAFE_INFIX_CALL by error3<FirSourceElement, KtExpression, FirExpression, String, FirExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
val UNSAFE_OPERATOR_CALL by error3<FirSourceElement, KtExpression, FirExpression, String, FirExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
val UNSAFE_OPERATOR_CALL by error3<FirSourceElement, KtExpression, FirExpression, String, FirExpression>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||||
|
val UNNECESSARY_SAFE_CALL by warning1<FirSourceElement, PsiElement, ConeKotlinType>(SourceElementPositioningStrategies.SAFE_ACCESS)
|
||||||
|
val UNEXPECTED_SAFE_CALL by error0<FirSourceElement, PsiElement>(SourceElementPositioningStrategies.SAFE_ACCESS)
|
||||||
val UNNECESSARY_NOT_NULL_ASSERTION by warning1<FirSourceElement, KtExpression, ConeKotlinType>(SourceElementPositioningStrategies.OPERATOR)
|
val UNNECESSARY_NOT_NULL_ASSERTION by warning1<FirSourceElement, KtExpression, ConeKotlinType>(SourceElementPositioningStrategies.OPERATOR)
|
||||||
val NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION by warning0<FirSourceElement, KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
val NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION by warning0<FirSourceElement, KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
||||||
val NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE by warning0<FirSourceElement, KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
val NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE by warning0<FirSourceElement, KtExpression>(SourceElementPositioningStrategies.OPERATOR)
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.FirSafeCallExpression
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
|
import org.jetbrains.kotlin.fir.types.canBeNull
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.fir.types.isUnit
|
||||||
|
|
||||||
|
object FirSafeCallExpressionChecker : FirBasicExpressionChecker() {
|
||||||
|
override fun check(expression: FirStatement, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
if (expression !is FirSafeCallExpression) return
|
||||||
|
|
||||||
|
val receiverType = expression.receiver.typeRef.coneType.fullyExpandedType(context.session)
|
||||||
|
if (receiverType.isUnit) {
|
||||||
|
reporter.reportOn(expression.source, FirErrors.UNEXPECTED_SAFE_CALL, context)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!receiverType.canBeNull) {
|
||||||
|
reporter.reportOn(expression.source, FirErrors.UNNECESSARY_SAFE_CALL, receiverType, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -77,6 +77,10 @@ class ExpressionCheckersDiagnosticComponent(
|
|||||||
checkers.allBasicExpressionCheckers.check(checkNotNullCall, data, reporter)
|
checkers.allBasicExpressionCheckers.check(checkNotNullCall, data, reporter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: CheckerContext) {
|
||||||
|
checkers.basicExpressionCheckers.check(safeCallExpression, data, reporter)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitTryExpression(tryExpression: FirTryExpression, data: CheckerContext) {
|
override fun visitTryExpression(tryExpression: FirTryExpression, data: CheckerContext) {
|
||||||
checkers.allTryExpressionCheckers.check(tryExpression, data, reporter)
|
checkers.allTryExpressionCheckers.check(tryExpression, data, reporter)
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -217,9 +217,11 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IN_CATCH_CLAUSE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IN_CATCH_CLAUSE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_ON_LHS_OF_DOT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_ON_LHS_OF_DOT
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNEXPECTED_SAFE_CALL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_VARIABLE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_VARIABLE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_LATEINIT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_LATEINIT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_NOT_NULL_ASSERTION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_NOT_NULL_ASSERTION
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_SAFE_CALL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_LABEL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_LABEL
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_REFERENCE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_REFERENCE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_CALL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_CALL
|
||||||
@@ -751,6 +753,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
|||||||
map.put(UNNECESSARY_NOT_NULL_ASSERTION, "Unnecessary non-null assertion (!!) on a non-null receiver of type {0}", RENDER_TYPE)
|
map.put(UNNECESSARY_NOT_NULL_ASSERTION, "Unnecessary non-null assertion (!!) on a non-null receiver of type {0}", RENDER_TYPE)
|
||||||
map.put(NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION, "Non-null assertion (!!) is called on a lambda expression")
|
map.put(NOT_NULL_ASSERTION_ON_LAMBDA_EXPRESSION, "Non-null assertion (!!) is called on a lambda expression")
|
||||||
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(UNEXPECTED_SAFE_CALL, "Safe-call is not allowed here")
|
||||||
|
|
||||||
// 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)
|
||||||
|
|||||||
+14
@@ -497,6 +497,17 @@ object LightTreePositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val SAFE_ACCESS = object : LightTreePositioningStrategy() {
|
||||||
|
override fun mark(
|
||||||
|
node: LighterASTNode,
|
||||||
|
startOffset: Int,
|
||||||
|
endOffset: Int,
|
||||||
|
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||||
|
): List<TextRange> {
|
||||||
|
return markElement(tree.safeAccess(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,
|
||||||
@@ -531,6 +542,9 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.constructorKeyword(nod
|
|||||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.dotOperator(node: LighterASTNode): LighterASTNode? =
|
private fun FlyweightCapableTreeStructure<LighterASTNode>.dotOperator(node: LighterASTNode): LighterASTNode? =
|
||||||
findChildByType(node, KtTokens.DOT)
|
findChildByType(node, KtTokens.DOT)
|
||||||
|
|
||||||
|
private fun FlyweightCapableTreeStructure<LighterASTNode>.safeAccess(node: LighterASTNode): LighterASTNode? =
|
||||||
|
findChildByType(node, KtTokens.SAFE_ACCESS)
|
||||||
|
|
||||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.initKeyword(node: LighterASTNode): LighterASTNode? =
|
private fun FlyweightCapableTreeStructure<LighterASTNode>.initKeyword(node: LighterASTNode): LighterASTNode? =
|
||||||
findChildByType(node, KtTokens.INIT_KEYWORD)
|
findChildByType(node, KtTokens.INIT_KEYWORD)
|
||||||
|
|
||||||
|
|||||||
+5
@@ -168,6 +168,11 @@ object SourceElementPositioningStrategies {
|
|||||||
PositioningStrategies.ARRAY_ACCESS
|
PositioningStrategies.ARRAY_ACCESS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val SAFE_ACCESS = SourceElementPositioningStrategy(
|
||||||
|
LightTreePositioningStrategies.SAFE_ACCESS,
|
||||||
|
PositioningStrategies.SAFE_ACCESS
|
||||||
|
)
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
+1
@@ -12,6 +12,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
FirAnonymousFunctionChecker,
|
FirAnonymousFunctionChecker,
|
||||||
FirCheckNotNullCallChecker,
|
FirCheckNotNullCallChecker,
|
||||||
FirGetClassCallChecker,
|
FirGetClassCallChecker,
|
||||||
|
FirSafeCallExpressionChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker> = setOf(
|
override val qualifiedAccessCheckers: Set<FirQualifiedAccessChecker> = setOf(
|
||||||
|
|||||||
+4
-1
@@ -490,7 +490,10 @@ class ExpressionsConverter(
|
|||||||
|
|
||||||
(firSelector as? FirQualifiedAccess)?.let {
|
(firSelector as? FirQualifiedAccess)?.let {
|
||||||
if (isSafe) {
|
if (isSafe) {
|
||||||
return it.wrapWithSafeCall(firReceiver!!)
|
return it.wrapWithSafeCall(
|
||||||
|
firReceiver!!,
|
||||||
|
dotQualifiedExpression.toFirSourceElement(FirFakeSourceElementKind.DesugaredSafeCallExpression)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
it.replaceExplicitReceiver(firReceiver)
|
it.replaceExplicitReceiver(firReceiver)
|
||||||
|
|||||||
@@ -1988,7 +1988,10 @@ open class RawFirBuilder(
|
|||||||
val receiver = expression.receiverExpression.toFirExpression("Incorrect receiver expression")
|
val receiver = expression.receiverExpression.toFirExpression("Incorrect receiver expression")
|
||||||
|
|
||||||
if (expression is KtSafeQualifiedExpression) {
|
if (expression is KtSafeQualifiedExpression) {
|
||||||
return firSelector.wrapWithSafeCall(receiver)
|
return firSelector.wrapWithSafeCall(
|
||||||
|
receiver,
|
||||||
|
expression.toFirSourceElement(FirFakeSourceElementKind.DesugaredSafeCallExpression)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
firSelector.replaceExplicitReceiver(receiver)
|
firSelector.replaceExplicitReceiver(receiver)
|
||||||
|
|||||||
+3
-3
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.fir.types.builder.*
|
|||||||
import org.jetbrains.kotlin.fir.types.impl.*
|
import org.jetbrains.kotlin.fir.types.impl.*
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi.KtQualifiedExpression
|
||||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
@@ -513,8 +514,7 @@ private fun FirExpression.checkReceiver(name: String?): Boolean {
|
|||||||
return receiverName == name
|
return receiverName == name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun FirQualifiedAccess.wrapWithSafeCall(receiver: FirExpression, source: FirSourceElement): FirSafeCallExpression {
|
||||||
fun FirQualifiedAccess.wrapWithSafeCall(receiver: FirExpression): FirSafeCallExpression {
|
|
||||||
val checkedSafeCallSubject = buildCheckedSafeCallSubject {
|
val checkedSafeCallSubject = buildCheckedSafeCallSubject {
|
||||||
@OptIn(FirContractViolation::class)
|
@OptIn(FirContractViolation::class)
|
||||||
this.originalReceiverRef = FirExpressionRef<FirExpression>().apply {
|
this.originalReceiverRef = FirExpressionRef<FirExpression>().apply {
|
||||||
@@ -531,7 +531,7 @@ fun FirQualifiedAccess.wrapWithSafeCall(receiver: FirExpression): FirSafeCallExp
|
|||||||
bind(checkedSafeCallSubject)
|
bind(checkedSafeCallSubject)
|
||||||
}
|
}
|
||||||
this.regularQualifiedAccess = this@wrapWithSafeCall
|
this.regularQualifiedAccess = this@wrapWithSafeCall
|
||||||
this.source = this@wrapWithSafeCall.source?.fakeElement(FirFakeSourceElementKind.DesugaredSafeCallExpression)
|
this.source = source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -421,6 +421,13 @@ object PositioningStrategies {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val SAFE_ACCESS: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
|
||||||
|
override fun mark(element: PsiElement): List<TextRange> {
|
||||||
|
return markElement(element.node.findChildByType(KtTokens.SAFE_ACCESS)?.psi ?: element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class ModifierSetBasedPositioningStrategy(private val modifierSet: TokenSet) : PositioningStrategy<KtModifierListOwner>() {
|
private class ModifierSetBasedPositioningStrategy(private val modifierSet: TokenSet) : PositioningStrategy<KtModifierListOwner>() {
|
||||||
override fun mark(element: KtModifierListOwner): List<TextRange> {
|
override fun mark(element: KtModifierListOwner): List<TextRange> {
|
||||||
val modifierList = element.modifierList
|
val modifierList = element.modifierList
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
fun bar(doIt: Int.() -> Int) {
|
fun bar(doIt: Int.() -> Int) {
|
||||||
1.doIt()
|
1.doIt()
|
||||||
1?.doIt()
|
1<!UNNECESSARY_SAFE_CALL!>?.<!>doIt()
|
||||||
val i: Int? = 1
|
val i: Int? = 1
|
||||||
i.<!INAPPLICABLE_CANDIDATE!>doIt<!>()
|
i.<!INAPPLICABLE_CANDIDATE!>doIt<!>()
|
||||||
i?.doIt()
|
i?.doIt()
|
||||||
|
|||||||
@@ -82,6 +82,6 @@ fun test() {
|
|||||||
val i : Int? = null
|
val i : Int? = null
|
||||||
i.(<!UNRESOLVED_REFERENCE!>fun Int.() = 1<!>)();
|
i.(<!UNRESOLVED_REFERENCE!>fun Int.() = 1<!>)();
|
||||||
<!INAPPLICABLE_CANDIDATE!>{}<!><Int>()
|
<!INAPPLICABLE_CANDIDATE!>{}<!><Int>()
|
||||||
1?.(<!UNRESOLVED_REFERENCE!>fun Int.() = 1<!>)()
|
1<!UNNECESSARY_SAFE_CALL!>?.<!>(<!UNRESOLVED_REFERENCE!>fun Int.() = 1<!>)()
|
||||||
1.<!UNRESOLVED_REFERENCE!>{}<!>()
|
1.<!UNRESOLVED_REFERENCE!>{}<!>()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ fun foo() {
|
|||||||
// these both also ok (with smart cast / unnecessary safe call)
|
// these both also ok (with smart cast / unnecessary safe call)
|
||||||
if (rule != null) {
|
if (rule != null) {
|
||||||
rule.apply()
|
rule.apply()
|
||||||
rule?.apply()
|
rule<!UNNECESSARY_SAFE_CALL!>?.<!>apply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
// http://youtrack.jetbrains.net/issue/KT-418
|
|
||||||
|
|
||||||
fun ff() {
|
|
||||||
val i: Int = 1
|
|
||||||
val a: Int = i?.plus(2)
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// http://youtrack.jetbrains.net/issue/KT-418
|
// http://youtrack.jetbrains.net/issue/KT-418
|
||||||
|
|
||||||
fun ff() {
|
fun ff() {
|
||||||
|
|||||||
+1
-1
@@ -3,5 +3,5 @@ fun Int.gg() = null
|
|||||||
|
|
||||||
fun ff() {
|
fun ff() {
|
||||||
val a: Int = 1
|
val a: Int = 1
|
||||||
val b: Int = a?.gg()
|
val b: Int = a<!UNNECESSARY_SAFE_CALL!>?.<!>gg()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ val s: String = "test"
|
|||||||
|
|
||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
fun ff() {
|
fun ff() {
|
||||||
val a = Test?.<!UNRESOLVED_REFERENCE!>FOO<!>
|
val a = Test<!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>FOO<!>
|
||||||
val b = foo?.<!UNRESOLVED_REFERENCE!>s<!>
|
val b = foo<!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>s<!>
|
||||||
System?.<!UNRESOLVED_REFERENCE!>out<!>.<!UNRESOLVED_REFERENCE!>println<!>(a + b)
|
System<!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>out<!>.<!UNRESOLVED_REFERENCE!>println<!>(a + b)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ fun test11() {
|
|||||||
|
|
||||||
fun test12() {
|
fun test12() {
|
||||||
fun Any.bar(i: Int) {}
|
fun Any.bar(i: Int) {}
|
||||||
todo()?.bar(1)
|
todo()<!UNNECESSARY_SAFE_CALL!>?.<!>bar(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun todo(): Nothing = throw Exception()
|
fun todo(): Nothing = throw Exception()
|
||||||
+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?.let { throw Exception() } ?: "unreachable"
|
val y = x<!UNNECESSARY_SAFE_CALL!>?.<!>let { throw Exception() } ?: "unreachable"
|
||||||
return y
|
return y
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ fun <T: Any, E> T.foo(x : E, y : A) : T {
|
|||||||
y plus 1
|
y plus 1
|
||||||
y + 1.0
|
y + 1.0
|
||||||
|
|
||||||
this?.minus<T>(this)
|
this<!UNNECESSARY_SAFE_CALL!>?.<!>minus<T>(this)
|
||||||
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ import outer.*
|
|||||||
command?.equals1(null)
|
command?.equals1(null)
|
||||||
|
|
||||||
val c = Command()
|
val c = Command()
|
||||||
c?.equals2(null)
|
c<!UNNECESSARY_SAFE_CALL!>?.<!>equals2(null)
|
||||||
|
|
||||||
if (command == null) 1
|
if (command == null) 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,15 +27,15 @@ fun foo(l: A<String>?) {
|
|||||||
foo(l?.bar()) checkType { _<String?>() }
|
foo(l?.bar()) checkType { _<String?>() }
|
||||||
foo(l?.gav()) checkType { _<String?>() }
|
foo(l?.gav()) checkType { _<String?>() }
|
||||||
if (l != null) {
|
if (l != null) {
|
||||||
foo(l?.bar()) checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
foo(l<!UNNECESSARY_SAFE_CALL!>?.<!>bar()) checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||||
foo(l?.gav()) checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
foo(l<!UNNECESSARY_SAFE_CALL!>?.<!>gav()) checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fooNotNull(l: A<String>) {
|
fun fooNotNull(l: A<String>) {
|
||||||
// No errors should be here
|
// No errors should be here
|
||||||
foo(l?.bar()) checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
foo(l<!UNNECESSARY_SAFE_CALL!>?.<!>bar()) checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||||
foo(l?.gav()) checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
foo(l<!UNNECESSARY_SAFE_CALL!>?.<!>gav()) checkType { <!INAPPLICABLE_CANDIDATE!>_<!><String>() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bar() {
|
fun bar() {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ fun <T : CharSequence?> foo(x: T) {
|
|||||||
if (x != null) {}
|
if (x != null) {}
|
||||||
|
|
||||||
x.length
|
x.length
|
||||||
x?.length
|
x<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||||
|
|
||||||
x.bar1()
|
x.bar1()
|
||||||
x.bar2()
|
x.bar2()
|
||||||
@@ -21,14 +21,14 @@ fun <T : CharSequence?> foo(x: T) {
|
|||||||
x.bar4()
|
x.bar4()
|
||||||
|
|
||||||
|
|
||||||
x?.bar1()
|
x<!UNNECESSARY_SAFE_CALL!>?.<!>bar1()
|
||||||
}
|
}
|
||||||
|
|
||||||
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
x.<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||||
|
|
||||||
if (x is String) {
|
if (x is String) {
|
||||||
x.length
|
x.length
|
||||||
x?.length
|
x<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||||
|
|
||||||
x.bar1()
|
x.bar1()
|
||||||
x.bar2()
|
x.bar2()
|
||||||
@@ -37,7 +37,7 @@ fun <T : CharSequence?> foo(x: T) {
|
|||||||
|
|
||||||
if (x is CharSequence) {
|
if (x is CharSequence) {
|
||||||
x.length
|
x.length
|
||||||
x?.length
|
x<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||||
|
|
||||||
x.bar1()
|
x.bar1()
|
||||||
x.bar2()
|
x.bar2()
|
||||||
|
|||||||
+3
-3
@@ -12,7 +12,7 @@ fun <T : String?> T.foo() {
|
|||||||
if (this != null) {}
|
if (this != null) {}
|
||||||
|
|
||||||
length
|
length
|
||||||
this?.length
|
this<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||||
|
|
||||||
bar1()
|
bar1()
|
||||||
bar2()
|
bar2()
|
||||||
@@ -20,14 +20,14 @@ fun <T : String?> T.foo() {
|
|||||||
bar4()
|
bar4()
|
||||||
|
|
||||||
|
|
||||||
this?.bar1()
|
this<!UNNECESSARY_SAFE_CALL!>?.<!>bar1()
|
||||||
}
|
}
|
||||||
|
|
||||||
<!INAPPLICABLE_CANDIDATE!>length<!>
|
<!INAPPLICABLE_CANDIDATE!>length<!>
|
||||||
|
|
||||||
if (this is String) {
|
if (this is String) {
|
||||||
length
|
length
|
||||||
this?.length
|
this<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||||
|
|
||||||
bar1()
|
bar1()
|
||||||
bar2()
|
bar2()
|
||||||
|
|||||||
@@ -55,5 +55,5 @@ fun test2(t: Test?) {
|
|||||||
val xSafeCallSafeCastExplicitType = t?.findViewById<X>(0) as? X
|
val xSafeCallSafeCastExplicitType = t?.findViewById<X>(0) as? X
|
||||||
|
|
||||||
val xSafeCallCast = t?.findViewById(0) as X
|
val xSafeCallCast = t?.findViewById(0) as X
|
||||||
val xSafeCallCastExplicitType = t?.findViewById<X>(0) as X
|
val xSafeCallCastExplicitType = t<!UNNECESSARY_SAFE_CALL!>?.<!>findViewById<X>(0) as X
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -11,7 +11,7 @@ interface B {
|
|||||||
|
|
||||||
fun test(u: A?, x: A?, y: A?, z: A?, w: A, v: A?) {
|
fun test(u: A?, x: A?, y: A?, z: A?, w: A, v: A?) {
|
||||||
u?.b?.foo()!! // was UNNECESSARY_SAFE_CALL everywhere, because result type (of 'foo()') wasn't made nullable
|
u?.b?.foo()!! // was UNNECESSARY_SAFE_CALL everywhere, because result type (of 'foo()') wasn't made nullable
|
||||||
u!!.b?.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
u!!.b<!UNNECESSARY_SAFE_CALL!>?.<!>foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
x?.b!!.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
x?.b!!.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
// x?.b is not null
|
// x?.b is not null
|
||||||
x!!.b<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
x!!.b<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
@@ -22,7 +22,7 @@ fun test(u: A?, x: A?, y: A?, z: A?, w: A, v: A?) {
|
|||||||
// z?.nb is not null
|
// z?.nb is not null
|
||||||
z!!.nb!!.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
z!!.nb!!.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
|
|
||||||
w.b?.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
w.b<!UNNECESSARY_SAFE_CALL!>?.<!>foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
w.b<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
w.b<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
w.nb?.foo()!!
|
w.nb?.foo()!!
|
||||||
w.nb!!.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
w.nb!!.foo()<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
|
|||||||
+1
-1
@@ -18,5 +18,5 @@ fun smartCastAfterIntersection(a: One, b: Two) = run {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun test(one: One, two: Two) {
|
fun test(one: One, two: Two) {
|
||||||
smartCastAfterIntersection(one, two)?.<!UNRESOLVED_REFERENCE!>base<!>()
|
smartCastAfterIntersection(one, two)<!UNNECESSARY_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>base<!>()
|
||||||
}
|
}
|
||||||
|
|||||||
-34
@@ -1,34 +0,0 @@
|
|||||||
// MODULE: m1
|
|
||||||
// FILE: a.kt
|
|
||||||
package p
|
|
||||||
|
|
||||||
public interface B<T, Z> {
|
|
||||||
public fun foo(a: T?)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MODULE: m2(m1)
|
|
||||||
// FILE: b.kt
|
|
||||||
package p
|
|
||||||
|
|
||||||
public interface C<X, Z> : B<X, Z> {
|
|
||||||
override fun foo(a: X?)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// MODULE: m3
|
|
||||||
// FILE: b.kt
|
|
||||||
package p
|
|
||||||
|
|
||||||
public interface B<Z, T> {
|
|
||||||
public fun foo(a: T?)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MODULE: m4(m3, m2)
|
|
||||||
// FILE: c.kt
|
|
||||||
import p.*
|
|
||||||
|
|
||||||
fun <Y, Z> test(b: B<Y, Z>?) {
|
|
||||||
if (b is C<Y, Z>) {
|
|
||||||
b?.<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// MODULE: m1
|
// MODULE: m1
|
||||||
// FILE: a.kt
|
// FILE: a.kt
|
||||||
package p
|
package p
|
||||||
|
|||||||
+1
-1
@@ -32,6 +32,6 @@ fun test(b: B?, c: C) {
|
|||||||
b?.foo(1, 1)
|
b?.foo(1, 1)
|
||||||
c.<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(1, 1)
|
c.<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(1, 1)
|
||||||
if (b is C) {
|
if (b is C) {
|
||||||
b?.<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(1, 1)
|
b<!UNNECESSARY_SAFE_CALL!>?.<!><!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!>(1, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -29,6 +29,6 @@ import p.*
|
|||||||
|
|
||||||
fun test(b: B?) {
|
fun test(b: B?) {
|
||||||
if (b is C) {
|
if (b is C) {
|
||||||
b?.foo(1, "")
|
b<!UNNECESSARY_SAFE_CALL!>?.<!>foo(1, "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vendored
-38
@@ -1,38 +0,0 @@
|
|||||||
// MODULE: m1
|
|
||||||
// FILE: a.kt
|
|
||||||
package p
|
|
||||||
|
|
||||||
public interface B {
|
|
||||||
public fun getParent(): B?
|
|
||||||
}
|
|
||||||
|
|
||||||
// MODULE: m2(m1)
|
|
||||||
// FILE: b.kt
|
|
||||||
package p
|
|
||||||
|
|
||||||
public interface C : B {
|
|
||||||
override fun getParent(): B?
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// MODULE: m3
|
|
||||||
// FILE: b.kt
|
|
||||||
package p
|
|
||||||
|
|
||||||
public interface B {
|
|
||||||
public fun getParent(): B?
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface D : B {
|
|
||||||
override fun getParent(): B?
|
|
||||||
}
|
|
||||||
|
|
||||||
// MODULE: m4(m3, m2)
|
|
||||||
// FILE: c.kt
|
|
||||||
import p.*
|
|
||||||
|
|
||||||
fun test(b: B?) {
|
|
||||||
if (b is C && b is D) {
|
|
||||||
b?.getParent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// MODULE: m1
|
// MODULE: m1
|
||||||
// FILE: a.kt
|
// FILE: a.kt
|
||||||
package p
|
package p
|
||||||
|
|||||||
Vendored
-34
@@ -1,34 +0,0 @@
|
|||||||
// MODULE: m1
|
|
||||||
// FILE: a.kt
|
|
||||||
package p
|
|
||||||
|
|
||||||
public interface B<T> {
|
|
||||||
public fun foo(a: T)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MODULE: m2(m1)
|
|
||||||
// FILE: b.kt
|
|
||||||
package p
|
|
||||||
|
|
||||||
public interface C : B<String> {
|
|
||||||
override fun foo(a: String)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// MODULE: m3
|
|
||||||
// FILE: b.kt
|
|
||||||
package p
|
|
||||||
|
|
||||||
public interface B {
|
|
||||||
public fun foo(a: String)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MODULE: m4(m3, m2)
|
|
||||||
// FILE: c.kt
|
|
||||||
import p.*
|
|
||||||
|
|
||||||
fun test(b: B?) {
|
|
||||||
if (b is C) {
|
|
||||||
b?.foo("")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// MODULE: m1
|
// MODULE: m1
|
||||||
// FILE: a.kt
|
// FILE: a.kt
|
||||||
package p
|
package p
|
||||||
|
|||||||
-44
@@ -1,44 +0,0 @@
|
|||||||
class A {
|
|
||||||
fun foo() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun A.bar() {}
|
|
||||||
fun A?.buzz() {}
|
|
||||||
|
|
||||||
fun test(a : A?) {
|
|
||||||
a<!UNSAFE_CALL!>.<!>foo() // error
|
|
||||||
a<!UNSAFE_CALL!>.<!>bar() // error
|
|
||||||
a.buzz()
|
|
||||||
|
|
||||||
a?.foo()
|
|
||||||
a?.bar()
|
|
||||||
a?.buzz()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun A.test2() {
|
|
||||||
foo()
|
|
||||||
bar()
|
|
||||||
buzz()
|
|
||||||
|
|
||||||
this.foo()
|
|
||||||
this.bar()
|
|
||||||
this.buzz()
|
|
||||||
|
|
||||||
this?.foo() // warning
|
|
||||||
this?.bar() // warning
|
|
||||||
this?.buzz() // warning
|
|
||||||
}
|
|
||||||
|
|
||||||
fun A?.test3() {
|
|
||||||
<!UNSAFE_CALL!>foo<!>() // error
|
|
||||||
<!UNSAFE_CALL!>bar<!>() // error
|
|
||||||
buzz()
|
|
||||||
|
|
||||||
this<!UNSAFE_CALL!>.<!>foo() // error
|
|
||||||
this<!UNSAFE_CALL!>.<!>bar() // error
|
|
||||||
this.buzz()
|
|
||||||
|
|
||||||
this?.foo()
|
|
||||||
this?.bar()
|
|
||||||
this?.buzz()
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
class A {
|
class A {
|
||||||
fun foo() {}
|
fun foo() {}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ fun <N : Number?> test(arg: N) {
|
|||||||
|
|
||||||
makeDefinitelyNotNull(arg)<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
makeDefinitelyNotNull(arg)<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
|
|
||||||
makeDefinitelyNotNull(arg)?.toInt()
|
makeDefinitelyNotNull(arg)<!UNNECESSARY_SAFE_CALL!>?.<!>toInt()
|
||||||
|
|
||||||
val nullImposible = when (val dnn = makeDefinitelyNotNull(arg)) {
|
val nullImposible = when (val dnn = makeDefinitelyNotNull(arg)) {
|
||||||
null -> false
|
null -> false
|
||||||
|
|||||||
Vendored
+2
-2
@@ -1,14 +1,14 @@
|
|||||||
// !WITH_NEW_INFERENCE
|
// !WITH_NEW_INFERENCE
|
||||||
fun <T> test(t: T): String? {
|
fun <T> test(t: T): String? {
|
||||||
if (t != null) {
|
if (t != null) {
|
||||||
return t?.toString()
|
return t<!UNNECESSARY_SAFE_CALL!>?.<!>toString()
|
||||||
}
|
}
|
||||||
return t?.toString()
|
return t?.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> T.testThis(): String? {
|
fun <T> T.testThis(): String? {
|
||||||
if (this != null) {
|
if (this != null) {
|
||||||
return this?.toString()
|
return this<!UNNECESSARY_SAFE_CALL!>?.<!>toString()
|
||||||
}
|
}
|
||||||
return this?.toString()
|
return this?.toString()
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-27
@@ -52,40 +52,40 @@ fun foo(a: A?) {
|
|||||||
a?.w.inc()
|
a?.w.inc()
|
||||||
|
|
||||||
if (a != null) {
|
if (a != null) {
|
||||||
a?.l += 1
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>l += 1
|
||||||
a?.l[0]
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>l[0]
|
||||||
a?.l[0]++
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>l[0]++
|
||||||
a?.l[0] = 1
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>l[0] = 1
|
||||||
|
|
||||||
a?.ll[0][0]
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>ll[0][0]
|
||||||
a?.ll[0][0]++
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>ll[0][0]++
|
||||||
a?.ll[0][0] = 1
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>ll[0][0] = 1
|
||||||
// No warning is reported because
|
// No warning is reported because
|
||||||
// 1. All kinds of green code with safe+call + invoke we identified fails with CCE if `a != null`, anyway
|
// 1. All kinds of green code with safe+call + invoke we identified fails with CCE if `a != null`, anyway
|
||||||
// 2. In case of null value, the behavior is intended (no call performed)
|
// 2. In case of null value, the behavior is intended (no call performed)
|
||||||
a?.q()
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>q()
|
||||||
a?.w++
|
a<!UNNECESSARY_SAFE_CALL, UNNECESSARY_SAFE_CALL!>?.<!>w++
|
||||||
|
|
||||||
(a?.l) += 1
|
(a<!UNNECESSARY_SAFE_CALL!>?.<!>l) += 1
|
||||||
(a?.l)[0]
|
(a<!UNNECESSARY_SAFE_CALL!>?.<!>l)[0]
|
||||||
(a?.l)[0]++
|
(a<!UNNECESSARY_SAFE_CALL!>?.<!>l)[0]++
|
||||||
(a?.l)[0] = 1
|
(a<!UNNECESSARY_SAFE_CALL!>?.<!>l)[0] = 1
|
||||||
|
|
||||||
(a?.ll)[0][0]
|
(a<!UNNECESSARY_SAFE_CALL!>?.<!>ll)[0][0]
|
||||||
(a?.ll)[0][0]++
|
(a<!UNNECESSARY_SAFE_CALL!>?.<!>ll)[0][0]++
|
||||||
(a?.ll)[0][0] = 1
|
(a<!UNNECESSARY_SAFE_CALL!>?.<!>ll)[0][0] = 1
|
||||||
(a?.q)()
|
(a<!UNNECESSARY_SAFE_CALL!>?.<!>q)()
|
||||||
(a?.w)++
|
(a<!UNNECESSARY_SAFE_CALL, UNNECESSARY_SAFE_CALL!>?.<!>w)++
|
||||||
|
|
||||||
a?.l.plusAssign(1)
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>l.plusAssign(1)
|
||||||
a?.l.get(0)
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>l.get(0)
|
||||||
a?.l.get(0).inc()
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>l.get(0).inc()
|
||||||
a?.l.set(0, 1)
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>l.set(0, 1)
|
||||||
|
|
||||||
a?.ll.get(0).get(0)
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>ll.get(0).get(0)
|
||||||
a?.ll.get(0).get(0).inc()
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>ll.get(0).get(0).inc()
|
||||||
a?.ll.get(0).set(0, 1)
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>ll.get(0).set(0, 1)
|
||||||
a?.q.invoke()
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>q.invoke()
|
||||||
a?.w.inc()
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>w.inc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
// FILE: A.java
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public class A<T> {
|
|
||||||
public static A<String> create() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public T bar() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: k.kt
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
A.create().bar()?.length
|
|
||||||
A<String?>().bar()?.length
|
|
||||||
}
|
|
||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// FILE: A.java
|
// FILE: A.java
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|||||||
Vendored
-19
@@ -1,19 +0,0 @@
|
|||||||
// FILE: A.java
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
public class A<T> {
|
|
||||||
@NotNull
|
|
||||||
public T bar() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: k.kt
|
|
||||||
|
|
||||||
fun test(a: A<out CharSequence>) {
|
|
||||||
a.bar()?.length
|
|
||||||
a.bar()?.length
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// FILE: A.java
|
// FILE: A.java
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ public class J {
|
|||||||
fun list(j: J): Any {
|
fun list(j: J): Any {
|
||||||
val a = j.n()!!
|
val a = j.n()!!
|
||||||
|
|
||||||
a?.get(0)
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>get(0)
|
||||||
if (a == null) {}
|
if (a == null) {}
|
||||||
a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
a<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||||
|
|
||||||
|
|||||||
-43
@@ -1,43 +0,0 @@
|
|||||||
// !DIAGNOSTICS: -SENSELESS_COMPARISON
|
|
||||||
|
|
||||||
// FILE: J.java
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.*;
|
|
||||||
|
|
||||||
public class J {
|
|
||||||
@NotNull
|
|
||||||
public static J staticNN;
|
|
||||||
@Nullable
|
|
||||||
public static J staticN;
|
|
||||||
public static J staticJ;
|
|
||||||
|
|
||||||
public void foo() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FILE: k.kt
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
// @NotNull platform type
|
|
||||||
val platformNN = J.staticNN
|
|
||||||
// @Nullable platform type
|
|
||||||
val platformN = J.staticN
|
|
||||||
// platform type with no annotation
|
|
||||||
val platformJ = J.staticJ
|
|
||||||
|
|
||||||
platformNN?.foo()
|
|
||||||
platformN?.foo()
|
|
||||||
platformJ?.foo()
|
|
||||||
|
|
||||||
if (platformNN != null) {
|
|
||||||
platformNN?.foo()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (platformN != null) {
|
|
||||||
platformN?.foo()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (platformJ != null) {
|
|
||||||
platformJ?.foo()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -SENSELESS_COMPARISON
|
// !DIAGNOSTICS: -SENSELESS_COMPARISON
|
||||||
|
|
||||||
// FILE: J.java
|
// FILE: J.java
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ fun test(room : Object) {
|
|||||||
for(item: Item? in items) {
|
for(item: Item? in items) {
|
||||||
if (item?.room === room) {
|
if (item?.room === room) {
|
||||||
// item?.room is not null
|
// item?.room is not null
|
||||||
System.out.println("You see " + item?.name)
|
System.out.println("You see " + item<!UNNECESSARY_SAFE_CALL!>?.<!>name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -4,6 +4,6 @@ fun main() {
|
|||||||
|
|
||||||
val command : Any = 1
|
val command : Any = 1
|
||||||
|
|
||||||
command?.equals(null)
|
command<!UNNECESSARY_SAFE_CALL!>?.<!>equals(null)
|
||||||
command.equals(null)
|
command.equals(null)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ fun testNullableReceiver(nullable: Cls?) {
|
|||||||
|
|
||||||
fun testNotNullableReceiver(notNullable: Cls) {
|
fun testNotNullableReceiver(notNullable: Cls) {
|
||||||
notNullable.<!UNSAFE_IMPLICIT_INVOKE_CALL!>nullableExtensionProperty<!>()
|
notNullable.<!UNSAFE_IMPLICIT_INVOKE_CALL!>nullableExtensionProperty<!>()
|
||||||
notNullable?.extensionProperty()
|
notNullable<!UNNECESSARY_SAFE_CALL!>?.<!>extensionProperty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun testFlexibleReceiver() {
|
fun testFlexibleReceiver() {
|
||||||
|
|||||||
Vendored
+2
-2
@@ -5,7 +5,7 @@ fun test(foo: Foo?) {
|
|||||||
// Correct
|
// Correct
|
||||||
foo.bar?.length
|
foo.bar?.length
|
||||||
// Unnecessary
|
// Unnecessary
|
||||||
foo?.bar?.length
|
foo<!UNNECESSARY_SAFE_CALL!>?.<!>bar?.length
|
||||||
}
|
}
|
||||||
foo.bar?.length
|
foo.bar<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||||
}
|
}
|
||||||
@@ -17,5 +17,5 @@ fun test1(a: A) {
|
|||||||
fun test2() {
|
fun test2() {
|
||||||
val a: A? = null;
|
val a: A? = null;
|
||||||
assert((a as B).bool())
|
assert((a as B).bool())
|
||||||
a?.bool()
|
a<!UNNECESSARY_SAFE_CALL!>?.<!>bool()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
fun test1(s: String?) {
|
fun test1(s: String?) {
|
||||||
assert(s!!.isEmpty())
|
assert(s!!.isEmpty())
|
||||||
s?.length
|
s<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test2(s: String?) {
|
fun test2(s: String?) {
|
||||||
@@ -21,7 +21,7 @@ fun test3(s: String?) {
|
|||||||
fun test4() {
|
fun test4() {
|
||||||
val s: String? = null;
|
val s: String? = null;
|
||||||
assert(s!!.isEmpty())
|
assert(s!!.isEmpty())
|
||||||
s?.length
|
s<!UNNECESSARY_SAFE_CALL!>?.<!>length
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test5() {
|
fun test5() {
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@ public class Test {
|
|||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
fun ff() {
|
fun ff() {
|
||||||
val a = Test.FOO
|
val a = Test.FOO
|
||||||
val b = Test?.<!UNRESOLVED_REFERENCE!>FOO<!>
|
val b = Test<!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>FOO<!>
|
||||||
System.out.println(a + b)
|
System.out.println(a + b)
|
||||||
System?.<!UNRESOLVED_REFERENCE!>out<!>.<!UNRESOLVED_REFERENCE!>println<!>(a + b)
|
System<!UNEXPECTED_SAFE_CALL!>?.<!><!UNRESOLVED_REFERENCE!>out<!>.<!UNRESOLVED_REFERENCE!>println<!>(a + b)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+11
-11
@@ -27,7 +27,7 @@ fun case_3(value_1: Any?, value_2: Any?) {
|
|||||||
fun case_4(value_1: Any?, value_2: Number?) {
|
fun case_4(value_1: Any?, value_2: Number?) {
|
||||||
funWithReturns(value_1 is Float? && value_1 != null && value_2 != null)
|
funWithReturns(value_1 is Float? && value_1 != null && value_2 != null)
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
// TESTCASE NUMBER: 5
|
// TESTCASE NUMBER: 5
|
||||||
@@ -38,7 +38,7 @@ class case_5_class {
|
|||||||
val o = case_5_class()
|
val o = case_5_class()
|
||||||
funWithReturns(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null)
|
funWithReturns(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null)
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
println(o.prop_1.plus(3))
|
println(o.prop_1.plus(3))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,19 +107,19 @@ fun case_8(value_1: Any?, value_2: Any?) {
|
|||||||
fun case_9(value_1: Any?, value_2: Number?) {
|
fun case_9(value_1: Any?, value_2: Number?) {
|
||||||
if (funWithReturnsTrue(value_1 is Float? && value_1 != null && value_2 != null)) {
|
if (funWithReturnsTrue(value_1 is Float? && value_1 != null && value_2 != null)) {
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
}
|
}
|
||||||
if (!funWithReturnsFalse(value_1 is Float? && value_1 != null && value_2 != null)) {
|
if (!funWithReturnsFalse(value_1 is Float? && value_1 != null && value_2 != null)) {
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
}
|
}
|
||||||
if (funWithReturnsNotNull(value_1 is Float? && value_1 != null && value_2 != null) != null) {
|
if (funWithReturnsNotNull(value_1 is Float? && value_1 != null && value_2 != null) != null) {
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
}
|
}
|
||||||
if (funWithReturnsNull(value_1 is Float? && value_1 != null && value_2 != null) == null) {
|
if (funWithReturnsNull(value_1 is Float? && value_1 != null && value_2 != null) == null) {
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,22 +131,22 @@ class case_10_class {
|
|||||||
val o = case_10_class()
|
val o = case_10_class()
|
||||||
if (funWithReturnsTrue(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null)) {
|
if (funWithReturnsTrue(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null)) {
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
println(o.prop_1.plus(3))
|
println(o.prop_1.plus(3))
|
||||||
}
|
}
|
||||||
if (!funWithReturnsFalse(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null)) {
|
if (!funWithReturnsFalse(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null)) {
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
println(o.prop_1.plus(3))
|
println(o.prop_1.plus(3))
|
||||||
}
|
}
|
||||||
if (funWithReturnsNotNull(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null) != null) {
|
if (funWithReturnsNotNull(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null) != null) {
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
println(o.prop_1.plus(3))
|
println(o.prop_1.plus(3))
|
||||||
}
|
}
|
||||||
if (funWithReturnsNull(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null) == null) {
|
if (funWithReturnsNull(value_1 is Float? && value_1 != null && value_2 != null && o.prop_1 != null && this.prop_1 != null) == null) {
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
println(o.prop_1.plus(3))
|
println(o.prop_1.plus(3))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,5 +160,5 @@ class case_10_class {
|
|||||||
fun case_11(value_1: Any?, value_2: Any?, value_3: Any?) {
|
fun case_11(value_1: Any?, value_2: Any?, value_3: Any?) {
|
||||||
funWithReturnsAndInvertCondition(value_1 !is String || value_2 !is Number || value_3 !is Any?)
|
funWithReturnsAndInvertCondition(value_1 !is String || value_2 !is Number || value_3 !is Any?)
|
||||||
println(value_1<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length)
|
println(value_1<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>.length)
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+5
-5
@@ -103,7 +103,7 @@ class case_3_class {
|
|||||||
val o = case_3_class()
|
val o = case_3_class()
|
||||||
contracts.case_3(value_1, value_2, o.prop_1, this.prop_1)
|
contracts.case_3(value_1, value_2, o.prop_1, this.prop_1)
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
println(o.prop_1.plus(3))
|
println(o.prop_1.plus(3))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,22 +155,22 @@ class case_6_class {
|
|||||||
val o = case_6_class()
|
val o = case_6_class()
|
||||||
if (contracts.case_6_1(value_1, value_2, o.prop_1, this.prop_1)) {
|
if (contracts.case_6_1(value_1, value_2, o.prop_1, this.prop_1)) {
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
println(o.prop_1.plus(3))
|
println(o.prop_1.plus(3))
|
||||||
}
|
}
|
||||||
if (!contracts.case_6_2(value_1, value_2, o.prop_1, this.prop_1)) {
|
if (!contracts.case_6_2(value_1, value_2, o.prop_1, this.prop_1)) {
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
println(o.prop_1.plus(3))
|
println(o.prop_1.plus(3))
|
||||||
}
|
}
|
||||||
if (contracts.case_6_3(value_1, value_2, o.prop_1, this.prop_1) != null) {
|
if (contracts.case_6_3(value_1, value_2, o.prop_1, this.prop_1) != null) {
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
println(o.prop_1.plus(3))
|
println(o.prop_1.plus(3))
|
||||||
}
|
}
|
||||||
if (contracts.case_6_4(value_1, value_2, o.prop_1, this.prop_1) == null) {
|
if (contracts.case_6_4(value_1, value_2, o.prop_1, this.prop_1) == null) {
|
||||||
println(value_1.dec())
|
println(value_1.dec())
|
||||||
println(value_2?.toByte())
|
println(value_2<!UNNECESSARY_SAFE_CALL!>?.<!>toByte())
|
||||||
println(o.prop_1.plus(3))
|
println(o.prop_1.plus(3))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ fun case_4(x: Any) {
|
|||||||
fun case_5(x: Any?) {
|
fun case_5(x: Any?) {
|
||||||
if (!(x !is Nothing?)) {
|
if (!(x !is Nothing?)) {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing")!>x<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing")!>x<!>?.inv()
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing")!>x<!><!UNNECESSARY_SAFE_CALL!>?.<!>inv()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ fun case_8(x: Any?) {
|
|||||||
fun case_9(x: Any?) {
|
fun case_9(x: Any?) {
|
||||||
if (!!(x !is Nothing?)) else {
|
if (!!(x !is Nothing?)) else {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing")!>x<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing")!>x<!>?.inv()
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any? & kotlin.Nothing")!>x<!><!UNNECESSARY_SAFE_CALL!>?.<!>inv()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ fun case_3(x: Class?) {
|
|||||||
* ISSUES: KT-30376
|
* ISSUES: KT-30376
|
||||||
*/
|
*/
|
||||||
fun case_4(x: Class?) {
|
fun case_4(x: Class?) {
|
||||||
if (x!!?.prop_8?.prop_8?.prop_8?.prop_8 == null == true) else {
|
if (x!!<!UNNECESSARY_SAFE_CALL!>?.<!>prop_8?.prop_8?.prop_8?.prop_8 == null == true) else {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8
|
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8<!UNSAFE_CALL!>.<!>prop_8
|
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8<!UNSAFE_CALL!>.<!>prop_8
|
||||||
@@ -68,7 +68,7 @@ fun case_4(x: Class?) {
|
|||||||
* ISSUES: KT-30376
|
* ISSUES: KT-30376
|
||||||
*/
|
*/
|
||||||
fun case_5(x: Class?) {
|
fun case_5(x: Class?) {
|
||||||
if (x?.prop_8!!?.prop_8?.prop_8?.prop_8 == null == true) else {
|
if (x?.prop_8!!<!UNNECESSARY_SAFE_CALL!>?.<!>prop_8?.prop_8?.prop_8 == null == true) else {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8
|
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8.prop_8
|
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8.prop_8
|
||||||
@@ -83,7 +83,7 @@ fun case_5(x: Class?) {
|
|||||||
* ISSUES: KT-30376
|
* ISSUES: KT-30376
|
||||||
*/
|
*/
|
||||||
fun case_6(x: Class?) {
|
fun case_6(x: Class?) {
|
||||||
if (x?.prop_8?.prop_8?.prop_8!!?.prop_8 == null == true) else {
|
if (x?.prop_8?.prop_8?.prop_8!!<!UNNECESSARY_SAFE_CALL!>?.<!>prop_8 == null == true) else {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8
|
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8.prop_8
|
<!DEBUG_INFO_EXPRESSION_TYPE("Class? & Class")!>x<!>.prop_8.prop_8
|
||||||
|
|||||||
+13
@@ -1535,6 +1535,19 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.UNNECESSARY_SAFE_CALL) { firDiagnostic ->
|
||||||
|
UnnecessarySafeCallImpl(
|
||||||
|
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.UNEXPECTED_SAFE_CALL) { firDiagnostic ->
|
||||||
|
UnexpectedSafeCallImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic<*>,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.UNNECESSARY_NOT_NULL_ASSERTION) { firDiagnostic ->
|
add(FirErrors.UNNECESSARY_NOT_NULL_ASSERTION) { firDiagnostic ->
|
||||||
UnnecessaryNotNullAssertionImpl(
|
UnnecessaryNotNullAssertionImpl(
|
||||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||||
|
|||||||
+9
@@ -1087,6 +1087,15 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
abstract val rhs: KtExpression
|
abstract val rhs: KtExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class UnnecessarySafeCall : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = UnnecessarySafeCall::class
|
||||||
|
abstract val receiverType: KtType
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class UnexpectedSafeCall : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = UnexpectedSafeCall::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class UnnecessaryNotNullAssertion : KtFirDiagnostic<KtExpression>() {
|
abstract class UnnecessaryNotNullAssertion : KtFirDiagnostic<KtExpression>() {
|
||||||
override val diagnosticClass get() = UnnecessaryNotNullAssertion::class
|
override val diagnosticClass get() = UnnecessaryNotNullAssertion::class
|
||||||
abstract val receiverType: KtType
|
abstract val receiverType: KtType
|
||||||
|
|||||||
+15
@@ -1754,6 +1754,21 @@ internal class UnsafeOperatorCallImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class UnnecessarySafeCallImpl(
|
||||||
|
override val receiverType: KtType,
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.UnnecessarySafeCall(), KtAbstractFirDiagnostic<PsiElement> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class UnexpectedSafeCallImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.UnexpectedSafeCall(), KtAbstractFirDiagnostic<PsiElement> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class UnnecessaryNotNullAssertionImpl(
|
internal class UnnecessaryNotNullAssertionImpl(
|
||||||
override val receiverType: KtType,
|
override val receiverType: KtType,
|
||||||
firDiagnostic: FirPsiDiagnostic<*>,
|
firDiagnostic: FirPsiDiagnostic<*>,
|
||||||
|
|||||||
Reference in New Issue
Block a user