[FE 1.0] Support proper DUPLICATE_LABEL_IN_WHEN reporting for deprecated complex boolean expressions
^KT-50385 ^KT-39883
This commit is contained in:
committed by
teamcity
parent
eb753eac83
commit
8a58e98530
+12
@@ -4942,6 +4942,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/constantEvaluator/constant/divideByZero.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("duplicateLabelWithNonTrivialCondition_disabled.kt")
|
||||
public void testDuplicateLabelWithNonTrivialCondition_disabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/constantEvaluator/constant/duplicateLabelWithNonTrivialCondition_disabled.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("duplicateLabelWithNonTrivialCondition_enabled.kt")
|
||||
public void testDuplicateLabelWithNonTrivialCondition_enabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/constantEvaluator/constant/duplicateLabelWithNonTrivialCondition_enabled.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("equals.kt")
|
||||
public void testEquals() throws Exception {
|
||||
|
||||
+12
@@ -4942,6 +4942,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/constantEvaluator/constant/divideByZero.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("duplicateLabelWithNonTrivialCondition_disabled.kt")
|
||||
public void testDuplicateLabelWithNonTrivialCondition_disabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/constantEvaluator/constant/duplicateLabelWithNonTrivialCondition_disabled.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("duplicateLabelWithNonTrivialCondition_enabled.kt")
|
||||
public void testDuplicateLabelWithNonTrivialCondition_enabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/constantEvaluator/constant/duplicateLabelWithNonTrivialCondition_enabled.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("equals.kt")
|
||||
public void testEquals() throws Exception {
|
||||
|
||||
+12
@@ -4942,6 +4942,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/constantEvaluator/constant/divideByZero.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("duplicateLabelWithNonTrivialCondition_disabled.kt")
|
||||
public void testDuplicateLabelWithNonTrivialCondition_disabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/constantEvaluator/constant/duplicateLabelWithNonTrivialCondition_disabled.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("duplicateLabelWithNonTrivialCondition_enabled.kt")
|
||||
public void testDuplicateLabelWithNonTrivialCondition_enabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/constantEvaluator/constant/duplicateLabelWithNonTrivialCondition_enabled.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("equals.kt")
|
||||
public void testEquals() throws Exception {
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.InstructionWithValu
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.MagicKind
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
|
||||
import org.jetbrains.kotlin.contracts.description.canBeRevisited
|
||||
import org.jetbrains.kotlin.contracts.description.isDefinitelyVisited
|
||||
@@ -1321,7 +1322,11 @@ class ControlFlowProcessor(
|
||||
builder.bindLabel(doneLabel)
|
||||
|
||||
mergeValues(branches, expression)
|
||||
WhenChecker.checkDuplicatedLabels(expression, trace)
|
||||
WhenChecker.checkDuplicatedLabels(
|
||||
expression,
|
||||
trace,
|
||||
languageVersionSettings ?: LanguageVersionSettingsImpl.DEFAULT
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitObjectLiteralExpression(expression: KtObjectLiteralExpression) {
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.cfg
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
@@ -357,7 +359,11 @@ object WhenChecker {
|
||||
fun containsNullCase(expression: KtWhenExpression, context: BindingContext) =
|
||||
WhenOnNullableExhaustivenessChecker.getMissingCases(expression, context, true).isEmpty()
|
||||
|
||||
fun checkDuplicatedLabels(expression: KtWhenExpression, trace: BindingTrace) {
|
||||
fun checkDuplicatedLabels(
|
||||
expression: KtWhenExpression,
|
||||
trace: BindingTrace,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
) {
|
||||
if (expression.subjectExpression == null) return
|
||||
|
||||
val checkedTypes = HashSet<Pair<KotlinType, Boolean>>()
|
||||
@@ -407,7 +413,7 @@ object WhenChecker {
|
||||
}
|
||||
false -> {
|
||||
// already found bad constant in previous branches
|
||||
val isTrivial = constant.isTrivial()
|
||||
val isTrivial = constant.isTrivial(constantExpression, languageVersionSettings)
|
||||
if (isTrivial) {
|
||||
// this constant is trivial -> report on first non trivial constant
|
||||
val reportOn = notTrivialBranches.remove(constant)!!
|
||||
@@ -420,7 +426,7 @@ object WhenChecker {
|
||||
}
|
||||
null -> {
|
||||
// met constant for a first time
|
||||
val isTrivial = constant.isTrivial()
|
||||
val isTrivial = constant.isTrivial(constantExpression, languageVersionSettings)
|
||||
checkedConstants[constant] = isTrivial
|
||||
if (!isTrivial) {
|
||||
notTrivialBranches[constant] = constantExpression
|
||||
@@ -446,8 +452,15 @@ object WhenChecker {
|
||||
}
|
||||
}
|
||||
|
||||
private fun CompileTimeConstant<*>.isTrivial(): Boolean {
|
||||
return !usesVariableAsConstant
|
||||
private fun CompileTimeConstant<*>.isTrivial(
|
||||
expression: KtExpression,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
): Boolean {
|
||||
if (usesVariableAsConstant) return false
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.ProhibitSimplificationOfNonTrivialConstBooleanExpressions)) {
|
||||
return !ConstantExpressionEvaluator.isComplexBooleanConstant(expression, this)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun checkDeprecatedWhenSyntax(trace: BindingTrace, expression: KtWhenExpression) {
|
||||
|
||||
+15
-6
@@ -51,7 +51,6 @@ import org.jetbrains.kotlin.types.isError
|
||||
import org.jetbrains.kotlin.types.typeUtil.isBoolean
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
|
||||
@@ -369,6 +368,17 @@ class ConstantExpressionEvaluator(
|
||||
KotlinBuiltIns.isArray(type) -> isTypeParameterOrArrayOfTypeParameter(type.arguments.singleOrNull()?.type)
|
||||
else -> type.constructor.declarationDescriptor is TypeParameterDescriptor
|
||||
}
|
||||
|
||||
fun isComplexBooleanConstant(
|
||||
expression: KtExpression,
|
||||
constant: CompileTimeConstant<*>
|
||||
): Boolean {
|
||||
if (constant.isError) return false
|
||||
val constantValue = constant.toConstantValue(constant.moduleDescriptor.builtIns.booleanType)
|
||||
if (!constantValue.getType(constant.moduleDescriptor).isBoolean()) return false
|
||||
if (expression is KtConstantExpression || constant.parameters.usesVariableAsConstant) return false
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,15 +419,13 @@ private class ConstantExpressionEvaluatorVisitor(
|
||||
return null
|
||||
}
|
||||
|
||||
@Suppress("warnings")
|
||||
private fun shouldSkipComplexBooleanValue(
|
||||
expression: KtExpression,
|
||||
constant: CompileTimeConstant<*>
|
||||
): Boolean {
|
||||
if (constant.isError) return false
|
||||
val constantValue = constant.toConstantValue(builtIns.booleanType)
|
||||
if (!constantValue.getType(constantExpressionEvaluator.module).isBoolean()) return false
|
||||
if (expression is KtConstantExpression || constant.parameters.usesVariableAsConstant) return false
|
||||
if (!ConstantExpressionEvaluator.isComplexBooleanConstant(expression, constant)) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitSimplificationOfNonTrivialConstBooleanExpressions)) {
|
||||
return true
|
||||
@@ -430,6 +438,7 @@ private class ConstantExpressionEvaluatorVisitor(
|
||||
parent is KtWhenConditionWithExpression ||
|
||||
parent is KtContainerNode && (parent.parent is KtWhileExpression || parent.parent is KtDoWhileExpression)
|
||||
) {
|
||||
val constantValue = constant.toConstantValue(builtIns.booleanType)
|
||||
trace.report(Errors.NON_TRIVIAL_BOOLEAN_CONSTANT.on(expression, constantValue.value as Boolean))
|
||||
}
|
||||
return false
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// LANGUAGE: -ProhibitSimplificationOfNonTrivialConstBooleanExpressions
|
||||
|
||||
const val myF = false
|
||||
const val myT = true
|
||||
|
||||
fun test(someBoolean: Boolean) {
|
||||
val s = when (someBoolean) {
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>true || true<!> -> 1
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>false && false<!> -> 2
|
||||
true -> 3
|
||||
false -> 4
|
||||
}
|
||||
}
|
||||
|
||||
fun test_2(someBoolean: Boolean) {
|
||||
val s = <!NO_ELSE_IN_WHEN!>when<!> (someBoolean) {
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>true || true<!> -> 1
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>false && false<!> -> 2
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// LANGUAGE: -ProhibitSimplificationOfNonTrivialConstBooleanExpressions
|
||||
|
||||
const val myF = false
|
||||
const val myT = true
|
||||
|
||||
fun test(someBoolean: Boolean) {
|
||||
val s = when (someBoolean) {
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING, DUPLICATE_LABEL_IN_WHEN, NON_TRIVIAL_BOOLEAN_CONSTANT!>true || true<!> -> 1
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING, DUPLICATE_LABEL_IN_WHEN, NON_TRIVIAL_BOOLEAN_CONSTANT!>false && false<!> -> 2
|
||||
true -> 3
|
||||
false -> 4
|
||||
}
|
||||
}
|
||||
|
||||
fun test_2(someBoolean: Boolean) {
|
||||
val s = when (someBoolean) {
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING, NON_TRIVIAL_BOOLEAN_CONSTANT!>true || true<!> -> 1
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING, NON_TRIVIAL_BOOLEAN_CONSTANT!>false && false<!> -> 2
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package
|
||||
|
||||
public const val myF: kotlin.Boolean = false
|
||||
public const val myT: kotlin.Boolean = true
|
||||
public fun test(/*0*/ someBoolean: kotlin.Boolean): kotlin.Unit
|
||||
public fun test_2(/*0*/ someBoolean: kotlin.Boolean): kotlin.Unit
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// FIR_IDENTICAL
|
||||
// LANGUAGE: +ProhibitSimplificationOfNonTrivialConstBooleanExpressions
|
||||
|
||||
const val myF = false
|
||||
const val myT = true
|
||||
|
||||
fun test(someBoolean: Boolean) {
|
||||
val s = when (someBoolean) {
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>true || true<!> -> 1
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>false && false<!> -> 2
|
||||
true -> 3
|
||||
false -> 4
|
||||
}
|
||||
}
|
||||
|
||||
fun test_2(someBoolean: Boolean) {
|
||||
val s = <!NO_ELSE_IN_WHEN!>when<!> (someBoolean) {
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>true || true<!> -> 1
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>false && false<!> -> 2
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package
|
||||
|
||||
public const val myF: kotlin.Boolean = false
|
||||
public const val myT: kotlin.Boolean = true
|
||||
public fun test(/*0*/ someBoolean: kotlin.Boolean): kotlin.Unit
|
||||
public fun test_2(/*0*/ someBoolean: kotlin.Boolean): kotlin.Unit
|
||||
|
||||
Generated
+12
@@ -4948,6 +4948,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/constantEvaluator/constant/divideByZero.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("duplicateLabelWithNonTrivialCondition_disabled.kt")
|
||||
public void testDuplicateLabelWithNonTrivialCondition_disabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/constantEvaluator/constant/duplicateLabelWithNonTrivialCondition_disabled.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("duplicateLabelWithNonTrivialCondition_enabled.kt")
|
||||
public void testDuplicateLabelWithNonTrivialCondition_enabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/constantEvaluator/constant/duplicateLabelWithNonTrivialCondition_enabled.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("equals.kt")
|
||||
public void testEquals() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user