[FIR] Implement checker for exhaustive when's in expression position

This commit is contained in:
Dmitriy Novozhilov
2021-02-04 15:41:57 +03:00
parent 3f715e671d
commit 8dd9d98129
103 changed files with 919 additions and 617 deletions
@@ -12,7 +12,7 @@
enum class E { A, B }
fun test(e: E?) = when (e) {
fun test(e: E?) = <!NO_ELSE_IN_WHEN!>when<!> (e) {
E.A -> 1
E.B -> 2
}
@@ -1,18 +1,18 @@
/*
* KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE)
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* SPEC VERSION: 0.1-313
* 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 3
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 10
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 4
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 5
*/
// See also: KT-3743
fun foo(arg: Boolean?): String {
// Must be NOT exhaustive
return when(arg) {
true -> "truth"
false -> "falsehood"
fun foo(arg: Boolean): String {
// Must be exhaustive
return <!NO_ELSE_IN_WHEN!>when<!>(arg) {
2 == 2 -> "truth"
2 == 1 -> "falsehood"
}
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -12,7 +12,7 @@ enum class MyEnum {
}
fun foo(x: MyEnum): Int {
return when (x) {
return <!NO_ELSE_IN_WHEN!>when<!> (x) {
is <!UNRESOLVED_REFERENCE!>MyEnum.A<!> -> 1
is <!UNRESOLVED_REFERENCE!>MyEnum.B<!> -> 2
is <!UNRESOLVED_REFERENCE!>MyEnum.C<!> -> 3
@@ -13,7 +13,7 @@ enum class MyEnum {
}
fun foo(x: MyEnum): Int {
return when (x) {
return <!NO_ELSE_IN_WHEN!>when<!> (x) {
MyEnum.A -> 1
is <!UNRESOLVED_REFERENCE!>MyEnum.B<!> -> 2
is <!UNRESOLVED_REFERENCE!>MyEnum.C<!> -> 3
@@ -1,16 +0,0 @@
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
* expressions, when-expression -> paragraph 9 -> sentence 2
* expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1
*/
fun foo(x: Int) {
val y: Unit = when (x) {
2 -> {}
3 -> {}
}
return y
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -1,15 +0,0 @@
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
* expressions, when-expression -> paragraph 9 -> sentence 2
* expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1
*/
fun foo(x: Int): Any {
val v = when (x) {
2 -> 0
}
return v
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -1,14 +0,0 @@
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
* expressions, when-expression -> paragraph 9 -> sentence 2
* expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1
*/
fun foo(x: Int): Any {
return when (x) {
2 -> 0
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -1,16 +0,0 @@
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
* expressions, when-expression -> paragraph 9 -> sentence 2
* expressions, when-expression, exhaustive-when-expressions -> paragraph 1 -> sentence 1
*/
fun foo(x: Int) {
return when (x) {
2 -> {}
3 -> {}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE)
*
@@ -1,29 +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
*/
// See KT-6399: exhaustive whens on platform enums
// FILE: J.java
public enum J {
A, B;
public static J create() {
return J.A;
}
}
// FILE: K.kt
fun foo(): Int {
// When is not-exhaustive
return when (J.create()) {
J.A -> 1
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
@@ -13,7 +13,7 @@
enum class X { A, B }
fun foo(arg: X?): Int {
if (arg != null) {
return when (arg) {
return <!NO_ELSE_IN_WHEN!>when<!> (arg) {
X.B -> 2
}
}
@@ -1,32 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*
* SPEC VERSION: 0.1-152
* PRIMARY LINKS: expressions, when-expression -> paragraph 5 -> sentence 1
* expressions, when-expression -> paragraph 6 -> sentence 1
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 6
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 7
* expressions, when-expression, exhaustive-when-expressions -> paragraph 2 -> sentence 8
*/
sealed class A {
class B: A() {
class C: A()
}
}
class D: A()
fun test(a: A) {
val nonExhaustive = when (a) {
is A.B -> "B"
is A.B.C -> "C"
}
val exhaustive = when (a) {
is A.B -> "B"
is A.B.C -> "C"
is D -> "D"
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
+1 -1
View File
@@ -27,7 +27,7 @@ fun foo(): Int {
fun bar(): Int {
val a = "a"
if (a.length > 0) {
return when (a) {
return <!NO_ELSE_IN_WHEN!>when<!> (a) {
"a" -> 1
}
}
@@ -38,4 +38,4 @@ fun test4() {
2 -> bar(x, y)
}
}
}
}
@@ -1,18 +0,0 @@
// !LANGUAGE: +VariableDeclarationInWhenSubject
// !DIAGNOSTICS: -UNUSED_VARIABLE
enum class E { FIRST, SECOND }
fun testSmartcastToEnumInSubjectInitializer1(e: E?) {
val x1 = when (val ne = e!!) {
E.FIRST -> "f"
E.SECOND -> "s"
}
}
fun testSmartcastToEnumInSubjectInitializer2(e: E?) {
val x2 = when (val ne: Any = e!!) { // NB explicit type annotation
E.FIRST -> "f"
E.SECOND -> "s"
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +VariableDeclarationInWhenSubject
// !DIAGNOSTICS: -UNUSED_VARIABLE
@@ -1,20 +0,0 @@
// !LANGUAGE: +VariableDeclarationInWhenSubject
// !DIAGNOSTICS: -UNUSED_VARIABLE
sealed class Either
class Left : Either()
class Right : Either()
fun testSmartcastToSealedInSubjectInitializer1(x: Any?) {
val y1 = when (val either = x as Either) {
is Left -> "L"
is Right -> "R"
}
}
fun testSmartcastToSealedInSubjectInitializer2(x: Any?) {
val y2 = when (val either: Any = x as Either) { // NB explicit type annotation
is Left -> "L"
is Right -> "R"
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +VariableDeclarationInWhenSubject
// !DIAGNOSTICS: -UNUSED_VARIABLE