[FE 1.0] Prohibit using non exhaustive if and when in rhs of elvis expression

^KT-44705
^KT-49349 Fixed
This commit is contained in:
Dmitriy Novozhilov
2021-10-21 12:49:36 +03:00
committed by teamcityserver
parent 06a26a5a74
commit a2b8493f47
16 changed files with 192 additions and 9 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.cfg
import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil.getParentOfType
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.cfg.TailRecursionKind.*
@@ -43,14 +44,10 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.getEnclosingDescriptor
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsResultOfLambda
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.checkers.findDestructuredVariable
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.resolve.calls.util.getDispatchReceiverWithSmartCast
import org.jetbrains.kotlin.resolve.calls.util.hasThisOrNoDispatchReceiver
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
import org.jetbrains.kotlin.resolve.calls.util.*
import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.descriptorUtil.module
@@ -943,6 +940,13 @@ class ControlFlowInformationProviderImpl private constructor(
} else {
checkImplicitCastOnConditionalExpression(element)
}
} else if (!languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNonExhaustiveIfInRhsOfElvis)) {
val parent = element.deparenthesizedParent
if (parent is KtBinaryExpression) {
if (parent.operationToken === KtTokens.ELVIS) {
trace.report(INVALID_IF_AS_EXPRESSION_WARNING.on(element.getIfKeyword()))
}
}
}
}
}
@@ -1036,6 +1040,18 @@ class ControlFlowInformationProviderImpl private constructor(
}
}
}
if (
!usedAsExpression &&
missingCases.isNotEmpty() &&
!languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNonExhaustiveIfInRhsOfElvis)
) {
val parent = element.deparenthesizedParent
if (parent is KtBinaryExpression) {
if (parent.operationToken === KtTokens.ELVIS) {
trace.report(NO_ELSE_IN_WHEN_WARNING.on(element, missingCases))
}
}
}
}
}
}
@@ -1355,4 +1371,13 @@ class ControlFlowInformationProviderImpl private constructor(
|| diagnosticFactory === UNUSED_ANONYMOUS_PARAMETER
|| diagnosticFactory === UNUSED_CHANGED_VALUE
}
private val PsiElement.deparenthesizedParent: PsiElement
get() {
var result = parent
while (result is KtParenthesizedExpression || result is KtLabeledExpression || result is KtAnnotatedExpression) {
result = result.parent
}
return result
}
}
@@ -346,7 +346,10 @@ class ControlFlowProcessor(
builder.jumpOnTrue(afterElvis, expression, builder.getBoundValue(left))
generateInstructions(right)
builder.bindLabel(afterElvis)
mergeValues(listOf(left, right).filterNotNull(), expression)
mergeValues(listOfNotNull(left, right), expression)
if (right != null && languageVersionSettings?.supportsFeature(LanguageFeature.ProhibitNonExhaustiveIfInRhsOfElvis) == true) {
trace.record(USED_AS_EXPRESSION, right, true)
}
} else {
if (!generateCall(expression)) {
generateBothArgumentsAndMark(expression)