[FE 1.0] Report NON_EXHAUSTIVE_WHEN_STATEMENT/NO_ELSE_IN_WHEN for when's on logical types
^KT-47709 In Progress
This commit is contained in:
committed by
teamcityserver
parent
85c7f386eb
commit
ef635f6a96
+12
@@ -31681,6 +31681,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/when/NonExhaustiveWarningNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonExhaustiveWhenStatement_1_6.kt")
|
||||
public void testNonExhaustiveWhenStatement_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/nonExhaustiveWhenStatement_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonExhaustiveWhenStatement_1_7.kt")
|
||||
public void testNonExhaustiveWhenStatement_1_7() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/nonExhaustiveWhenStatement_1_7.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("NonExhaustiveWithNullabilityCheck.kt")
|
||||
public void testNonExhaustiveWithNullabilityCheck() throws Exception {
|
||||
|
||||
+12
@@ -31681,6 +31681,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/when/NonExhaustiveWarningNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonExhaustiveWhenStatement_1_6.kt")
|
||||
public void testNonExhaustiveWhenStatement_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/nonExhaustiveWhenStatement_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonExhaustiveWhenStatement_1_7.kt")
|
||||
public void testNonExhaustiveWhenStatement_1_7() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/nonExhaustiveWhenStatement_1_7.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("NonExhaustiveWithNullabilityCheck.kt")
|
||||
public void testNonExhaustiveWithNullabilityCheck() throws Exception {
|
||||
|
||||
+19
-12
@@ -62,6 +62,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils.*
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
import org.jetbrains.kotlin.types.isFlexible
|
||||
import org.jetbrains.kotlin.types.typeUtil.isBooleanOrNullableBoolean
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
class ControlFlowInformationProviderImpl private constructor(
|
||||
@@ -1024,19 +1025,19 @@ class ControlFlowInformationProviderImpl private constructor(
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (!usedAsExpression) {
|
||||
val enumClassDescriptor = WhenChecker.getClassDescriptorOfTypeIfEnum(subjectType)
|
||||
if (enumClassDescriptor != null) {
|
||||
val enumMissingCases = WhenChecker.getEnumMissingCases(element, context, enumClassDescriptor)
|
||||
if (enumMissingCases.isNotEmpty()) {
|
||||
trace.report(NON_EXHAUSTIVE_WHEN.on(element, enumMissingCases))
|
||||
}
|
||||
if (!usedAsExpression && missingCases.isNotEmpty()) {
|
||||
val kind = when {
|
||||
WhenChecker.getClassDescriptorOfTypeIfSealed(subjectType) != null -> AlgebraicTypeKind.Sealed
|
||||
WhenChecker.getClassDescriptorOfTypeIfEnum(subjectType) != null -> AlgebraicTypeKind.Enum
|
||||
subjectType?.isBooleanOrNullableBoolean() == true -> AlgebraicTypeKind.Boolean
|
||||
else -> null
|
||||
}
|
||||
val sealedClassDescriptor = WhenChecker.getClassDescriptorOfTypeIfSealed(subjectType)
|
||||
if (sealedClassDescriptor != null) {
|
||||
val sealedMissingCases = WhenChecker.getSealedMissingCases(element, context, sealedClassDescriptor)
|
||||
if (sealedMissingCases.isNotEmpty()) {
|
||||
trace.report(NON_EXHAUSTIVE_WHEN_ON_SEALED_CLASS.on(element, sealedMissingCases))
|
||||
|
||||
if (kind != null) {
|
||||
if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNonExhaustiveWhenOnAlgebraicTypes)) {
|
||||
trace.report(NO_ELSE_IN_WHEN.on(element, missingCases))
|
||||
} else {
|
||||
trace.report(NON_EXHAUSTIVE_WHEN_STATEMENT.on(element, kind.displayName, missingCases))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1045,6 +1046,12 @@ class ControlFlowInformationProviderImpl private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private enum class AlgebraicTypeKind(val displayName: String) {
|
||||
Sealed("sealed class/interface"),
|
||||
Enum("enum"),
|
||||
Boolean("Boolean")
|
||||
}
|
||||
|
||||
private fun checkConstructorConsistency() {
|
||||
when (subroutine) {
|
||||
is KtClassOrObject -> ConstructorConsistencyChecker.check(subroutine, trace, pseudocode, pseudocodeVariablesData)
|
||||
|
||||
@@ -1080,6 +1080,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtWhenEntry> REDUNDANT_ELSE_IN_WHEN = DiagnosticFactory0.create(WARNING, ELSE_ENTRY);
|
||||
DiagnosticFactory1<KtWhenExpression, List<WhenMissingCase>> NO_ELSE_IN_WHEN = DiagnosticFactory1.create(ERROR, WHEN_EXPRESSION);
|
||||
DiagnosticFactory1<KtWhenExpression, List<WhenMissingCase>> NON_EXHAUSTIVE_WHEN = DiagnosticFactory1.create(WARNING, WHEN_EXPRESSION);
|
||||
DiagnosticFactory2<KtWhenExpression, String, List<WhenMissingCase>> NON_EXHAUSTIVE_WHEN_STATEMENT = DiagnosticFactory2.create(WARNING, WHEN_EXPRESSION);
|
||||
DiagnosticFactory1<KtWhenExpression, List<WhenMissingCase>>
|
||||
NON_EXHAUSTIVE_WHEN_ON_SEALED_CLASS = DiagnosticFactory1.create(INFO, WHEN_EXPRESSION);
|
||||
DiagnosticFactory1<KtWhenExpression, String> EXPECT_TYPE_IN_WHEN_WITHOUT_ELSE = DiagnosticFactory1.create(ERROR, WHEN_EXPRESSION);
|
||||
|
||||
+1
@@ -631,6 +631,7 @@ public class DefaultErrorMessages {
|
||||
|
||||
MAP.put(NO_ELSE_IN_WHEN, "''when'' expression must be exhaustive, add necessary {0}", RENDER_WHEN_MISSING_CASES);
|
||||
MAP.put(NON_EXHAUSTIVE_WHEN, "''when'' expression on enum is recommended to be exhaustive, add {0}", RENDER_WHEN_MISSING_CASES);
|
||||
MAP.put(NON_EXHAUSTIVE_WHEN_STATEMENT, "Non exhaustive ''when'' statements on {0} will be prohibited in 1.7, add {1}", STRING, RENDER_WHEN_MISSING_CASES);
|
||||
MAP.put(NON_EXHAUSTIVE_WHEN_ON_SEALED_CLASS, "''when'' expression on sealed classes is recommended to be exhaustive, add {0}", RENDER_WHEN_MISSING_CASES);
|
||||
MAP.put(EXPECT_TYPE_IN_WHEN_WITHOUT_ELSE, "'when' with expect {0} as subject can not be exhaustive without else branch", STRING);
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
//FILE: foo.kt
|
||||
fun main() {
|
||||
val c: Type
|
||||
<!NON_EXHAUSTIVE_WHEN!>when<!> (<!UNINITIALIZED_VARIABLE!>c<!>) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (<!UNINITIALIZED_VARIABLE!>c<!>) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VALUE
|
||||
|
||||
fun foo(f: Boolean): Int {
|
||||
val i: Int
|
||||
when (f) {
|
||||
true -> i = 1
|
||||
}
|
||||
<!VAL_REASSIGNMENT!>i<!> = 3
|
||||
return i
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_VALUE
|
||||
|
||||
fun foo(f: Boolean): Int {
|
||||
val i: Int
|
||||
when (f) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (f) {
|
||||
true -> i = 1
|
||||
}
|
||||
<!VAL_REASSIGNMENT!>i<!> = 3
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ fun foo(my: My) {
|
||||
if (my.x != null) {
|
||||
// my.x should be smart-cast
|
||||
if (<!DEBUG_INFO_SMARTCAST!>my.x<!>) doIt()
|
||||
when (<!DEBUG_INFO_SMARTCAST!>my.x<!>) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (<!DEBUG_INFO_SMARTCAST!>my.x<!>) {
|
||||
true -> doIt()
|
||||
}
|
||||
when {
|
||||
@@ -20,11 +20,11 @@ fun bar(x: Boolean?) {
|
||||
if (x != null) {
|
||||
// x should be smart-cast
|
||||
if (<!DEBUG_INFO_SMARTCAST!>x<!>) doIt()
|
||||
when (<!DEBUG_INFO_SMARTCAST!>x<!>) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (<!DEBUG_INFO_SMARTCAST!>x<!>) {
|
||||
true -> doIt()
|
||||
}
|
||||
when {
|
||||
<!DEBUG_INFO_SMARTCAST!>x<!> -> doIt()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ fun bar(a: Boolean, b: Boolean): Int {
|
||||
if (a) {
|
||||
x = 1
|
||||
}
|
||||
when (b) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (b) {
|
||||
false -> <!VAL_REASSIGNMENT!>x<!> = 3
|
||||
}
|
||||
return <!UNINITIALIZED_VARIABLE!>x<!>
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ fun bar(a: Boolean, b: Boolean): Int {
|
||||
if (a) {
|
||||
x = 1
|
||||
}
|
||||
when (b) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (b) {
|
||||
false -> x = 3
|
||||
}
|
||||
return <!UNINITIALIZED_VARIABLE!>x<!>
|
||||
|
||||
@@ -15,7 +15,7 @@ enum class X { A, B, C, D }
|
||||
|
||||
fun foo(arg: X): String {
|
||||
var res = "XXX"
|
||||
<!NON_EXHAUSTIVE_WHEN!>when<!> (arg) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (arg) {
|
||||
X.A -> res = "A"
|
||||
X.B -> res = "B"
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ object Last : S()
|
||||
fun use(s: String) = s
|
||||
|
||||
fun foo(s: S) {
|
||||
<!NON_EXHAUSTIVE_WHEN_ON_SEALED_CLASS!>when<!> (s) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (s) {
|
||||
First -> {}
|
||||
is Derived -> use(<!DEBUG_INFO_SMARTCAST!>s<!>.s)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
|
||||
*
|
||||
* SPEC VERSION: 0.1-152
|
||||
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
|
||||
* expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1
|
||||
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 9
|
||||
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 10
|
||||
* expressions, when-expression -> paragraph 9 -> sentence 2
|
||||
* control--and-data-flow-analysis, performing-analysis-on-the-control-flow-graph, variable-initialization-analysis -> paragraph 2 -> sentence 1
|
||||
* control--and-data-flow-analysis, performing-analysis-on-the-control-flow-graph, variable-initialization-analysis -> paragraph 2 -> sentence 3
|
||||
*/
|
||||
|
||||
// Base for KT-6227
|
||||
enum class X { A, B, C, D }
|
||||
|
||||
fun foo(arg: X?): String {
|
||||
var res = "XXX"
|
||||
// Should we report something here? Probably not, null is not an enum entry
|
||||
when (arg) {
|
||||
X.A -> res = "A"
|
||||
X.B -> res = "B"
|
||||
X.C -> res = "C"
|
||||
X.D -> res = "D"
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
/*
|
||||
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
|
||||
*
|
||||
@@ -17,12 +16,11 @@ enum class X { A, B, C, D }
|
||||
|
||||
fun foo(arg: X?): String {
|
||||
var res = "XXX"
|
||||
// Should we report something here? Probably not, null is not an enum entry
|
||||
when (arg) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (arg) {
|
||||
X.A -> res = "A"
|
||||
X.B -> res = "B"
|
||||
X.C -> res = "C"
|
||||
X.D -> res = "D"
|
||||
}
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
// !LANGUAGE: -ProhibitNonExhaustiveWhenOnLogicalTypes
|
||||
|
||||
enum class SomeEnum {
|
||||
A, B
|
||||
}
|
||||
|
||||
sealed class Base {
|
||||
class A : Base()
|
||||
class B : Base()
|
||||
}
|
||||
|
||||
sealed interface IBase {
|
||||
interface A : IBase
|
||||
interface B : IBase
|
||||
}
|
||||
|
||||
// ------------------ not null ------------------
|
||||
|
||||
fun test_1(x: SomeEnum) {
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_2(x: Base) {
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_3(x: IBase) {
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_4(x: Boolean) {
|
||||
when (x) {
|
||||
true -> ""
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ nullable ------------------
|
||||
|
||||
fun test_5(x: SomeEnum?) {
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
SomeEnum.B -> ""
|
||||
}
|
||||
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_6(x: Base?) {
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
is Base.B -> ""
|
||||
}
|
||||
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_7(x: IBase?) {
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
is IBase.B -> ""
|
||||
}
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_8(x: Boolean?) {
|
||||
when (x) {
|
||||
true -> ""
|
||||
false -> ""
|
||||
}
|
||||
|
||||
when (x) {
|
||||
true -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ with else ------------------
|
||||
|
||||
fun test_9(x: SomeEnum?) {
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_10(x: Base?) {
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_11(x: IBase?) {
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_12(x: Boolean?) {
|
||||
when (x) {
|
||||
true -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ exhaustive ------------------
|
||||
|
||||
fun test_13(x: SomeEnum?) {
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
SomeEnum.B -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_14(x: Base?) {
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
is Base.B -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_15(x: IBase?) {
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
is IBase.B -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_16(x: Boolean?) {
|
||||
when (x) {
|
||||
true -> ""
|
||||
false -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
// !LANGUAGE: -ProhibitNonExhaustiveWhenOnAlgebraicTypes
|
||||
|
||||
enum class SomeEnum {
|
||||
A, B
|
||||
}
|
||||
|
||||
sealed class Base {
|
||||
class A : Base()
|
||||
class B : Base()
|
||||
}
|
||||
|
||||
sealed interface IBase {
|
||||
interface A : IBase
|
||||
interface B : IBase
|
||||
}
|
||||
|
||||
// ------------------ not null ------------------
|
||||
|
||||
fun test_1(x: SomeEnum) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
|
||||
SomeEnum.A -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_2(x: Base) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
|
||||
is Base.A -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_3(x: IBase) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
|
||||
is IBase.A -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_4(x: Boolean) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
|
||||
true -> ""
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ nullable ------------------
|
||||
|
||||
fun test_5(x: SomeEnum?) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
|
||||
SomeEnum.A -> ""
|
||||
SomeEnum.B -> ""
|
||||
}
|
||||
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
|
||||
SomeEnum.A -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_6(x: Base?) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
|
||||
is Base.A -> ""
|
||||
is Base.B -> ""
|
||||
}
|
||||
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
|
||||
is Base.A -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_7(x: IBase?) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
|
||||
is IBase.A -> ""
|
||||
is IBase.B -> ""
|
||||
}
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
|
||||
is IBase.A -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_8(x: Boolean?) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
|
||||
true -> ""
|
||||
false -> ""
|
||||
}
|
||||
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
|
||||
true -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ with else ------------------
|
||||
|
||||
fun test_9(x: SomeEnum?) {
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_10(x: Base?) {
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_11(x: IBase?) {
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_12(x: Boolean?) {
|
||||
when (x) {
|
||||
true -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ exhaustive ------------------
|
||||
|
||||
fun test_13(x: SomeEnum?) {
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
SomeEnum.B -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_14(x: Base?) {
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
is Base.B -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_15(x: IBase?) {
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
is IBase.B -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_16(x: Boolean?) {
|
||||
when (x) {
|
||||
true -> ""
|
||||
false -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package
|
||||
|
||||
public fun test_1(/*0*/ x: SomeEnum): kotlin.Unit
|
||||
public fun test_10(/*0*/ x: Base?): kotlin.Unit
|
||||
public fun test_11(/*0*/ x: IBase?): kotlin.Unit
|
||||
public fun test_12(/*0*/ x: kotlin.Boolean?): kotlin.Unit
|
||||
public fun test_13(/*0*/ x: SomeEnum?): kotlin.Unit
|
||||
public fun test_14(/*0*/ x: Base?): kotlin.Unit
|
||||
public fun test_15(/*0*/ x: IBase?): kotlin.Unit
|
||||
public fun test_16(/*0*/ x: kotlin.Boolean?): kotlin.Unit
|
||||
public fun test_2(/*0*/ x: Base): kotlin.Unit
|
||||
public fun test_3(/*0*/ x: IBase): kotlin.Unit
|
||||
public fun test_4(/*0*/ x: kotlin.Boolean): kotlin.Unit
|
||||
public fun test_5(/*0*/ x: SomeEnum?): kotlin.Unit
|
||||
public fun test_6(/*0*/ x: Base?): kotlin.Unit
|
||||
public fun test_7(/*0*/ x: IBase?): kotlin.Unit
|
||||
public fun test_8(/*0*/ x: kotlin.Boolean?): kotlin.Unit
|
||||
public fun test_9(/*0*/ x: SomeEnum?): kotlin.Unit
|
||||
|
||||
public sealed class Base {
|
||||
protected constructor Base()
|
||||
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public final class A : Base {
|
||||
public constructor 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class B : Base {
|
||||
public constructor B()
|
||||
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
public sealed interface IBase {
|
||||
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public interface A : IBase {
|
||||
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface B : IBase {
|
||||
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
public final enum class SomeEnum : kotlin.Enum<SomeEnum> {
|
||||
enum entry A
|
||||
|
||||
enum entry B
|
||||
|
||||
private constructor SomeEnum()
|
||||
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: SomeEnum): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<SomeEnum!>!
|
||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): SomeEnum
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<SomeEnum>
|
||||
}
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
// !LANGUAGE: +ProhibitNonExhaustiveWhenOnLogicalTypes
|
||||
|
||||
enum class SomeEnum {
|
||||
A, B
|
||||
}
|
||||
|
||||
sealed class Base {
|
||||
class A : Base()
|
||||
class B : Base()
|
||||
}
|
||||
|
||||
sealed interface IBase {
|
||||
interface A : IBase
|
||||
interface B : IBase
|
||||
}
|
||||
|
||||
// ------------------ not null ------------------
|
||||
|
||||
fun test_1(x: SomeEnum) {
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_2(x: Base) {
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_3(x: IBase) {
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_4(x: Boolean) {
|
||||
when (x) {
|
||||
true -> ""
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ nullable ------------------
|
||||
|
||||
fun test_5(x: SomeEnum?) {
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
SomeEnum.B -> ""
|
||||
}
|
||||
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_6(x: Base?) {
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
is Base.B -> ""
|
||||
}
|
||||
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_7(x: IBase?) {
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
is IBase.B -> ""
|
||||
}
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_8(x: Boolean?) {
|
||||
when (x) {
|
||||
true -> ""
|
||||
false -> ""
|
||||
}
|
||||
|
||||
when (x) {
|
||||
true -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ with else ------------------
|
||||
|
||||
fun test_9(x: SomeEnum?) {
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_10(x: Base?) {
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_11(x: IBase?) {
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_12(x: Boolean?) {
|
||||
when (x) {
|
||||
true -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ exhaustive ------------------
|
||||
|
||||
fun test_13(x: SomeEnum?) {
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
SomeEnum.B -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_14(x: Base?) {
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
is Base.B -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_15(x: IBase?) {
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
is IBase.B -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_16(x: Boolean?) {
|
||||
when (x) {
|
||||
true -> ""
|
||||
false -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
// !LANGUAGE: +ProhibitNonExhaustiveWhenOnAlgebraicTypes
|
||||
|
||||
enum class SomeEnum {
|
||||
A, B
|
||||
}
|
||||
|
||||
sealed class Base {
|
||||
class A : Base()
|
||||
class B : Base()
|
||||
}
|
||||
|
||||
sealed interface IBase {
|
||||
interface A : IBase
|
||||
interface B : IBase
|
||||
}
|
||||
|
||||
// ------------------ not null ------------------
|
||||
|
||||
fun test_1(x: SomeEnum) {
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
SomeEnum.A -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_2(x: Base) {
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
is Base.A -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_3(x: IBase) {
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
is IBase.A -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_4(x: Boolean) {
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
true -> ""
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ nullable ------------------
|
||||
|
||||
fun test_5(x: SomeEnum?) {
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
SomeEnum.A -> ""
|
||||
SomeEnum.B -> ""
|
||||
}
|
||||
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
SomeEnum.A -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_6(x: Base?) {
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
is Base.A -> ""
|
||||
is Base.B -> ""
|
||||
}
|
||||
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
is Base.A -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_7(x: IBase?) {
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
is IBase.A -> ""
|
||||
is IBase.B -> ""
|
||||
}
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
is IBase.A -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_8(x: Boolean?) {
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
true -> ""
|
||||
false -> ""
|
||||
}
|
||||
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
true -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ with else ------------------
|
||||
|
||||
fun test_9(x: SomeEnum?) {
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_10(x: Base?) {
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_11(x: IBase?) {
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_12(x: Boolean?) {
|
||||
when (x) {
|
||||
true -> ""
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------ exhaustive ------------------
|
||||
|
||||
fun test_13(x: SomeEnum?) {
|
||||
when (x) {
|
||||
SomeEnum.A -> ""
|
||||
SomeEnum.B -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_14(x: Base?) {
|
||||
when (x) {
|
||||
is Base.A -> ""
|
||||
is Base.B -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_15(x: IBase?) {
|
||||
when (x) {
|
||||
is IBase.A -> ""
|
||||
is IBase.B -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test_16(x: Boolean?) {
|
||||
when (x) {
|
||||
true -> ""
|
||||
false -> ""
|
||||
null -> ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package
|
||||
|
||||
public fun test_1(/*0*/ x: SomeEnum): kotlin.Unit
|
||||
public fun test_10(/*0*/ x: Base?): kotlin.Unit
|
||||
public fun test_11(/*0*/ x: IBase?): kotlin.Unit
|
||||
public fun test_12(/*0*/ x: kotlin.Boolean?): kotlin.Unit
|
||||
public fun test_13(/*0*/ x: SomeEnum?): kotlin.Unit
|
||||
public fun test_14(/*0*/ x: Base?): kotlin.Unit
|
||||
public fun test_15(/*0*/ x: IBase?): kotlin.Unit
|
||||
public fun test_16(/*0*/ x: kotlin.Boolean?): kotlin.Unit
|
||||
public fun test_2(/*0*/ x: Base): kotlin.Unit
|
||||
public fun test_3(/*0*/ x: IBase): kotlin.Unit
|
||||
public fun test_4(/*0*/ x: kotlin.Boolean): kotlin.Unit
|
||||
public fun test_5(/*0*/ x: SomeEnum?): kotlin.Unit
|
||||
public fun test_6(/*0*/ x: Base?): kotlin.Unit
|
||||
public fun test_7(/*0*/ x: IBase?): kotlin.Unit
|
||||
public fun test_8(/*0*/ x: kotlin.Boolean?): kotlin.Unit
|
||||
public fun test_9(/*0*/ x: SomeEnum?): kotlin.Unit
|
||||
|
||||
public sealed class Base {
|
||||
protected constructor Base()
|
||||
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public final class A : Base {
|
||||
public constructor 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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class B : Base {
|
||||
public constructor B()
|
||||
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
public sealed interface IBase {
|
||||
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
public interface A : IBase {
|
||||
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public interface B : IBase {
|
||||
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
public final enum class SomeEnum : kotlin.Enum<SomeEnum> {
|
||||
enum entry A
|
||||
|
||||
enum entry B
|
||||
|
||||
private constructor SomeEnum()
|
||||
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: SomeEnum): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<SomeEnum!>!
|
||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): SomeEnum
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<SomeEnum>
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fun test1() {
|
||||
if (true) {
|
||||
when (true) {
|
||||
true -> println()
|
||||
}
|
||||
} else {
|
||||
System.out?.println() // kotlin.Unit?
|
||||
}
|
||||
}
|
||||
|
||||
fun test2() {
|
||||
val mlist = arrayListOf("")
|
||||
if (true) {
|
||||
when (true) {
|
||||
true -> println()
|
||||
}
|
||||
} else {
|
||||
mlist.add("") // kotlin.Boolean
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
// FIR_IDENTICAL
|
||||
fun test1() {
|
||||
if (true) {
|
||||
when (true) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (true) {
|
||||
true -> println()
|
||||
}
|
||||
} else {
|
||||
@@ -12,10 +11,10 @@ fun test1() {
|
||||
fun test2() {
|
||||
val mlist = arrayListOf("")
|
||||
if (true) {
|
||||
when (true) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (true) {
|
||||
true -> println()
|
||||
}
|
||||
} else {
|
||||
mlist.add("") // kotlin.Boolean
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+12
@@ -31777,6 +31777,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/when/NonExhaustiveWarningNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonExhaustiveWhenStatement_1_6.kt")
|
||||
public void testNonExhaustiveWhenStatement_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/nonExhaustiveWhenStatement_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonExhaustiveWhenStatement_1_7.kt")
|
||||
public void testNonExhaustiveWhenStatement_1_7() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/nonExhaustiveWhenStatement_1_7.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("NonExhaustiveWithNullabilityCheck.kt")
|
||||
public void testNonExhaustiveWithNullabilityCheck() throws Exception {
|
||||
|
||||
+2
-2
@@ -70,11 +70,11 @@ fun case_5(value_1: Int, value_2: Int, value_3: Boolean?) {
|
||||
false -> "2"
|
||||
null -> "3"
|
||||
}
|
||||
value_1 == 5 -> when (value_3) {
|
||||
value_1 == 5 -> <!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_3) {
|
||||
true -> "1"
|
||||
false -> "2"
|
||||
}
|
||||
value_1 == 6 -> when (value_3) {}
|
||||
value_1 == 6 -> <!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_3) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -61,21 +61,21 @@ fun case_5(value_1: Int, value_2: Int, value_3: Boolean?) {
|
||||
value_2 > 100 -> "2"
|
||||
else -> "3"
|
||||
}
|
||||
2 -> when (value_3) {
|
||||
2 -> <!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_3) {
|
||||
value_2 > 1000 -> "1"
|
||||
value_2 > 100 -> "2"
|
||||
}
|
||||
3 -> when (value_3) {}
|
||||
3 -> <!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_3) {}
|
||||
4 -> when (value_3) {
|
||||
true -> "1"
|
||||
false -> "2"
|
||||
null -> "3"
|
||||
}
|
||||
5 -> when (value_3) {
|
||||
5 -> <!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_3) {
|
||||
true -> "1"
|
||||
false -> "2"
|
||||
}
|
||||
6 -> when (value_3) {}
|
||||
6 -> <!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_3) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ fun case_3(value_1: SealedClass?): String = when (value_1) {
|
||||
* ISSUES: KT-22996
|
||||
*/
|
||||
fun case_4(value_1: SealedClass?) {
|
||||
when (value_1) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_1) {
|
||||
!is SealedChild2 -> {} // including null
|
||||
<!USELESS_IS_CHECK!>is SealedChild2?<!> -> {} // redundant nullable type check
|
||||
}
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ fun case_2(value_1: Number, value_2: Int) {
|
||||
|
||||
// TESTCASE NUMBER: 3
|
||||
fun case_3(value_1: Boolean, value_2: Boolean, value_3: Long) {
|
||||
when (value_1) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_1) {
|
||||
value_2 -> {}
|
||||
!value_2 -> {}
|
||||
getBoolean() && value_2 -> {}
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ fun case_2(value_1: Number, value_2: Int) {
|
||||
|
||||
// TESTCASE NUMBER: 3
|
||||
fun case_3(value_1: Boolean, value_2: Boolean, value_3: Long) {
|
||||
when (value_1) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_1) {
|
||||
value_2, !value_2, getBoolean() && value_2, getChar() != 'a' -> {}
|
||||
getList() === getAny(), value_3 <= 11 -> {}
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
fun case_1(value_1: EnumClass?) {
|
||||
val value_2: Int
|
||||
|
||||
<!NON_EXHAUSTIVE_WHEN!>when<!> (value_1) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_1) {
|
||||
EnumClass.NORTH -> funWithExactlyOnceCallsInPlace { value_2 = 1 }
|
||||
EnumClass.SOUTH -> funWithExactlyOnceCallsInPlace { value_2 = 2 }
|
||||
EnumClass.EAST -> funWithExactlyOnceCallsInPlace { value_2 = 4 }
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ fun case_4(value_1: Number, value_2: (() -> Unit)?) {
|
||||
|
||||
// TESTCASE NUMBER: 5
|
||||
fun case_5(value_1: Number?, value_2: String?) {
|
||||
when (value_2.case_5(value_1)) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_2.case_5(value_1)) {
|
||||
true -> {
|
||||
println(value_2<!UNSAFE_CALL!>.<!>length)
|
||||
println(value_1<!UNSAFE_CALL!>.<!>toByte())
|
||||
|
||||
+1
-1
@@ -114,7 +114,7 @@ fun case_4(value_1: Number, value_2: (() -> Unit)?) {
|
||||
* ISSUES: KT-26612
|
||||
*/
|
||||
fun case_5(value_1: Number?, value_2: String?) {
|
||||
when (value_2.case_5(value_1)) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (value_2.case_5(value_1)) {
|
||||
true -> {
|
||||
println(value_2<!UNSAFE_CALL!>.<!>length)
|
||||
println(<!DEBUG_INFO_SMARTCAST!>value_1<!>.toByte())
|
||||
|
||||
@@ -146,7 +146,7 @@ fun case_7() {
|
||||
var b = a
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.String")!>b<!>
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.String"), DEBUG_INFO_SMARTCAST!>b<!>.length
|
||||
when (true) {
|
||||
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (true) {
|
||||
true -> b = a
|
||||
}
|
||||
|
||||
|
||||
@@ -216,6 +216,10 @@ enum class LanguageFeature(
|
||||
TypeInferenceOnCallsWithSelfTypes(KOTLIN_1_6),
|
||||
OptInRelease(KOTLIN_1_6),
|
||||
|
||||
// 1.7
|
||||
|
||||
ProhibitNonExhaustiveWhenOnAlgebraicTypes(KOTLIN_1_7, kind = BUG_FIX),
|
||||
|
||||
// Temporarily disabled, see KT-27084/KT-22379
|
||||
SoundSmartcastFromLoopConditionForLoopAssignedVariables(sinceVersion = null, kind = BUG_FIX),
|
||||
|
||||
|
||||
+12
@@ -31681,6 +31681,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/when/NonExhaustiveWarningNull.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonExhaustiveWhenStatement_1_6.kt")
|
||||
public void testNonExhaustiveWhenStatement_1_6() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/nonExhaustiveWhenStatement_1_6.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nonExhaustiveWhenStatement_1_7.kt")
|
||||
public void testNonExhaustiveWhenStatement_1_7() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/when/nonExhaustiveWhenStatement_1_7.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("NonExhaustiveWithNullabilityCheck.kt")
|
||||
public void testNonExhaustiveWithNullabilityCheck() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user