[FIR] Report NON_EXHAUSTIVE_WHEN_STATEMENT/NO_ELSE_IN_WHEN for when's on logical types

^KT-47709 In Progress
This commit is contained in:
Dmitriy Novozhilov
2021-07-13 13:15:49 +03:00
committed by teamcityserver
parent ef635f6a96
commit a6edd852ff
38 changed files with 120 additions and 431 deletions
-15
View File
@@ -1,15 +0,0 @@
//FILE: foo.kt
fun main() {
val c: Type
when (<!UNINITIALIZED_VARIABLE!>c<!>) {
}
}
//FILE: Type.java
public enum Type {
TYPE,
NO_TYPE;
}
+1
View File
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
//FILE: foo.kt
fun main() {
val c: Type
@@ -1,10 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VALUE
fun foo(f: Boolean): Int {
val i: Int
when (f) {
true -> i = 1
}
<!VAL_REASSIGNMENT!>i<!> = 3
return i
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VALUE
fun foo(f: Boolean): Int {
@@ -7,7 +7,7 @@ fun foo(my: My) {
if (my.x != null) {
// my.x should be smart-cast
if (my.x) doIt()
when (my.x) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (my.x) {
true -> doIt()
}
when {
@@ -20,11 +20,11 @@ fun bar(x: Boolean?) {
if (x != null) {
// x should be smart-cast
if (x) doIt()
when (x) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
true -> doIt()
}
when {
x -> doIt()
}
}
}
}
@@ -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<!>
@@ -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<!>
@@ -1,23 +0,0 @@
/*
* 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 -> 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"
when (arg) {
X.A -> res = "A"
X.B -> res = "B"
}
return res
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -22,7 +22,7 @@ object Last : S()
fun use(s: String) = s
fun foo(s: S) {
when (s) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (s) {
First -> {}
is Derived -> use(s.s)
}
@@ -1,27 +0,0 @@
/*
* 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,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -1,154 +0,0 @@
// !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 -> ""
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: -ProhibitNonExhaustiveWhenOnAlgebraicTypes
enum class SomeEnum {
@@ -1,154 +0,0 @@
// !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 -> ""
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +ProhibitNonExhaustiveWhenOnAlgebraicTypes
enum class SomeEnum {
@@ -1,20 +0,0 @@
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,3 +1,4 @@
// FIR_IDENTICAL
fun test1() {
if (true) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (true) {