[FE 1.0] Prohibit confusing syntax inside when branches
^KT-48385 Fixed
This commit is contained in:
committed by
teamcityserver
parent
653fc85461
commit
1513e739c6
+18
@@ -32095,6 +32095,24 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/when/CommaInWhenConditionWithoutArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedSyntaxInConditionsNoSubject.kt")
|
||||
public void testDeprecatedSyntaxInConditionsNoSubject() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditionsNoSubject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedSyntaxInConditions_after.kt")
|
||||
public void testDeprecatedSyntaxInConditions_after() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_after.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedSyntaxInConditions_before.kt")
|
||||
public void testDeprecatedSyntaxInConditions_before() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_before.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DuplicatedLabels.kt")
|
||||
public void testDuplicatedLabels() throws Exception {
|
||||
|
||||
+18
@@ -32095,6 +32095,24 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/when/CommaInWhenConditionWithoutArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedSyntaxInConditionsNoSubject.kt")
|
||||
public void testDeprecatedSyntaxInConditionsNoSubject() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditionsNoSubject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedSyntaxInConditions_after.kt")
|
||||
public void testDeprecatedSyntaxInConditions_after() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_after.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedSyntaxInConditions_before.kt")
|
||||
public void testDeprecatedSyntaxInConditions_before() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_before.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DuplicatedLabels.kt")
|
||||
public void testDuplicatedLabels() throws Exception {
|
||||
|
||||
+18
@@ -32095,6 +32095,24 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/when/CommaInWhenConditionWithoutArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedSyntaxInConditionsNoSubject.kt")
|
||||
public void testDeprecatedSyntaxInConditionsNoSubject() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditionsNoSubject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedSyntaxInConditions_after.kt")
|
||||
public void testDeprecatedSyntaxInConditions_after() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_after.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedSyntaxInConditions_before.kt")
|
||||
public void testDeprecatedSyntaxInConditions_before() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_before.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DuplicatedLabels.kt")
|
||||
public void testDuplicatedLabels() throws Exception {
|
||||
|
||||
@@ -997,6 +997,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtElement> SENSELESS_NULL_IN_WHEN = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory0<PsiElement> INVALID_IF_AS_EXPRESSION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactoryForDeprecation0<PsiElement> CONFUSING_BRANCH_CONDITION = DiagnosticFactoryForDeprecation0.create(LanguageFeature.ProhibitConfusingSyntaxInWhenBranches);
|
||||
|
||||
// Nullability
|
||||
|
||||
|
||||
+1
@@ -833,6 +833,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(SENSELESS_NULL_IN_WHEN, "Expression under 'when' is never equal to null");
|
||||
|
||||
MAP.put(INVALID_IF_AS_EXPRESSION, "'if' must have both main and 'else' branches if used as an expression");
|
||||
MAP.put(CONFUSING_BRANCH_CONDITION, "The logical expressions may be understood ambiguously in when with subject branches. Please wrap it with parenthesis");
|
||||
|
||||
MAP.put(OVERRIDING_FINAL_MEMBER, "''{0}'' in ''{1}'' is final and cannot be overridden", NAME, NAME);
|
||||
MAP.put(CANNOT_WEAKEN_ACCESS_PRIVILEGE, "Cannot weaken access privilege ''{0}'' for ''{1}'' in ''{2}''", VISIBILITY, NAME, NAME);
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.resolve.checkers
|
||||
|
||||
import com.intellij.psi.tree.TokenSet
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.CONFUSING_BRANCH_CONDITION
|
||||
import org.jetbrains.kotlin.lexer.KtTokens.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
|
||||
object ConfusingWhenBranchSyntaxChecker {
|
||||
private val prohibitedTokens = TokenSet.create(
|
||||
IN_KEYWORD, NOT_IN,
|
||||
LT, LTEQ, GT, GTEQ,
|
||||
EQEQ, EXCLEQ, EQEQEQ, EXCLEQEQEQ,
|
||||
ANDAND, OROR
|
||||
)
|
||||
|
||||
fun check(whenExpression: KtWhenExpression, languageVersionSettings: LanguageVersionSettings, trace: BindingTrace) {
|
||||
if (whenExpression.subjectExpression == null && whenExpression.subjectVariable == null) return
|
||||
for (entry in whenExpression.entries) {
|
||||
for (condition in entry.conditions) {
|
||||
checkCondition(condition, languageVersionSettings, trace)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkCondition(condition: KtWhenCondition, languageVersionSettings: LanguageVersionSettings, trace: BindingTrace) {
|
||||
when (condition) {
|
||||
is KtWhenConditionWithExpression -> checkConditionExpression(condition.expression, languageVersionSettings, trace)
|
||||
is KtWhenConditionInRange -> checkConditionExpression(condition.rangeExpression, languageVersionSettings, trace)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkConditionExpression(rawExpression: KtExpression?, languageVersionSettings: LanguageVersionSettings, trace: BindingTrace) {
|
||||
if (rawExpression == null) return
|
||||
if (rawExpression is KtParenthesizedExpression) return
|
||||
val shouldReport = when (val expression = KtPsiUtil.safeDeparenthesize(rawExpression)) {
|
||||
is KtIsExpression -> true
|
||||
is KtBinaryExpression -> expression.operationToken in prohibitedTokens
|
||||
else -> false
|
||||
}
|
||||
if (shouldReport) {
|
||||
trace.report(CONFUSING_BRANCH_CONDITION.on(languageVersionSettings, rawExpression))
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.calls.checkers.RttiOperation
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency.INDEPENDENT
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.*
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.checkers.ConfusingWhenBranchSyntaxChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.PrimitiveNumericComparisonCallChecker
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind
|
||||
@@ -249,6 +250,8 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
||||
val branchesType = branchesTypeInfo.type ?: return noTypeInfo(resultDataFlowInfo)
|
||||
val resultType = components.dataFlowAnalyzer.checkType(branchesType, expression, contextWithExpectedType)
|
||||
|
||||
ConfusingWhenBranchSyntaxChecker.check(expression, contextWithExpectedType.languageVersionSettings, trace)
|
||||
|
||||
return createTypeInfo(resultType, resultDataFlowInfo, branchesTypeInfo.jumpOutPossible, contextWithExpectedType.dataFlowInfo)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
fun foo(arg: Boolean): String {
|
||||
// Must be exhaustive
|
||||
return <!NO_ELSE_IN_WHEN!>when<!>(arg) {
|
||||
2 == 2 -> "truth"
|
||||
2 == 1 -> "falsehood"
|
||||
(2 == 2) -> "truth"
|
||||
(2 == 1) -> "falsehood"
|
||||
}
|
||||
}
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// LANGUAGE: +ProhibitConfusingSyntaxInWhenBranches
|
||||
// DIAGNOSTICS: -INCOMPATIBLE_TYPES, -NON_EXHAUSTIVE_WHEN_STATEMENT, -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE
|
||||
// ISSUE: KT-48385
|
||||
|
||||
operator fun Boolean.plus(other: Boolean): Boolean = true
|
||||
operator fun Boolean.minus(other: Boolean): Boolean = true
|
||||
operator fun Boolean.times(other: Boolean): Boolean = true
|
||||
operator fun Boolean.div(other: Boolean): Boolean = true
|
||||
operator fun Boolean.rem(other: Boolean): Boolean = true
|
||||
|
||||
operator fun Boolean.rangeTo(other: Boolean): Boolean = true
|
||||
|
||||
fun Boolean.id(): Boolean = true
|
||||
|
||||
operator fun Boolean.inc(): Boolean = true
|
||||
operator fun Boolean.dec(): Boolean = true
|
||||
|
||||
operator fun Boolean.plusAssign(other: Boolean) {}
|
||||
operator fun Boolean.minusAssign(other: Boolean) {}
|
||||
operator fun Boolean.timesAssign(other: Boolean) {}
|
||||
operator fun Boolean.divAssign(other: Boolean) {}
|
||||
operator fun Boolean.remAssign(other: Boolean) {}
|
||||
|
||||
operator fun Any?.contains(other: Any): Boolean = false
|
||||
|
||||
fun testWithSubject_ok(x: Boolean, y: Boolean?, any: Any, z: Boolean) {
|
||||
when {
|
||||
x.id() -> {}
|
||||
<!CONDITION_TYPE_MISMATCH!>y?.id()<!> -> {}
|
||||
<!CONDITION_TYPE_MISMATCH!>any as? Boolean<!> -> {}
|
||||
any as Boolean -> {}
|
||||
x * x -> {}
|
||||
x / x -> {}
|
||||
x % x -> {}
|
||||
x + x -> {}
|
||||
x - x -> {}
|
||||
x..x -> {}
|
||||
<!CONDITION_TYPE_MISMATCH!>y<!> -> {}
|
||||
y ?: x -> {}
|
||||
x in x -> {}
|
||||
x !in x -> {}
|
||||
x is String -> {}
|
||||
x !is String -> {}
|
||||
x <!OVERLOAD_RESOLUTION_AMBIGUITY!><<!> x -> {}
|
||||
x <!OVERLOAD_RESOLUTION_AMBIGUITY!>><!> x -> {}
|
||||
x <!OVERLOAD_RESOLUTION_AMBIGUITY!><=<!> x -> {}
|
||||
x <!OVERLOAD_RESOLUTION_AMBIGUITY!>>=<!> x -> {}
|
||||
x == x -> {}
|
||||
x != x -> {}
|
||||
x === x -> {}
|
||||
x !== x -> {}
|
||||
x && x -> {}
|
||||
x || x -> {}
|
||||
}
|
||||
|
||||
var b = z
|
||||
when (z) {
|
||||
b++ -> {}
|
||||
b-- -> {}
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
// LANGUAGE: +ProhibitConfusingSyntaxInWhenBranches
|
||||
// DIAGNOSTICS: -INCOMPATIBLE_TYPES, -NON_EXHAUSTIVE_WHEN_STATEMENT, -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE
|
||||
// ISSUE: KT-48385
|
||||
|
||||
operator fun Boolean.plus(other: Boolean): Boolean = true
|
||||
operator fun Boolean.minus(other: Boolean): Boolean = true
|
||||
operator fun Boolean.times(other: Boolean): Boolean = true
|
||||
operator fun Boolean.div(other: Boolean): Boolean = true
|
||||
operator fun Boolean.rem(other: Boolean): Boolean = true
|
||||
|
||||
operator fun Boolean.rangeTo(other: Boolean): Boolean = true
|
||||
|
||||
fun Boolean.id(): Boolean = true
|
||||
|
||||
operator fun Boolean.inc(): Boolean = true
|
||||
operator fun Boolean.dec(): Boolean = true
|
||||
|
||||
operator fun Boolean.plusAssign(other: Boolean) {}
|
||||
operator fun Boolean.minusAssign(other: Boolean) {}
|
||||
operator fun Boolean.timesAssign(other: Boolean) {}
|
||||
operator fun Boolean.divAssign(other: Boolean) {}
|
||||
operator fun Boolean.remAssign(other: Boolean) {}
|
||||
|
||||
operator fun Any?.contains(other: Any): Boolean = false
|
||||
|
||||
fun testWithSubject_ok(x: Boolean, y: Boolean?, any: Any, z: Boolean) {
|
||||
when {
|
||||
x.id() -> {}
|
||||
<!TYPE_MISMATCH!>y?.id()<!> -> {}
|
||||
<!TYPE_MISMATCH!>any as? Boolean<!> -> {}
|
||||
any as Boolean -> {}
|
||||
x * x -> {}
|
||||
x / x -> {}
|
||||
x % x -> {}
|
||||
x + x -> {}
|
||||
x - x -> {}
|
||||
x..x -> {}
|
||||
<!TYPE_MISMATCH!>y<!> -> {}
|
||||
y ?: x -> {}
|
||||
x in x -> {}
|
||||
x !in x -> {}
|
||||
x is String -> {}
|
||||
x !is String -> {}
|
||||
x <!OVERLOAD_RESOLUTION_AMBIGUITY!><<!> x -> {}
|
||||
x <!OVERLOAD_RESOLUTION_AMBIGUITY!>><!> x -> {}
|
||||
x <!OVERLOAD_RESOLUTION_AMBIGUITY!><=<!> x -> {}
|
||||
x <!OVERLOAD_RESOLUTION_AMBIGUITY!>>=<!> x -> {}
|
||||
x == x -> {}
|
||||
x != x -> {}
|
||||
<!DEPRECATED_IDENTITY_EQUALS!>x === x<!> -> {}
|
||||
<!DEPRECATED_IDENTITY_EQUALS!>x !== x<!> -> {}
|
||||
x && x -> {}
|
||||
x || x -> {}
|
||||
}
|
||||
|
||||
var b = z
|
||||
when (z) {
|
||||
b++ -> {}
|
||||
b-- -> {}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package
|
||||
|
||||
public fun testWithSubject_ok(/*0*/ x: kotlin.Boolean, /*1*/ y: kotlin.Boolean?, /*2*/ any: kotlin.Any, /*3*/ z: kotlin.Boolean): kotlin.Unit
|
||||
public operator fun kotlin.Any?.contains(/*0*/ other: kotlin.Any): kotlin.Boolean
|
||||
public operator fun kotlin.Boolean.dec(): kotlin.Boolean
|
||||
public operator fun kotlin.Boolean.div(/*0*/ other: kotlin.Boolean): kotlin.Boolean
|
||||
public operator fun kotlin.Boolean.divAssign(/*0*/ other: kotlin.Boolean): kotlin.Unit
|
||||
public fun kotlin.Boolean.id(): kotlin.Boolean
|
||||
public operator fun kotlin.Boolean.inc(): kotlin.Boolean
|
||||
public operator fun kotlin.Boolean.minus(/*0*/ other: kotlin.Boolean): kotlin.Boolean
|
||||
public operator fun kotlin.Boolean.minusAssign(/*0*/ other: kotlin.Boolean): kotlin.Unit
|
||||
public operator fun kotlin.Boolean.plus(/*0*/ other: kotlin.Boolean): kotlin.Boolean
|
||||
public operator fun kotlin.Boolean.plusAssign(/*0*/ other: kotlin.Boolean): kotlin.Unit
|
||||
public operator fun kotlin.Boolean.rangeTo(/*0*/ other: kotlin.Boolean): kotlin.Boolean
|
||||
public operator fun kotlin.Boolean.rem(/*0*/ other: kotlin.Boolean): kotlin.Boolean
|
||||
public operator fun kotlin.Boolean.remAssign(/*0*/ other: kotlin.Boolean): kotlin.Unit
|
||||
public operator fun kotlin.Boolean.times(/*0*/ other: kotlin.Boolean): kotlin.Boolean
|
||||
public operator fun kotlin.Boolean.timesAssign(/*0*/ other: kotlin.Boolean): kotlin.Unit
|
||||
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
// LANGUAGE: +ProhibitConfusingSyntaxInWhenBranches
|
||||
// DIAGNOSTICS: -INCOMPATIBLE_TYPES, -NON_EXHAUSTIVE_WHEN_STATEMENT, -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE
|
||||
// ISSUE: KT-48385
|
||||
|
||||
interface A {
|
||||
operator fun plus(other: A): A
|
||||
operator fun minus(other: A): A
|
||||
operator fun times(other: A): A
|
||||
operator fun div(other: A): A
|
||||
operator fun rem(other: A): A
|
||||
|
||||
operator fun rangeTo(other: A): A
|
||||
|
||||
operator fun compareTo(other: A): Int
|
||||
|
||||
fun id(): A
|
||||
}
|
||||
|
||||
interface B {
|
||||
operator fun inc(): B
|
||||
operator fun dec(): B
|
||||
|
||||
operator fun plusAssign(other: B)
|
||||
operator fun minusAssign(other: B)
|
||||
operator fun timesAssign(other: B)
|
||||
operator fun divAssign(other: B)
|
||||
operator fun remAssign(other: B)
|
||||
}
|
||||
|
||||
operator fun Any?.contains(other: Any): Boolean = false
|
||||
|
||||
fun testWithSubject_ok(x: A, y: A?, any: Any, z: B) {
|
||||
when (x) {
|
||||
x.id() -> {}
|
||||
y?.id() -> {}
|
||||
any as? A -> {}
|
||||
any as A -> {}
|
||||
x * x -> {}
|
||||
x / x -> {}
|
||||
x % x -> {}
|
||||
x + x -> {}
|
||||
x - x -> {}
|
||||
x..x -> {}
|
||||
y -> {}
|
||||
y ?: x -> {}
|
||||
}
|
||||
|
||||
var b = z
|
||||
when (z) {
|
||||
b++ -> {}
|
||||
b-- -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_1(x: A) {
|
||||
// bad
|
||||
when (x) {
|
||||
x in x -> {}
|
||||
x !in x -> {}
|
||||
x is String -> {}
|
||||
x !is String -> {}
|
||||
x < x -> {}
|
||||
x > x -> {}
|
||||
x <= x -> {}
|
||||
x >= x -> {}
|
||||
x == x -> {}
|
||||
x != x -> {}
|
||||
x === x -> {}
|
||||
x !== x -> {}
|
||||
}
|
||||
// ok
|
||||
when (x) {
|
||||
(x in x) -> {}
|
||||
(x !in x) -> {}
|
||||
(x is String) -> {}
|
||||
(x !is String) -> {}
|
||||
(x < x) -> {}
|
||||
(x > x) -> {}
|
||||
(x <= x) -> {}
|
||||
(x >= x) -> {}
|
||||
(x == x) -> {}
|
||||
(x != x) -> {}
|
||||
(x === x) -> {}
|
||||
(x !== x) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_2(b: Boolean) {
|
||||
// bad
|
||||
when (b) {
|
||||
b && b -> {}
|
||||
b || b -> {}
|
||||
}
|
||||
// ok
|
||||
when (b) {
|
||||
(b && b) -> {}
|
||||
(b || b) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_3(a: Array<Any>) {
|
||||
// bad
|
||||
when (a) {
|
||||
<!SYNTAX!><!SYNTAX!><!>*<!>a <!SYNTAX!><!>-> {}
|
||||
}
|
||||
// also bad
|
||||
when (a) {
|
||||
(<!UNRESOLVED_REFERENCE!><!SYNTAX!><!>*<!>a<!SYNTAX!>)<!><!SYNTAX!><!> <!SYNTAX!><!>-> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_4(b: B) {
|
||||
var x = b
|
||||
// bad
|
||||
when (b) {
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>x = b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b += b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b -= b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b *= b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b /= b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b %= b<!> -> {}
|
||||
}
|
||||
// also bad
|
||||
when (b) {
|
||||
<!EXPRESSION_EXPECTED!>(x = b)<!> -> {}
|
||||
<!EXPRESSION_EXPECTED!>(b += b)<!> -> {}
|
||||
<!EXPRESSION_EXPECTED!>(b -= b)<!> -> {}
|
||||
<!EXPRESSION_EXPECTED!>(b *= b)<!> -> {}
|
||||
<!EXPRESSION_EXPECTED!>(b /= b)<!> -> {}
|
||||
<!EXPRESSION_EXPECTED!>(b %= b)<!> -> {}
|
||||
}
|
||||
}
|
||||
|
||||
// range
|
||||
|
||||
fun testWithRange_ok(x: A, y: A?, any: Any, z: B) {
|
||||
when (x) {
|
||||
in x.id() -> {}
|
||||
in y?.id() -> {}
|
||||
in any as? A -> {}
|
||||
in any as A -> {}
|
||||
in x * x -> {}
|
||||
in x / x -> {}
|
||||
in x % x -> {}
|
||||
in x + x -> {}
|
||||
in x - x -> {}
|
||||
in x..x -> {}
|
||||
in y -> {}
|
||||
in y ?: x -> {}
|
||||
}
|
||||
|
||||
var b = z
|
||||
when (z) {
|
||||
in b++ -> {}
|
||||
in b-- -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_1(x: A) {
|
||||
// bad
|
||||
when (x) {
|
||||
in x in x -> {}
|
||||
in x !in x -> {}
|
||||
in x is String -> {}
|
||||
in x !is String -> {}
|
||||
in x < x -> {}
|
||||
in x > x -> {}
|
||||
in x <= x -> {}
|
||||
in x >= x -> {}
|
||||
in x == x -> {}
|
||||
in x != x -> {}
|
||||
in x === x -> {}
|
||||
in x !== x -> {}
|
||||
}
|
||||
// ok
|
||||
when (x) {
|
||||
in (x in x) -> {}
|
||||
in (x !in x) -> {}
|
||||
in (x is String) -> {}
|
||||
in (x !is String) -> {}
|
||||
in (x < x) -> {}
|
||||
in (x > x) -> {}
|
||||
in (x <= x) -> {}
|
||||
in (x >= x) -> {}
|
||||
in (x == x) -> {}
|
||||
in (x != x) -> {}
|
||||
in (x === x) -> {}
|
||||
in (x !== x) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_2(b: Boolean) {
|
||||
// bad
|
||||
when (b) {
|
||||
in b && b -> {}
|
||||
in b || b -> {}
|
||||
}
|
||||
// ok
|
||||
when (b) {
|
||||
in (b && b) -> {}
|
||||
in (b || b) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_3(a: Array<Any>) {
|
||||
// bad
|
||||
when (a) {
|
||||
in<!SYNTAX!><!> <!SYNTAX!>*<!>a <!SYNTAX!><!>-> {}
|
||||
}
|
||||
// also bad
|
||||
when (a) {
|
||||
in (<!UNRESOLVED_REFERENCE!><!SYNTAX!><!>*<!>a<!SYNTAX!>)<!><!SYNTAX!><!> <!SYNTAX!><!>-> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_4(b: B) {
|
||||
var x = b
|
||||
// bad
|
||||
when (b) {
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>x = b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b += b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b -= b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b *= b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b /= b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b %= b<!> -> {}
|
||||
}
|
||||
// also bad
|
||||
when (b) {
|
||||
in <!EXPRESSION_EXPECTED!>(x = b)<!> -> {}
|
||||
in <!EXPRESSION_EXPECTED!>(b += b)<!> -> {}
|
||||
in <!EXPRESSION_EXPECTED!>(b -= b)<!> -> {}
|
||||
in <!EXPRESSION_EXPECTED!>(b *= b)<!> -> {}
|
||||
in <!EXPRESSION_EXPECTED!>(b /= b)<!> -> {}
|
||||
in <!EXPRESSION_EXPECTED!>(b %= b)<!> -> {}
|
||||
}
|
||||
}
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
// LANGUAGE: +ProhibitConfusingSyntaxInWhenBranches
|
||||
// DIAGNOSTICS: -INCOMPATIBLE_TYPES, -NON_EXHAUSTIVE_WHEN_STATEMENT, -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE
|
||||
// ISSUE: KT-48385
|
||||
|
||||
interface A {
|
||||
operator fun plus(other: A): A
|
||||
operator fun minus(other: A): A
|
||||
operator fun times(other: A): A
|
||||
operator fun div(other: A): A
|
||||
operator fun rem(other: A): A
|
||||
|
||||
operator fun rangeTo(other: A): A
|
||||
|
||||
operator fun compareTo(other: A): Int
|
||||
|
||||
fun id(): A
|
||||
}
|
||||
|
||||
interface B {
|
||||
operator fun inc(): B
|
||||
operator fun dec(): B
|
||||
|
||||
operator fun plusAssign(other: B)
|
||||
operator fun minusAssign(other: B)
|
||||
operator fun timesAssign(other: B)
|
||||
operator fun divAssign(other: B)
|
||||
operator fun remAssign(other: B)
|
||||
}
|
||||
|
||||
operator fun Any?.contains(other: Any): Boolean = false
|
||||
|
||||
fun testWithSubject_ok(x: A, y: A?, any: Any, z: B) {
|
||||
when (x) {
|
||||
x.id() -> {}
|
||||
y?.id() -> {}
|
||||
any as? A -> {}
|
||||
any as A -> {}
|
||||
x * x -> {}
|
||||
x / x -> {}
|
||||
x % x -> {}
|
||||
x + x -> {}
|
||||
x - x -> {}
|
||||
x..x -> {}
|
||||
y -> {}
|
||||
y ?: x -> {}
|
||||
}
|
||||
|
||||
var b = z
|
||||
when (z) {
|
||||
b++ -> {}
|
||||
b-- -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_1(x: A) {
|
||||
// bad
|
||||
when (x) {
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>x in x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>x !in x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>x is String<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>x !is String<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>x < x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>x > x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>x <= x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>x >= x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>x == x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>x != x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>x === x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>x !== x<!> -> {}
|
||||
}
|
||||
// ok
|
||||
when (x) {
|
||||
(x in x) -> {}
|
||||
(x !in x) -> {}
|
||||
(x is String) -> {}
|
||||
(x !is String) -> {}
|
||||
(x < x) -> {}
|
||||
(x > x) -> {}
|
||||
(x <= x) -> {}
|
||||
(x >= x) -> {}
|
||||
(x == x) -> {}
|
||||
(x != x) -> {}
|
||||
(x === x) -> {}
|
||||
(x !== x) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_2(b: Boolean) {
|
||||
// bad
|
||||
when (b) {
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>b && b<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_ERROR!>b || b<!> -> {}
|
||||
}
|
||||
// ok
|
||||
when (b) {
|
||||
(b && b) -> {}
|
||||
(b || b) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_3(a: Array<Any>) {
|
||||
// bad
|
||||
when (a) {
|
||||
<!SYNTAX!><!SYNTAX!><!>*<!>a <!SYNTAX!><!>-> {}
|
||||
}
|
||||
// also bad
|
||||
when (a) {
|
||||
(<!DEBUG_INFO_MISSING_UNRESOLVED!><!SYNTAX!><!>*<!>a<!SYNTAX!>)<!><!SYNTAX!><!> <!SYNTAX!><!>-> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_4(b: B) {
|
||||
var x = b
|
||||
// bad
|
||||
when (b) {
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>x = b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b += b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b -= b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b *= b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b /= b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b %= b<!> -> {}
|
||||
}
|
||||
// also bad
|
||||
when (b) {
|
||||
(<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>x = b<!>) -> {}
|
||||
(<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b += b<!>) -> {}
|
||||
(<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b -= b<!>) -> {}
|
||||
(<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b *= b<!>) -> {}
|
||||
(<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b /= b<!>) -> {}
|
||||
(<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b %= b<!>) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
// range
|
||||
|
||||
fun testWithRange_ok(x: A, y: A?, any: Any, z: B) {
|
||||
when (x) {
|
||||
in x.id() -> {}
|
||||
in y?.id() -> {}
|
||||
in any as? A -> {}
|
||||
in any as A -> {}
|
||||
in x * x -> {}
|
||||
in x / x -> {}
|
||||
in x % x -> {}
|
||||
in x + x -> {}
|
||||
in x - x -> {}
|
||||
in x..x -> {}
|
||||
in y -> {}
|
||||
in y ?: x -> {}
|
||||
}
|
||||
|
||||
var b = z
|
||||
when (z) {
|
||||
in b++ -> {}
|
||||
in b-- -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_1(x: A) {
|
||||
// bad
|
||||
when (x) {
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x in x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x !in x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x is String<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x !is String<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x < x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x > x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x <= x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x >= x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x == x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x != x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x === x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>x !== x<!> -> {}
|
||||
}
|
||||
// ok
|
||||
when (x) {
|
||||
in (x in x) -> {}
|
||||
in (x !in x) -> {}
|
||||
in (x is String) -> {}
|
||||
in (x !is String) -> {}
|
||||
in (x < x) -> {}
|
||||
in (x > x) -> {}
|
||||
in (x <= x) -> {}
|
||||
in (x >= x) -> {}
|
||||
in (x == x) -> {}
|
||||
in (x != x) -> {}
|
||||
in (x === x) -> {}
|
||||
in (x !== x) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_2(b: Boolean) {
|
||||
// bad
|
||||
when (b) {
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>b && b<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_ERROR!>b || b<!> -> {}
|
||||
}
|
||||
// ok
|
||||
when (b) {
|
||||
in (b && b) -> {}
|
||||
in (b || b) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_3(a: Array<Any>) {
|
||||
// bad
|
||||
when (a) {
|
||||
in<!SYNTAX!><!> <!SYNTAX!>*<!>a <!SYNTAX!><!>-> {}
|
||||
}
|
||||
// also bad
|
||||
when (a) {
|
||||
in (<!DEBUG_INFO_MISSING_UNRESOLVED!><!SYNTAX!><!>*<!>a<!SYNTAX!>)<!><!SYNTAX!><!> <!SYNTAX!><!>-> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_4(b: B) {
|
||||
var x = b
|
||||
// bad
|
||||
when (b) {
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>x = b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b += b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b -= b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b *= b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b /= b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b %= b<!> -> {}
|
||||
}
|
||||
// also bad
|
||||
when (b) {
|
||||
in (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>x = b<!>) -> {}
|
||||
in (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b += b<!>) -> {}
|
||||
in (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b -= b<!>) -> {}
|
||||
in (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b *= b<!>) -> {}
|
||||
in (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b /= b<!>) -> {}
|
||||
in (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b %= b<!>) -> {}
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package
|
||||
|
||||
public fun testWithRange_bad_1(/*0*/ x: A): kotlin.Unit
|
||||
public fun testWithRange_bad_2(/*0*/ b: kotlin.Boolean): kotlin.Unit
|
||||
public fun testWithRange_bad_3(/*0*/ a: kotlin.Array<kotlin.Any>): kotlin.Unit
|
||||
public fun testWithRange_bad_4(/*0*/ b: B): kotlin.Unit
|
||||
public fun testWithRange_ok(/*0*/ x: A, /*1*/ y: A?, /*2*/ any: kotlin.Any, /*3*/ z: B): kotlin.Unit
|
||||
public fun testWithSubject_bad_1(/*0*/ x: A): kotlin.Unit
|
||||
public fun testWithSubject_bad_2(/*0*/ b: kotlin.Boolean): kotlin.Unit
|
||||
public fun testWithSubject_bad_3(/*0*/ a: kotlin.Array<kotlin.Any>): kotlin.Unit
|
||||
public fun testWithSubject_bad_4(/*0*/ b: B): kotlin.Unit
|
||||
public fun testWithSubject_ok(/*0*/ x: A, /*1*/ y: A?, /*2*/ any: kotlin.Any, /*3*/ z: B): kotlin.Unit
|
||||
public operator fun kotlin.Any?.contains(/*0*/ other: kotlin.Any): kotlin.Boolean
|
||||
|
||||
public interface A {
|
||||
public abstract operator fun compareTo(/*0*/ other: A): kotlin.Int
|
||||
public abstract operator fun div(/*0*/ other: A): A
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public abstract fun id(): A
|
||||
public abstract operator fun minus(/*0*/ other: A): A
|
||||
public abstract operator fun plus(/*0*/ other: A): A
|
||||
public abstract operator fun rangeTo(/*0*/ other: A): A
|
||||
public abstract operator fun rem(/*0*/ other: A): A
|
||||
public abstract operator fun times(/*0*/ other: A): A
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface B {
|
||||
public abstract operator fun dec(): B
|
||||
public abstract operator fun divAssign(/*0*/ other: B): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public abstract operator fun inc(): B
|
||||
public abstract operator fun minusAssign(/*0*/ other: B): kotlin.Unit
|
||||
public abstract operator fun plusAssign(/*0*/ other: B): kotlin.Unit
|
||||
public abstract operator fun remAssign(/*0*/ other: B): kotlin.Unit
|
||||
public abstract operator fun timesAssign(/*0*/ other: B): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
// LANGUAGE: -ProhibitConfusingSyntaxInWhenBranches
|
||||
// DIAGNOSTICS: -INCOMPATIBLE_TYPES, -NON_EXHAUSTIVE_WHEN_STATEMENT, -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE
|
||||
// ISSUE: KT-48385
|
||||
|
||||
interface A {
|
||||
operator fun plus(other: A): A
|
||||
operator fun minus(other: A): A
|
||||
operator fun times(other: A): A
|
||||
operator fun div(other: A): A
|
||||
operator fun rem(other: A): A
|
||||
|
||||
operator fun rangeTo(other: A): A
|
||||
|
||||
operator fun compareTo(other: A): Int
|
||||
|
||||
fun id(): A
|
||||
}
|
||||
|
||||
interface B {
|
||||
operator fun inc(): B
|
||||
operator fun dec(): B
|
||||
|
||||
operator fun plusAssign(other: B)
|
||||
operator fun minusAssign(other: B)
|
||||
operator fun timesAssign(other: B)
|
||||
operator fun divAssign(other: B)
|
||||
operator fun remAssign(other: B)
|
||||
}
|
||||
|
||||
operator fun Any?.contains(other: Any): Boolean = false
|
||||
|
||||
fun testWithSubject_ok(x: A, y: A?, any: Any, z: B) {
|
||||
when (x) {
|
||||
x.id() -> {}
|
||||
y?.id() -> {}
|
||||
any as? A -> {}
|
||||
any as A -> {}
|
||||
x * x -> {}
|
||||
x / x -> {}
|
||||
x % x -> {}
|
||||
x + x -> {}
|
||||
x - x -> {}
|
||||
x..x -> {}
|
||||
y -> {}
|
||||
y ?: x -> {}
|
||||
}
|
||||
|
||||
var b = z
|
||||
when (z) {
|
||||
b++ -> {}
|
||||
b-- -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_1(x: A) {
|
||||
// bad
|
||||
when (x) {
|
||||
x in x -> {}
|
||||
x !in x -> {}
|
||||
x is String -> {}
|
||||
x !is String -> {}
|
||||
x < x -> {}
|
||||
x > x -> {}
|
||||
x <= x -> {}
|
||||
x >= x -> {}
|
||||
x == x -> {}
|
||||
x != x -> {}
|
||||
x === x -> {}
|
||||
x !== x -> {}
|
||||
}
|
||||
// ok
|
||||
when (x) {
|
||||
(x in x) -> {}
|
||||
(x !in x) -> {}
|
||||
(x is String) -> {}
|
||||
(x !is String) -> {}
|
||||
(x < x) -> {}
|
||||
(x > x) -> {}
|
||||
(x <= x) -> {}
|
||||
(x >= x) -> {}
|
||||
(x == x) -> {}
|
||||
(x != x) -> {}
|
||||
(x === x) -> {}
|
||||
(x !== x) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_2(b: Boolean) {
|
||||
// bad
|
||||
when (b) {
|
||||
b && b -> {}
|
||||
b || b -> {}
|
||||
}
|
||||
// ok
|
||||
when (b) {
|
||||
(b && b) -> {}
|
||||
(b || b) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_3(a: Array<Any>) {
|
||||
// bad
|
||||
when (a) {
|
||||
<!SYNTAX!><!SYNTAX!><!>*<!>a <!SYNTAX!><!>-> {}
|
||||
}
|
||||
// also bad
|
||||
when (a) {
|
||||
(<!UNRESOLVED_REFERENCE!><!SYNTAX!><!>*<!>a<!SYNTAX!>)<!><!SYNTAX!><!> <!SYNTAX!><!>-> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_4(b: B) {
|
||||
var x = b
|
||||
// bad
|
||||
when (b) {
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>x = b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b += b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b -= b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b *= b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b /= b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b %= b<!> -> {}
|
||||
}
|
||||
// also bad
|
||||
when (b) {
|
||||
<!EXPRESSION_EXPECTED!>(x = b)<!> -> {}
|
||||
<!EXPRESSION_EXPECTED!>(b += b)<!> -> {}
|
||||
<!EXPRESSION_EXPECTED!>(b -= b)<!> -> {}
|
||||
<!EXPRESSION_EXPECTED!>(b *= b)<!> -> {}
|
||||
<!EXPRESSION_EXPECTED!>(b /= b)<!> -> {}
|
||||
<!EXPRESSION_EXPECTED!>(b %= b)<!> -> {}
|
||||
}
|
||||
}
|
||||
|
||||
// range
|
||||
|
||||
fun testWithRange_ok(x: A, y: A?, any: Any, z: B) {
|
||||
when (x) {
|
||||
in x.id() -> {}
|
||||
in y?.id() -> {}
|
||||
in any as? A -> {}
|
||||
in any as A -> {}
|
||||
in x * x -> {}
|
||||
in x / x -> {}
|
||||
in x % x -> {}
|
||||
in x + x -> {}
|
||||
in x - x -> {}
|
||||
in x..x -> {}
|
||||
in y -> {}
|
||||
in y ?: x -> {}
|
||||
}
|
||||
|
||||
var b = z
|
||||
when (z) {
|
||||
in b++ -> {}
|
||||
in b-- -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_1(x: A) {
|
||||
// bad
|
||||
when (x) {
|
||||
in x in x -> {}
|
||||
in x !in x -> {}
|
||||
in x is String -> {}
|
||||
in x !is String -> {}
|
||||
in x < x -> {}
|
||||
in x > x -> {}
|
||||
in x <= x -> {}
|
||||
in x >= x -> {}
|
||||
in x == x -> {}
|
||||
in x != x -> {}
|
||||
in x === x -> {}
|
||||
in x !== x -> {}
|
||||
}
|
||||
// ok
|
||||
when (x) {
|
||||
in (x in x) -> {}
|
||||
in (x !in x) -> {}
|
||||
in (x is String) -> {}
|
||||
in (x !is String) -> {}
|
||||
in (x < x) -> {}
|
||||
in (x > x) -> {}
|
||||
in (x <= x) -> {}
|
||||
in (x >= x) -> {}
|
||||
in (x == x) -> {}
|
||||
in (x != x) -> {}
|
||||
in (x === x) -> {}
|
||||
in (x !== x) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_2(b: Boolean) {
|
||||
// bad
|
||||
when (b) {
|
||||
in b && b -> {}
|
||||
in b || b -> {}
|
||||
}
|
||||
// ok
|
||||
when (b) {
|
||||
in (b && b) -> {}
|
||||
in (b || b) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_3(a: Array<Any>) {
|
||||
// bad
|
||||
when (a) {
|
||||
in<!SYNTAX!><!> <!SYNTAX!>*<!>a <!SYNTAX!><!>-> {}
|
||||
}
|
||||
// also bad
|
||||
when (a) {
|
||||
in (<!UNRESOLVED_REFERENCE!><!SYNTAX!><!>*<!>a<!SYNTAX!>)<!><!SYNTAX!><!> <!SYNTAX!><!>-> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_4(b: B) {
|
||||
var x = b
|
||||
// bad
|
||||
when (b) {
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>x = b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b += b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b -= b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b *= b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b /= b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b %= b<!> -> {}
|
||||
}
|
||||
// also bad
|
||||
when (b) {
|
||||
in <!EXPRESSION_EXPECTED!>(x = b)<!> -> {}
|
||||
in <!EXPRESSION_EXPECTED!>(b += b)<!> -> {}
|
||||
in <!EXPRESSION_EXPECTED!>(b -= b)<!> -> {}
|
||||
in <!EXPRESSION_EXPECTED!>(b *= b)<!> -> {}
|
||||
in <!EXPRESSION_EXPECTED!>(b /= b)<!> -> {}
|
||||
in <!EXPRESSION_EXPECTED!>(b %= b)<!> -> {}
|
||||
}
|
||||
}
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
// LANGUAGE: -ProhibitConfusingSyntaxInWhenBranches
|
||||
// DIAGNOSTICS: -INCOMPATIBLE_TYPES, -NON_EXHAUSTIVE_WHEN_STATEMENT, -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE
|
||||
// ISSUE: KT-48385
|
||||
|
||||
interface A {
|
||||
operator fun plus(other: A): A
|
||||
operator fun minus(other: A): A
|
||||
operator fun times(other: A): A
|
||||
operator fun div(other: A): A
|
||||
operator fun rem(other: A): A
|
||||
|
||||
operator fun rangeTo(other: A): A
|
||||
|
||||
operator fun compareTo(other: A): Int
|
||||
|
||||
fun id(): A
|
||||
}
|
||||
|
||||
interface B {
|
||||
operator fun inc(): B
|
||||
operator fun dec(): B
|
||||
|
||||
operator fun plusAssign(other: B)
|
||||
operator fun minusAssign(other: B)
|
||||
operator fun timesAssign(other: B)
|
||||
operator fun divAssign(other: B)
|
||||
operator fun remAssign(other: B)
|
||||
}
|
||||
|
||||
operator fun Any?.contains(other: Any): Boolean = false
|
||||
|
||||
fun testWithSubject_ok(x: A, y: A?, any: Any, z: B) {
|
||||
when (x) {
|
||||
x.id() -> {}
|
||||
y?.id() -> {}
|
||||
any as? A -> {}
|
||||
any as A -> {}
|
||||
x * x -> {}
|
||||
x / x -> {}
|
||||
x % x -> {}
|
||||
x + x -> {}
|
||||
x - x -> {}
|
||||
x..x -> {}
|
||||
y -> {}
|
||||
y ?: x -> {}
|
||||
}
|
||||
|
||||
var b = z
|
||||
when (z) {
|
||||
b++ -> {}
|
||||
b-- -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_1(x: A) {
|
||||
// bad
|
||||
when (x) {
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>x in x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>x !in x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>x is String<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>x !is String<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>x < x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>x > x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>x <= x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>x >= x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>x == x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>x != x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>x === x<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>x !== x<!> -> {}
|
||||
}
|
||||
// ok
|
||||
when (x) {
|
||||
(x in x) -> {}
|
||||
(x !in x) -> {}
|
||||
(x is String) -> {}
|
||||
(x !is String) -> {}
|
||||
(x < x) -> {}
|
||||
(x > x) -> {}
|
||||
(x <= x) -> {}
|
||||
(x >= x) -> {}
|
||||
(x == x) -> {}
|
||||
(x != x) -> {}
|
||||
(x === x) -> {}
|
||||
(x !== x) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_2(b: Boolean) {
|
||||
// bad
|
||||
when (b) {
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>b && b<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>b || b<!> -> {}
|
||||
}
|
||||
// ok
|
||||
when (b) {
|
||||
(b && b) -> {}
|
||||
(b || b) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_3(a: Array<Any>) {
|
||||
// bad
|
||||
when (a) {
|
||||
<!SYNTAX!><!SYNTAX!><!>*<!>a <!SYNTAX!><!>-> {}
|
||||
}
|
||||
// also bad
|
||||
when (a) {
|
||||
(<!DEBUG_INFO_MISSING_UNRESOLVED!><!SYNTAX!><!>*<!>a<!SYNTAX!>)<!><!SYNTAX!><!> <!SYNTAX!><!>-> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithSubject_bad_4(b: B) {
|
||||
var x = b
|
||||
// bad
|
||||
when (b) {
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>x = b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b += b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b -= b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b *= b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b /= b<!> -> {}
|
||||
<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b %= b<!> -> {}
|
||||
}
|
||||
// also bad
|
||||
when (b) {
|
||||
(<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>x = b<!>) -> {}
|
||||
(<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b += b<!>) -> {}
|
||||
(<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b -= b<!>) -> {}
|
||||
(<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b *= b<!>) -> {}
|
||||
(<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b /= b<!>) -> {}
|
||||
(<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b %= b<!>) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
// range
|
||||
|
||||
fun testWithRange_ok(x: A, y: A?, any: Any, z: B) {
|
||||
when (x) {
|
||||
in x.id() -> {}
|
||||
in y?.id() -> {}
|
||||
in any as? A -> {}
|
||||
in any as A -> {}
|
||||
in x * x -> {}
|
||||
in x / x -> {}
|
||||
in x % x -> {}
|
||||
in x + x -> {}
|
||||
in x - x -> {}
|
||||
in x..x -> {}
|
||||
in y -> {}
|
||||
in y ?: x -> {}
|
||||
}
|
||||
|
||||
var b = z
|
||||
when (z) {
|
||||
in b++ -> {}
|
||||
in b-- -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_1(x: A) {
|
||||
// bad
|
||||
when (x) {
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x in x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x !in x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x is String<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x !is String<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x < x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x > x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x <= x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x >= x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x == x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x != x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x === x<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>x !== x<!> -> {}
|
||||
}
|
||||
// ok
|
||||
when (x) {
|
||||
in (x in x) -> {}
|
||||
in (x !in x) -> {}
|
||||
in (x is String) -> {}
|
||||
in (x !is String) -> {}
|
||||
in (x < x) -> {}
|
||||
in (x > x) -> {}
|
||||
in (x <= x) -> {}
|
||||
in (x >= x) -> {}
|
||||
in (x == x) -> {}
|
||||
in (x != x) -> {}
|
||||
in (x === x) -> {}
|
||||
in (x !== x) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_2(b: Boolean) {
|
||||
// bad
|
||||
when (b) {
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>b && b<!> -> {}
|
||||
in <!CONFUSING_BRANCH_CONDITION_WARNING!>b || b<!> -> {}
|
||||
}
|
||||
// ok
|
||||
when (b) {
|
||||
in (b && b) -> {}
|
||||
in (b || b) -> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_3(a: Array<Any>) {
|
||||
// bad
|
||||
when (a) {
|
||||
in<!SYNTAX!><!> <!SYNTAX!>*<!>a <!SYNTAX!><!>-> {}
|
||||
}
|
||||
// also bad
|
||||
when (a) {
|
||||
in (<!DEBUG_INFO_MISSING_UNRESOLVED!><!SYNTAX!><!>*<!>a<!SYNTAX!>)<!><!SYNTAX!><!> <!SYNTAX!><!>-> {}
|
||||
}
|
||||
}
|
||||
|
||||
fun testWithRange_bad_4(b: B) {
|
||||
var x = b
|
||||
// bad
|
||||
when (b) {
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>x = b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b += b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b -= b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b *= b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b /= b<!> -> {}
|
||||
in <!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b %= b<!> -> {}
|
||||
}
|
||||
// also bad
|
||||
when (b) {
|
||||
in (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>x = b<!>) -> {}
|
||||
in (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b += b<!>) -> {}
|
||||
in (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b -= b<!>) -> {}
|
||||
in (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b *= b<!>) -> {}
|
||||
in (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b /= b<!>) -> {}
|
||||
in (<!ASSIGNMENT_IN_EXPRESSION_CONTEXT!>b %= b<!>) -> {}
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package
|
||||
|
||||
public fun testWithRange_bad_1(/*0*/ x: A): kotlin.Unit
|
||||
public fun testWithRange_bad_2(/*0*/ b: kotlin.Boolean): kotlin.Unit
|
||||
public fun testWithRange_bad_3(/*0*/ a: kotlin.Array<kotlin.Any>): kotlin.Unit
|
||||
public fun testWithRange_bad_4(/*0*/ b: B): kotlin.Unit
|
||||
public fun testWithRange_ok(/*0*/ x: A, /*1*/ y: A?, /*2*/ any: kotlin.Any, /*3*/ z: B): kotlin.Unit
|
||||
public fun testWithSubject_bad_1(/*0*/ x: A): kotlin.Unit
|
||||
public fun testWithSubject_bad_2(/*0*/ b: kotlin.Boolean): kotlin.Unit
|
||||
public fun testWithSubject_bad_3(/*0*/ a: kotlin.Array<kotlin.Any>): kotlin.Unit
|
||||
public fun testWithSubject_bad_4(/*0*/ b: B): kotlin.Unit
|
||||
public fun testWithSubject_ok(/*0*/ x: A, /*1*/ y: A?, /*2*/ any: kotlin.Any, /*3*/ z: B): kotlin.Unit
|
||||
public operator fun kotlin.Any?.contains(/*0*/ other: kotlin.Any): kotlin.Boolean
|
||||
|
||||
public interface A {
|
||||
public abstract operator fun compareTo(/*0*/ other: A): kotlin.Int
|
||||
public abstract operator fun div(/*0*/ other: A): A
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public abstract fun id(): A
|
||||
public abstract operator fun minus(/*0*/ other: A): A
|
||||
public abstract operator fun plus(/*0*/ other: A): A
|
||||
public abstract operator fun rangeTo(/*0*/ other: A): A
|
||||
public abstract operator fun rem(/*0*/ other: A): A
|
||||
public abstract operator fun times(/*0*/ other: A): A
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface B {
|
||||
public abstract operator fun dec(): B
|
||||
public abstract operator fun divAssign(/*0*/ other: B): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public abstract operator fun inc(): B
|
||||
public abstract operator fun minusAssign(/*0*/ other: B): kotlin.Unit
|
||||
public abstract operator fun plusAssign(/*0*/ other: B): kotlin.Unit
|
||||
public abstract operator fun remAssign(/*0*/ other: B): kotlin.Unit
|
||||
public abstract operator fun timesAssign(/*0*/ other: B): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
+3
-3
@@ -10,8 +10,8 @@ fun test_0(b: Boolean): String = when (b) {
|
||||
|
||||
// Deprecated
|
||||
fun test_1(b: Boolean): String = <!NO_ELSE_IN_WHEN!>when<!> (b) {
|
||||
1 == 1 -> "true"
|
||||
"" != "" -> "false"
|
||||
(1 == 1) -> "true"
|
||||
("" != "") -> "false"
|
||||
}
|
||||
|
||||
const val TRUE = true
|
||||
@@ -28,5 +28,5 @@ const val s2 = "s2"
|
||||
// Already not working
|
||||
fun test_3(b: Boolean): String = <!NO_ELSE_IN_WHEN!>when<!>(b) {
|
||||
true -> "true"
|
||||
s1 == s2 -> "false"
|
||||
(s1 == s2) -> "false"
|
||||
}
|
||||
|
||||
Vendored
+3
-3
@@ -9,8 +9,8 @@ fun test_0(b: Boolean): String = when (b) {
|
||||
|
||||
// Deprecated
|
||||
fun test_1(b: Boolean): String = when (b) {
|
||||
<!NON_TRIVIAL_BOOLEAN_CONSTANT!>1 == 1<!> -> "true"
|
||||
<!NON_TRIVIAL_BOOLEAN_CONSTANT!>"" != ""<!> -> "false"
|
||||
(<!NON_TRIVIAL_BOOLEAN_CONSTANT!>1 == 1<!>) -> "true"
|
||||
(<!NON_TRIVIAL_BOOLEAN_CONSTANT!>"" != ""<!>) -> "false"
|
||||
}
|
||||
|
||||
const val TRUE = true
|
||||
@@ -27,5 +27,5 @@ const val s2 = "s2"
|
||||
// Already not working
|
||||
fun test_3(b: Boolean): String = <!NO_ELSE_IN_WHEN!>when<!>(b) {
|
||||
true -> "true"
|
||||
s1 == s2 -> "false"
|
||||
(s1 == s2) -> "false"
|
||||
}
|
||||
|
||||
Generated
+18
@@ -32191,6 +32191,24 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/when/CommaInWhenConditionWithoutArgument.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedSyntaxInConditionsNoSubject.kt")
|
||||
public void testDeprecatedSyntaxInConditionsNoSubject() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditionsNoSubject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedSyntaxInConditions_after.kt")
|
||||
public void testDeprecatedSyntaxInConditions_after() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_after.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("deprecatedSyntaxInConditions_before.kt")
|
||||
public void testDeprecatedSyntaxInConditions_before() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/deprecatedSyntaxInConditions_before.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DuplicatedLabels.kt")
|
||||
public void testDuplicatedLabels() throws Exception {
|
||||
|
||||
+2
-2
@@ -29,7 +29,7 @@ fun case_3(value_1: Boolean?): Int = <!TYPE_MISMATCH!><!NO_ELSE_IN_WHEN!>when<!>
|
||||
|
||||
// TESTCASE NUMBER: 4
|
||||
fun case_4(value_1: Boolean?): String = <!NO_ELSE_IN_WHEN!>when<!> (value_1) {
|
||||
true && false && ((true || false)) || true && !!!false && !!!true -> ""
|
||||
true && false && ((true || false)) || true && !!!false -> ""
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>true && false && ((true || false)) || true && !!!false && !!!true<!> -> ""
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>true && false && ((true || false)) || true && !!!false<!> -> ""
|
||||
null -> ""
|
||||
}
|
||||
|
||||
+2
-2
@@ -48,6 +48,6 @@ fun case_5(value_1: Boolean): String {
|
||||
|
||||
// TESTCASE NUMBER: 6
|
||||
fun case_6(value_1: Boolean): String = <!NO_ELSE_IN_WHEN!>when<!> (value_1) {
|
||||
true && false && ((true || false)) || true && !!!false && !!!true -> ""
|
||||
true && false && ((true || false)) || true && !!!false -> ""
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>true && false && ((true || false)) || true && !!!false && !!!true<!> -> ""
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>true && false && ((true || false)) || true && !!!false<!> -> ""
|
||||
}
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ fun case_1(value_1: Boolean?): String = when (value_1) {
|
||||
|
||||
// TESTCASE NUMBER: 2
|
||||
fun case_2(value_1: Boolean?): String = when (value_1) {
|
||||
<!NON_TRIVIAL_BOOLEAN_CONSTANT!>true && false && ((true || false)) || true && !!!false && !!!true<!> -> ""
|
||||
<!NON_TRIVIAL_BOOLEAN_CONSTANT!>true && false && ((true || false)) || true && !!!false<!> -> ""
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING, NON_TRIVIAL_BOOLEAN_CONSTANT!>true && false && ((true || false)) || true && !!!false && !!!true<!> -> ""
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING, NON_TRIVIAL_BOOLEAN_CONSTANT!>true && false && ((true || false)) || true && !!!false<!> -> ""
|
||||
null -> ""
|
||||
}
|
||||
|
||||
+2
-2
@@ -18,6 +18,6 @@ fun case_1(value_1: Boolean): String = when (value_1) {
|
||||
|
||||
// TESTCASE NUMBER: 2
|
||||
fun case_2(value_1: Boolean): String = when (value_1) {
|
||||
<!NON_TRIVIAL_BOOLEAN_CONSTANT!>true && false && ((true || false)) || true && !!!false && !!!true<!> -> ""
|
||||
<!NON_TRIVIAL_BOOLEAN_CONSTANT!>true && false && ((true || false)) || true && !!!false<!> -> ""
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING, NON_TRIVIAL_BOOLEAN_CONSTANT!>true && false && ((true || false)) || true && !!!false && !!!true<!> -> ""
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING, NON_TRIVIAL_BOOLEAN_CONSTANT!>true && false && ((true || false)) || true && !!!false<!> -> ""
|
||||
}
|
||||
|
||||
+6
-6
@@ -58,13 +58,13 @@ fun case_4(value_1: Int, value_2: String, value_3: String) {
|
||||
fun case_5(value_1: Int, value_2: Int, value_3: Boolean?) {
|
||||
when (value_1) {
|
||||
1 -> when (value_3) {
|
||||
value_2 > 1000 -> "1"
|
||||
value_2 > 100 -> "2"
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_2 > 1000<!> -> "1"
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_2 > 100<!> -> "2"
|
||||
else -> "3"
|
||||
}
|
||||
2 -> <!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_3) {
|
||||
value_2 > 1000 -> "1"
|
||||
value_2 > 100 -> "2"
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_2 > 1000<!> -> "1"
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_2 > 100<!> -> "2"
|
||||
}
|
||||
3 -> <!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_3) {}
|
||||
4 -> when (value_3) {
|
||||
@@ -83,8 +83,8 @@ fun case_5(value_1: Int, value_2: Int, value_3: Boolean?) {
|
||||
// TESTCASE NUMBER: 6
|
||||
fun case_6(value_1: Int, value_2: Int, value_3: Boolean?) = when (value_1) {
|
||||
1 -> when (value_3) {
|
||||
value_2 > 1000 -> 1
|
||||
value_2 > 100 -> 2
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_2 > 1000<!> -> 1
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_2 > 100<!> -> 2
|
||||
else -> 3
|
||||
}
|
||||
else -> when (value_3) {
|
||||
|
||||
+4
-4
@@ -37,10 +37,10 @@ fun case_3(value_1: Boolean, value_2: Boolean, value_3: Long) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_1) {
|
||||
value_2 -> {}
|
||||
!value_2 -> {}
|
||||
getBoolean() && value_2 -> {}
|
||||
getChar() != 'a' -> {}
|
||||
getList() === getAny() -> {}
|
||||
value_3 <= 11 -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>getBoolean() && value_2<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>getChar() != 'a'<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>getList() === getAny()<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>value_3 <= 11<!> -> {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -29,8 +29,8 @@ fun case_2(value_1: Number, value_2: Int) {
|
||||
// TESTCASE NUMBER: 3
|
||||
fun case_3(value_1: Boolean, value_2: Boolean, value_3: Long) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_1) {
|
||||
value_2, !value_2, getBoolean() && value_2, getChar() != 'a' -> {}
|
||||
getList() === getAny(), value_3 <= 11 -> {}
|
||||
value_2, !value_2, <!CONFUSING_BRANCH_CONDITION_WARNING!>getBoolean() && value_2<!>, <!CONFUSING_BRANCH_CONDITION_WARNING!>getChar() != 'a'<!> -> {}
|
||||
<!CONFUSING_BRANCH_CONDITION_WARNING!>getList() === getAny()<!>, <!CONFUSING_BRANCH_CONDITION_WARNING!>value_3 <= 11<!> -> {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -234,6 +234,7 @@ enum class LanguageFeature(
|
||||
RefineTypeCheckingOnAssignmentsToJavaFields(KOTLIN_1_7),
|
||||
JvmPermittedSubclassesAttributeForSealed(KOTLIN_1_7),
|
||||
ForbidUsingExtensionPropertyTypeParameterInDelegate(KOTLIN_1_7, kind = BUG_FIX),
|
||||
ProhibitConfusingSyntaxInWhenBranches(KOTLIN_1_7, kind = BUG_FIX), // KT-48385
|
||||
|
||||
// Temporarily disabled, see KT-27084/KT-22379
|
||||
SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX),
|
||||
|
||||
Reference in New Issue
Block a user