[FIR] Implement checker for exhaustive when's in expression position
This commit is contained in:
+99
-40
@@ -139,46 +139,6 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/enumWithCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveWhenAndDNNType.kt")
|
||||
public void testExhaustiveWhenAndDNNType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveWhenAndFlexibleType.kt")
|
||||
public void testExhaustiveWhenAndFlexibleType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_boolean.kt")
|
||||
public void testExhaustiveness_boolean() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_enum.kt")
|
||||
public void testExhaustiveness_enum() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_enumJava.kt")
|
||||
public void testExhaustiveness_enumJava() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_sealedClass.kt")
|
||||
public void testExhaustiveness_sealedClass() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_sealedObject.kt")
|
||||
public void testExhaustiveness_sealedObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_sealedSubClass.kt")
|
||||
public void testExhaustiveness_sealedSubClass() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("extension.kt")
|
||||
public void testExtension() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/extension.kt");
|
||||
@@ -1271,6 +1231,105 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Exhaustiveness extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInExhaustiveness() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Negative extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInNegative() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("missingBooleanBranch.kt")
|
||||
public void testMissingBooleanBranch() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("missingElse.kt")
|
||||
public void testMissingElse() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("missingEnumEntry.kt")
|
||||
public void testMissingEnumEntry() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("missingSealedInheritor.kt")
|
||||
public void testMissingSealedInheritor() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Positive extends AbstractLazyBodyIsNotTouchedTilContractsPhaseTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInPositive() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveWhenAndDNNType.kt")
|
||||
public void testExhaustiveWhenAndDNNType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveWhenAndFlexibleType.kt")
|
||||
public void testExhaustiveWhenAndFlexibleType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_boolean.kt")
|
||||
public void testExhaustiveness_boolean() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_enum.kt")
|
||||
public void testExhaustiveness_enum() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_enumJava.kt")
|
||||
public void testExhaustiveness_enumJava() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_sealedClass.kt")
|
||||
public void testExhaustiveness_sealedClass() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_sealedObject.kt")
|
||||
public void testExhaustiveness_sealedObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_sealedSubClass.kt")
|
||||
public void testExhaustiveness_sealedSubClass() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/expresssions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Vendored
+55
@@ -0,0 +1,55 @@
|
||||
FILE: missingBooleanBranch.kt
|
||||
public final fun test_1(cond: R|kotlin/Boolean|): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Unit| = when (R|<local>/cond|) {
|
||||
==($subj$, Boolean(true)) -> {
|
||||
Int(1)
|
||||
}
|
||||
}
|
||||
|
||||
lval y: R|kotlin/Unit| = when (R|<local>/cond|) {
|
||||
==($subj$, Boolean(false)) -> {
|
||||
Int(2)
|
||||
}
|
||||
}
|
||||
|
||||
lval z: R|kotlin/Int| = when (R|<local>/cond|) {
|
||||
==($subj$, Boolean(true)) -> {
|
||||
Int(1)
|
||||
}
|
||||
==($subj$, Boolean(false)) -> {
|
||||
Int(2)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test_2(cond: R|kotlin/Boolean?|): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Unit| = when (R|<local>/cond|) {
|
||||
==($subj$, Boolean(true)) -> {
|
||||
Int(1)
|
||||
}
|
||||
==($subj$, Boolean(false)) -> {
|
||||
Int(2)
|
||||
}
|
||||
}
|
||||
|
||||
lval x: R|kotlin/Int| = when (R|<local>/cond|) {
|
||||
==($subj$, Boolean(true)) -> {
|
||||
Int(1)
|
||||
}
|
||||
==($subj$, Boolean(false)) -> {
|
||||
Int(2)
|
||||
}
|
||||
==($subj$, Null(null)) -> {
|
||||
Int(3)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test_3(cond: R|kotlin/Boolean|): R|kotlin/Unit| {
|
||||
when (R|<local>/cond|) {
|
||||
==($subj$, Boolean(true)) -> {
|
||||
Int(1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
fun test_1(cond: Boolean) {
|
||||
val x = <!NO_ELSE_IN_WHEN!>when<!> (cond) {
|
||||
true -> 1
|
||||
}
|
||||
|
||||
val y = <!NO_ELSE_IN_WHEN!>when<!> (cond) {
|
||||
false -> 2
|
||||
}
|
||||
|
||||
val z = when (cond) {
|
||||
true -> 1
|
||||
false -> 2
|
||||
}
|
||||
}
|
||||
|
||||
fun test_2(cond: Boolean?) {
|
||||
val x = <!NO_ELSE_IN_WHEN!>when<!> (cond) {
|
||||
true -> 1
|
||||
false -> 2
|
||||
}
|
||||
|
||||
val x = when (cond) {
|
||||
true -> 1
|
||||
false -> 2
|
||||
null -> 3
|
||||
}
|
||||
}
|
||||
|
||||
fun test_3(cond: Boolean) {
|
||||
when (cond) {
|
||||
true -> 1
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
FILE: missingElse.kt
|
||||
public final fun test(a: R|kotlin/Any|): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Unit| = when (R|<local>/a|) {
|
||||
($subj$ is R|kotlin/Int|) -> {
|
||||
Int(1)
|
||||
}
|
||||
($subj$ is R|kotlin/String|) -> {
|
||||
Int(2)
|
||||
}
|
||||
}
|
||||
|
||||
lval y: R|kotlin/Int| = when (R|<local>/a|) {
|
||||
else -> {
|
||||
Int(1)
|
||||
}
|
||||
}
|
||||
|
||||
lval z: R|kotlin/Int| = when (R|<local>/a|) {
|
||||
($subj$ is R|kotlin/Int|) -> {
|
||||
Int(1)
|
||||
}
|
||||
($subj$ is R|kotlin/String|) -> {
|
||||
Int(2)
|
||||
}
|
||||
else -> {
|
||||
Int(3)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test_2(a: R|kotlin/Any|): R|kotlin/Unit| {
|
||||
when (R|<local>/a|) {
|
||||
($subj$ is R|kotlin/String|) -> {
|
||||
Int(1)
|
||||
}
|
||||
($subj$ is R|kotlin/Int|) -> {
|
||||
Int(2)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
fun test(a: Any) {
|
||||
val x = <!NO_ELSE_IN_WHEN!>when<!> (a) {
|
||||
is Int -> 1
|
||||
is String -> 2
|
||||
}
|
||||
|
||||
val y = when (a) {
|
||||
else -> 1
|
||||
}
|
||||
|
||||
val z = when (a) {
|
||||
is Int -> 1
|
||||
is String -> 2
|
||||
else -> 3
|
||||
}
|
||||
}
|
||||
|
||||
fun test_2(a: Any) {
|
||||
when (a) {
|
||||
is String -> 1
|
||||
is Int -> 2
|
||||
}
|
||||
}
|
||||
Vendored
+63
@@ -0,0 +1,63 @@
|
||||
FILE: missingEnumEntry.kt
|
||||
public final enum class SomeEnum : R|kotlin/Enum<SomeEnum>| {
|
||||
private constructor(): R|SomeEnum| {
|
||||
super<R|kotlin/Enum<SomeEnum>|>()
|
||||
}
|
||||
|
||||
public final static enum entry A: R|SomeEnum|
|
||||
public final static enum entry B: R|SomeEnum|
|
||||
public final static fun values(): R|kotlin/Array<SomeEnum>| {
|
||||
}
|
||||
|
||||
public final static fun valueOf(value: R|kotlin/String|): R|SomeEnum| {
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test_1(enum: R|SomeEnum|): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Unit| = when (R|<local>/enum|) {
|
||||
==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> {
|
||||
Int(1)
|
||||
}
|
||||
}
|
||||
|
||||
lval y: R|kotlin/Int| = when (R|<local>/enum|) {
|
||||
==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> {
|
||||
Int(1)
|
||||
}
|
||||
==($subj$, Q|SomeEnum|.R|/SomeEnum.B|) -> {
|
||||
Int(2)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test_2(enum: R|SomeEnum?|): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Unit| = when (R|<local>/enum|) {
|
||||
==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> {
|
||||
Int(1)
|
||||
}
|
||||
==($subj$, Q|SomeEnum|.R|/SomeEnum.B|) -> {
|
||||
Int(2)
|
||||
}
|
||||
}
|
||||
|
||||
lval y: R|kotlin/Int| = when (R|<local>/enum|) {
|
||||
==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> {
|
||||
Int(1)
|
||||
}
|
||||
==($subj$, Q|SomeEnum|.R|/SomeEnum.B|) -> {
|
||||
Int(2)
|
||||
}
|
||||
==($subj$, Null(null)) -> {
|
||||
Int(3)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test_3(enum: R|SomeEnum|): R|kotlin/Unit| {
|
||||
when (R|<local>/enum|) {
|
||||
==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> {
|
||||
Int(1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
enum class SomeEnum {
|
||||
A, B
|
||||
}
|
||||
|
||||
fun test_1(enum: SomeEnum) {
|
||||
val x = <!NO_ELSE_IN_WHEN!>when<!> (enum) {
|
||||
SomeEnum.A -> 1
|
||||
}
|
||||
|
||||
val y = when (enum) {
|
||||
SomeEnum.A -> 1
|
||||
SomeEnum.B -> 2
|
||||
}
|
||||
}
|
||||
|
||||
fun test_2(enum: SomeEnum?) {
|
||||
val x = <!NO_ELSE_IN_WHEN!>when<!> (enum) {
|
||||
SomeEnum.A -> 1
|
||||
SomeEnum.B -> 2
|
||||
}
|
||||
|
||||
val y = when (enum) {
|
||||
SomeEnum.A -> 1
|
||||
SomeEnum.B -> 2
|
||||
null -> 3
|
||||
}
|
||||
}
|
||||
|
||||
fun test_3(enum: SomeEnum) {
|
||||
when (enum) {
|
||||
SomeEnum.A -> 1
|
||||
}
|
||||
}
|
||||
Vendored
+84
@@ -0,0 +1,84 @@
|
||||
FILE: a.kt
|
||||
public sealed class Base : R|kotlin/Any| {
|
||||
private constructor(): R|Base| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
}
|
||||
public final class A : R|Base| {
|
||||
public constructor(): R|A| {
|
||||
super<R|Base|>()
|
||||
}
|
||||
|
||||
}
|
||||
FILE: b.kt
|
||||
public final object B : R|Base| {
|
||||
private constructor(): R|B| {
|
||||
super<R|Base|>()
|
||||
}
|
||||
|
||||
}
|
||||
FILE: c.kt
|
||||
public final fun test_1(base: R|Base|): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Unit| = when (R|<local>/base|) {
|
||||
($subj$ is R|A|) -> {
|
||||
Int(1)
|
||||
}
|
||||
}
|
||||
|
||||
lval y: R|kotlin/Unit| = when (R|<local>/base|) {
|
||||
==($subj$, Q|B|) -> {
|
||||
Int(1)
|
||||
}
|
||||
}
|
||||
|
||||
lval z: R|kotlin/Int| = when (R|<local>/base|) {
|
||||
($subj$ is R|A|) -> {
|
||||
Int(1)
|
||||
}
|
||||
==($subj$, Q|B|) -> {
|
||||
Int(2)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test_2(base: R|Base?|): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Unit| = when (R|<local>/base|) {
|
||||
($subj$ is R|A|) -> {
|
||||
Int(1)
|
||||
}
|
||||
($subj$ is R|B|) -> {
|
||||
Int(2)
|
||||
}
|
||||
}
|
||||
|
||||
lval y: R|kotlin/Unit| = when (R|<local>/base|) {
|
||||
($subj$ is R|A|) -> {
|
||||
Int(1)
|
||||
}
|
||||
==($subj$, Q|B|) -> {
|
||||
Int(2)
|
||||
}
|
||||
}
|
||||
|
||||
lval z: R|kotlin/Int| = when (R|<local>/base|) {
|
||||
($subj$ is R|A|) -> {
|
||||
Int(1)
|
||||
}
|
||||
==($subj$, Q|B|) -> {
|
||||
Int(2)
|
||||
}
|
||||
==($subj$, Null(null)) -> {
|
||||
Int(3)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test_3(base: R|Base|): R|kotlin/Unit| {
|
||||
when (R|<local>/base|) {
|
||||
($subj$ is R|A|) -> {
|
||||
Int(1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+50
@@ -0,0 +1,50 @@
|
||||
// FILE: a.kt
|
||||
|
||||
sealed class Base
|
||||
|
||||
class A : Base
|
||||
|
||||
// FILE: b.kt
|
||||
|
||||
object B : Base()
|
||||
|
||||
// FILE: c.kt
|
||||
|
||||
fun test_1(base: Base) {
|
||||
val x = <!NO_ELSE_IN_WHEN!>when<!> (base) {
|
||||
is A -> 1
|
||||
}
|
||||
|
||||
val y = <!NO_ELSE_IN_WHEN!>when<!> (base) {
|
||||
B -> 1
|
||||
}
|
||||
|
||||
val z = when (base) {
|
||||
is A -> 1
|
||||
B -> 2
|
||||
}
|
||||
}
|
||||
|
||||
fun test_2(base: Base?) {
|
||||
val x = <!NO_ELSE_IN_WHEN!>when<!> (base) {
|
||||
is A -> 1
|
||||
is B -> 2
|
||||
}
|
||||
|
||||
val y = <!NO_ELSE_IN_WHEN!>when<!> (base) {
|
||||
is A -> 1
|
||||
B -> 2
|
||||
}
|
||||
|
||||
val z = when (base) {
|
||||
is A -> 1
|
||||
B -> 2
|
||||
null -> 3
|
||||
}
|
||||
}
|
||||
|
||||
fun test_3(base: Base) {
|
||||
when (base) {
|
||||
is A -> 1
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
fun test_1(b: Boolean) {
|
||||
val x = when (b) {
|
||||
val x = <!NO_ELSE_IN_WHEN!>when<!> (b) {
|
||||
true -> 1
|
||||
}
|
||||
val y = when (b) {
|
||||
@@ -13,7 +13,7 @@ fun test_1(b: Boolean) {
|
||||
}
|
||||
|
||||
fun test_2(b: Boolean?) {
|
||||
val x = when (b) {
|
||||
val x = <!NO_ELSE_IN_WHEN!>when<!> (b) {
|
||||
true -> 1
|
||||
false -> 2
|
||||
}
|
||||
+3
-3
@@ -3,12 +3,12 @@ enum class Enum {
|
||||
}
|
||||
|
||||
fun test_1(e: Enum) {
|
||||
val a = when (e) {
|
||||
val a = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
Enum.A -> 1
|
||||
Enum.B -> 2
|
||||
}
|
||||
|
||||
val b = when (e) {
|
||||
val b = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
Enum.A -> 1
|
||||
Enum.B -> 2
|
||||
is String -> 3
|
||||
@@ -27,7 +27,7 @@ fun test_1(e: Enum) {
|
||||
}
|
||||
|
||||
fun test_2(e: Enum?) {
|
||||
val a = when (e) {
|
||||
val a = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
Enum.A -> 1
|
||||
Enum.B -> 2
|
||||
Enum.C -> 3
|
||||
+3
-3
@@ -7,12 +7,12 @@ public enum JavaEnum {
|
||||
|
||||
// FILE: main.kt
|
||||
fun test_1(e: JavaEnum) {
|
||||
val a = when (e) {
|
||||
val a = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
JavaEnum.A -> 1
|
||||
JavaEnum.B -> 2
|
||||
}.<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>plus<!>(0)<!>
|
||||
|
||||
val b = when (e) {
|
||||
val b = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
JavaEnum.A -> 1
|
||||
JavaEnum.B -> 2
|
||||
is String -> 3
|
||||
@@ -31,7 +31,7 @@ fun test_1(e: JavaEnum) {
|
||||
}
|
||||
|
||||
fun test_2(e: JavaEnum?) {
|
||||
val a = when (e) {
|
||||
val a = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
JavaEnum.A -> 1
|
||||
JavaEnum.B -> 2
|
||||
JavaEnum.C -> 3
|
||||
+3
-3
@@ -7,12 +7,12 @@ sealed class Base {
|
||||
class C : Base()
|
||||
|
||||
fun test_1(e: Base) {
|
||||
val a = when (e) {
|
||||
val a = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
is Base.A -> 1
|
||||
is Base.A.B -> 2
|
||||
}
|
||||
|
||||
val b = when (e) {
|
||||
val b = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
is Base.A -> 1
|
||||
is Base.A.B -> 2
|
||||
is String -> 3
|
||||
@@ -31,7 +31,7 @@ fun test_1(e: Base) {
|
||||
}
|
||||
|
||||
fun test_2(e: Base?) {
|
||||
val a = when (e) {
|
||||
val a = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
is Base.A -> 1
|
||||
is Base.A.B -> 2
|
||||
is C -> 3
|
||||
+4
-4
@@ -32,23 +32,23 @@ fun test_1(e: A) {
|
||||
}
|
||||
|
||||
fun test_2(e: A) {
|
||||
val a = when (e) {
|
||||
val a = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
is D -> 1
|
||||
is E -> 2
|
||||
}.<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>plus<!>(0)<!>
|
||||
|
||||
val b = when (e) {
|
||||
val b = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
is B -> 1
|
||||
is D -> 2
|
||||
is E -> 3
|
||||
}.<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>plus<!>(0)<!>
|
||||
|
||||
val c = when (e) {
|
||||
val c = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
is B -> 1
|
||||
is D -> 2
|
||||
}.<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>plus<!>(0)<!>
|
||||
|
||||
val d = when (e) {
|
||||
val d = <!NO_ELSE_IN_WHEN!>when<!> (e) {
|
||||
is C -> 1
|
||||
}.<!UNRESOLVED_REFERENCE{LT}!><!UNRESOLVED_REFERENCE{PSI}!>plus<!>(0)<!>
|
||||
}
|
||||
@@ -16,12 +16,12 @@ fun get(f: Boolean) = if (f) {A.A1} else {""}
|
||||
<!CONFLICTING_OVERLOADS!>fun case2()<!> {
|
||||
|
||||
val flag: Any = get(false) //string
|
||||
val l1 = when (flag!!) { // should be NO_ELSE_IN_WHEN
|
||||
val l1 = <!NO_ELSE_IN_WHEN!>when<!> (flag!!) { // should be NO_ELSE_IN_WHEN
|
||||
A.A1 -> B()
|
||||
A.A2 -> B()
|
||||
}
|
||||
|
||||
val l2 = when (flag) {// should be NO_ELSE_IN_WHEN
|
||||
val l2 = <!NO_ELSE_IN_WHEN!>when<!> (flag) {// should be NO_ELSE_IN_WHEN
|
||||
A.A1 -> B()
|
||||
A.A2 -> B()
|
||||
}
|
||||
@@ -30,12 +30,12 @@ fun get(f: Boolean) = if (f) {A.A1} else {""}
|
||||
<!CONFLICTING_OVERLOADS!>fun case2()<!> {
|
||||
|
||||
val flag: Any = get(true) //A
|
||||
val l1 = when (flag!!) {// should be NO_ELSE_IN_WHEN
|
||||
val l1 = <!NO_ELSE_IN_WHEN!>when<!> (flag!!) {// should be NO_ELSE_IN_WHEN
|
||||
A.A1 -> B()
|
||||
A.A2 -> B()
|
||||
}
|
||||
|
||||
val l2 = when (flag) {// should be NO_ELSE_IN_WHEN
|
||||
val l2 = <!NO_ELSE_IN_WHEN!>when<!> (flag) {// should be NO_ELSE_IN_WHEN
|
||||
A.A1 -> B()
|
||||
A.A2 -> B()
|
||||
}
|
||||
@@ -44,12 +44,12 @@ fun get(f: Boolean) = if (f) {A.A1} else {""}
|
||||
fun case3() {
|
||||
|
||||
val flag = "" //A
|
||||
val l1 = when (flag!!) {// should be NO_ELSE_IN_WHEN
|
||||
val l1 = <!NO_ELSE_IN_WHEN!>when<!> (flag!!) {// should be NO_ELSE_IN_WHEN
|
||||
A.A1 -> B() //should be INCOMPATIBLE_TYPES
|
||||
A.A2 -> B() //should be INCOMPATIBLE_TYPES
|
||||
}
|
||||
|
||||
val l2 = when (flag) {// should be NO_ELSE_IN_WHEN
|
||||
val l2 = <!NO_ELSE_IN_WHEN!>when<!> (flag) {// should be NO_ELSE_IN_WHEN
|
||||
A.A1 -> B() //should be INCOMPATIBLE_TYPES
|
||||
A.A2 -> B() //should be INCOMPATIBLE_TYPES
|
||||
}
|
||||
|
||||
+102
-48
@@ -158,54 +158,6 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/enumWithCompanion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveWhenAndDNNType.kt")
|
||||
public void testExhaustiveWhenAndDNNType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveWhenAndFlexibleType.kt")
|
||||
public void testExhaustiveWhenAndFlexibleType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_boolean.kt")
|
||||
public void testExhaustiveness_boolean() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_enum.kt")
|
||||
public void testExhaustiveness_enum() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_enumJava.kt")
|
||||
public void testExhaustiveness_enumJava() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_sealedClass.kt")
|
||||
public void testExhaustiveness_sealedClass() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_sealedObject.kt")
|
||||
public void testExhaustiveness_sealedObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_sealedSubClass.kt")
|
||||
public void testExhaustiveness_sealedSubClass() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("extension.kt")
|
||||
public void testExtension() throws Exception {
|
||||
@@ -1466,6 +1418,108 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Exhaustiveness {
|
||||
@Test
|
||||
public void testAllFilesPresentInExhaustiveness() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Negative {
|
||||
@Test
|
||||
public void testAllFilesPresentInNegative() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("missingBooleanBranch.kt")
|
||||
public void testMissingBooleanBranch() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("missingElse.kt")
|
||||
public void testMissingElse() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("missingEnumEntry.kt")
|
||||
public void testMissingEnumEntry() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("missingSealedInheritor.kt")
|
||||
public void testMissingSealedInheritor() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Positive {
|
||||
@Test
|
||||
public void testAllFilesPresentInPositive() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveWhenAndDNNType.kt")
|
||||
public void testExhaustiveWhenAndDNNType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveWhenAndFlexibleType.kt")
|
||||
public void testExhaustiveWhenAndFlexibleType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_boolean.kt")
|
||||
public void testExhaustiveness_boolean() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_enum.kt")
|
||||
public void testExhaustiveness_enum() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_enumJava.kt")
|
||||
public void testExhaustiveness_enumJava() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_sealedClass.kt")
|
||||
public void testExhaustiveness_sealedClass() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_sealedObject.kt")
|
||||
public void testExhaustiveness_sealedObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_sealedSubClass.kt")
|
||||
public void testExhaustiveness_sealedSubClass() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/expresssions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+105
-48
@@ -161,54 +161,6 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/enumWithCompanion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveWhenAndDNNType.kt")
|
||||
public void testExhaustiveWhenAndDNNType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveWhenAndFlexibleType.kt")
|
||||
public void testExhaustiveWhenAndFlexibleType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_boolean.kt")
|
||||
public void testExhaustiveness_boolean() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_enum.kt")
|
||||
public void testExhaustiveness_enum() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_enumJava.kt")
|
||||
public void testExhaustiveness_enumJava() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_sealedClass.kt")
|
||||
public void testExhaustiveness_sealedClass() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_sealedObject.kt")
|
||||
public void testExhaustiveness_sealedObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_sealedSubClass.kt")
|
||||
public void testExhaustiveness_sealedSubClass() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("extension.kt")
|
||||
public void testExtension() throws Exception {
|
||||
@@ -1478,6 +1430,111 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Execution(ExecutionMode.SAME_THREAD)
|
||||
public class Exhaustiveness {
|
||||
@Test
|
||||
public void testAllFilesPresentInExhaustiveness() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Execution(ExecutionMode.SAME_THREAD)
|
||||
public class Negative {
|
||||
@Test
|
||||
public void testAllFilesPresentInNegative() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("missingBooleanBranch.kt")
|
||||
public void testMissingBooleanBranch() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("missingElse.kt")
|
||||
public void testMissingElse() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("missingEnumEntry.kt")
|
||||
public void testMissingEnumEntry() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("missingSealedInheritor.kt")
|
||||
public void testMissingSealedInheritor() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Execution(ExecutionMode.SAME_THREAD)
|
||||
public class Positive {
|
||||
@Test
|
||||
public void testAllFilesPresentInPositive() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveWhenAndDNNType.kt")
|
||||
public void testExhaustiveWhenAndDNNType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveWhenAndFlexibleType.kt")
|
||||
public void testExhaustiveWhenAndFlexibleType() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_boolean.kt")
|
||||
public void testExhaustiveness_boolean() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_enum.kt")
|
||||
public void testExhaustiveness_enum() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_enumJava.kt")
|
||||
public void testExhaustiveness_enumJava() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_sealedClass.kt")
|
||||
public void testExhaustiveness_sealedClass() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_sealedObject.kt")
|
||||
public void testExhaustiveness_sealedObject() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exhaustiveness_sealedSubClass.kt")
|
||||
public void testExhaustiveness_sealedSubClass() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/expresssions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+2
-5
@@ -6,11 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.checkers.generator
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||
import org.jetbrains.kotlin.fir.expressions.FirTryExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import java.io.File
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
@@ -23,6 +19,7 @@ fun main(args: Array<String>) {
|
||||
alias<FirFunctionCall>("FunctionCallChecker")
|
||||
alias<FirVariableAssignment>("VariableAssignmentChecker")
|
||||
alias<FirTryExpression>("TryExpressionChecker")
|
||||
alias<FirWhenExpression>("WhenExpressionChecker")
|
||||
}
|
||||
|
||||
val declarationPackage = "org.jetbrains.kotlin.fir.analysis.checkers.declaration"
|
||||
|
||||
+4
@@ -23,12 +23,15 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() {
|
||||
get() = _variableAssignmentCheckers
|
||||
override val tryExpressionCheckers: Set<FirTryExpressionChecker>
|
||||
get() = _tryExpressionCheckers
|
||||
override val whenExpressionCheckers: Set<FirWhenExpressionChecker>
|
||||
get() = _whenExpressionCheckers
|
||||
|
||||
private val _basicExpressionCheckers: MutableSet<FirBasicExpressionChecker> = mutableSetOf()
|
||||
private val _qualifiedAccessCheckers: MutableSet<FirQualifiedAccessChecker> = mutableSetOf()
|
||||
private val _functionCallCheckers: MutableSet<FirFunctionCallChecker> = mutableSetOf()
|
||||
private val _variableAssignmentCheckers: MutableSet<FirVariableAssignmentChecker> = mutableSetOf()
|
||||
private val _tryExpressionCheckers: MutableSet<FirTryExpressionChecker> = mutableSetOf()
|
||||
private val _whenExpressionCheckers: MutableSet<FirWhenExpressionChecker> = mutableSetOf()
|
||||
|
||||
@CheckersComponentInternal
|
||||
internal fun register(checkers: ExpressionCheckers) {
|
||||
@@ -37,5 +40,6 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() {
|
||||
_functionCallCheckers += checkers.allFunctionCallCheckers
|
||||
_variableAssignmentCheckers += checkers.allVariableAssignmentCheckers
|
||||
_tryExpressionCheckers += checkers.allTryExpressionCheckers
|
||||
_whenExpressionCheckers += checkers.allWhenExpressionCheckers
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -22,10 +22,12 @@ abstract class ExpressionCheckers {
|
||||
open val functionCallCheckers: Set<FirFunctionCallChecker> = emptySet()
|
||||
open val variableAssignmentCheckers: Set<FirVariableAssignmentChecker> = emptySet()
|
||||
open val tryExpressionCheckers: Set<FirTryExpressionChecker> = emptySet()
|
||||
open val whenExpressionCheckers: Set<FirWhenExpressionChecker> = emptySet()
|
||||
|
||||
@CheckersComponentInternal internal val allBasicExpressionCheckers: Set<FirBasicExpressionChecker> get() = basicExpressionCheckers
|
||||
@CheckersComponentInternal internal val allQualifiedAccessCheckers: Set<FirQualifiedAccessChecker> get() = qualifiedAccessCheckers + allBasicExpressionCheckers
|
||||
@CheckersComponentInternal internal val allFunctionCallCheckers: Set<FirFunctionCallChecker> get() = functionCallCheckers + allQualifiedAccessCheckers
|
||||
@CheckersComponentInternal internal val allVariableAssignmentCheckers: Set<FirVariableAssignmentChecker> get() = variableAssignmentCheckers + allBasicExpressionCheckers
|
||||
@CheckersComponentInternal internal val allTryExpressionCheckers: Set<FirTryExpressionChecker> get() = tryExpressionCheckers + allBasicExpressionCheckers
|
||||
@CheckersComponentInternal internal val allWhenExpressionCheckers: Set<FirWhenExpressionChecker> get() = whenExpressionCheckers + allBasicExpressionCheckers
|
||||
}
|
||||
|
||||
+2
@@ -15,9 +15,11 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.expressions.FirTryExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
|
||||
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
|
||||
|
||||
typealias FirBasicExpressionChecker = FirExpressionChecker<FirStatement>
|
||||
typealias FirQualifiedAccessChecker = FirExpressionChecker<FirQualifiedAccessExpression>
|
||||
typealias FirFunctionCallChecker = FirExpressionChecker<FirFunctionCall>
|
||||
typealias FirVariableAssignmentChecker = FirExpressionChecker<FirVariableAssignment>
|
||||
typealias FirTryExpressionChecker = FirExpressionChecker<FirTryExpression>
|
||||
typealias FirWhenExpressionChecker = FirExpressionChecker<FirWhenExpression>
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.fir.analysis.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
|
||||
|
||||
object FirExhaustiveWhenChecker : FirWhenExpressionChecker() {
|
||||
override fun check(expression: FirWhenExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
// TODO: add reporting of proper missing clauses, see class WhenMissingCase
|
||||
if (expression.usedAsExpression && !expression.isExhaustive) {
|
||||
val factory = if (expression.source?.isIfExpression == true) {
|
||||
FirErrors.INVALID_IF_AS_EXPRESSION
|
||||
} else {
|
||||
FirErrors.NO_ELSE_IN_WHEN
|
||||
}
|
||||
reporter.reportOn(expression.source, factory, context)
|
||||
}
|
||||
}
|
||||
|
||||
private val FirSourceElement.isIfExpression: Boolean
|
||||
get() = elementType == KtNodeTypes.IF
|
||||
}
|
||||
+1
-1
@@ -53,7 +53,7 @@ class ExpressionCheckersDiagnosticComponent(collector: AbstractDiagnosticCollect
|
||||
}
|
||||
|
||||
override fun visitWhenExpression(whenExpression: FirWhenExpression, data: CheckerContext) {
|
||||
checkers.basicExpressionCheckers.check(whenExpression, data, reporter)
|
||||
checkers.whenExpressionCheckers.check(whenExpression, data, reporter)
|
||||
}
|
||||
|
||||
override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression, data: CheckerContext) {
|
||||
|
||||
+6
@@ -84,6 +84,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_REQUI
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INTERFACE_WITH_SUPERCLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_IF_AS_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVALID_TYPE_OF_ANNOTATION_MEMBER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LEAKED_IN_PLACE_LAMBDA
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LOCAL_ANNOTATION_CLASS_ERROR
|
||||
@@ -100,6 +101,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_OVERRI
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_LOOP_LABEL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ELSE_IN_WHEN
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_THIS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_TYPE_FOR_TYPE_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER
|
||||
@@ -501,6 +503,10 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
// RENDER_TYPE
|
||||
//)
|
||||
|
||||
// When expressions
|
||||
map.put(NO_ELSE_IN_WHEN, "''when'' expression must be exhaustive")
|
||||
map.put(INVALID_IF_AS_EXPRESSION, "'if' must have both main and 'else' branches if used as an expression")
|
||||
|
||||
// Extended checkers group
|
||||
map.put(REDUNDANT_VISIBILITY_MODIFIER, "Redundant visibility modifier")
|
||||
map.put(REDUNDANT_MODALITY_MODIFIER, "Redundant modality modifier")
|
||||
|
||||
@@ -230,6 +230,10 @@ object FirErrors {
|
||||
// TODO: val UNSAFE_OPERATOR_CALL by ...
|
||||
// TODO: val UNEXPECTED_SAFE_CALL by ...
|
||||
|
||||
// When expressions
|
||||
val NO_ELSE_IN_WHEN by error0<FirSourceElement, KtWhenExpression>(SourceElementPositioningStrategies.WHEN_EXPRESSION)
|
||||
val INVALID_IF_AS_EXPRESSION by error0<FirSourceElement, KtIfExpression>(SourceElementPositioningStrategies.IF_EXPRESSION)
|
||||
|
||||
// Extended checkers group
|
||||
val REDUNDANT_VISIBILITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||
val REDUNDANT_MODALITY_MODIFIER by warning0<FirSourceElement, KtModifierListOwner>(SourceElementPositioningStrategies.MODALITY_MODIFIER)
|
||||
|
||||
+28
@@ -334,6 +334,28 @@ object LightTreePositioningStrategies {
|
||||
return super.mark(node, startOffset, endOffset, tree)
|
||||
}
|
||||
}
|
||||
|
||||
val WHEN_EXPRESSION = object : LightTreePositioningStrategy() {
|
||||
override fun mark(
|
||||
node: LighterASTNode,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
): List<TextRange> {
|
||||
return markElement(tree.whenKeyword(node) ?: node, startOffset, endOffset, tree, node)
|
||||
}
|
||||
}
|
||||
|
||||
val IF_EXPRESSION = object : LightTreePositioningStrategy() {
|
||||
override fun mark(
|
||||
node: LighterASTNode,
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
tree: FlyweightCapableTreeStructure<LighterASTNode>
|
||||
): List<TextRange> {
|
||||
return markElement(tree.ifKeyword(node) ?: node, startOffset, endOffset, tree, node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun FirSourceElement.hasValOrVar(): Boolean =
|
||||
@@ -354,6 +376,12 @@ private fun FlyweightCapableTreeStructure<LighterASTNode>.dotOperator(node: Ligh
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.initKeyword(node: LighterASTNode): LighterASTNode? =
|
||||
findChildByType(node, KtTokens.INIT_KEYWORD)
|
||||
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.whenKeyword(node: LighterASTNode): LighterASTNode? =
|
||||
findChildByType(node, KtTokens.WHEN_KEYWORD)
|
||||
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.ifKeyword(node: LighterASTNode): LighterASTNode? =
|
||||
findChildByType(node, KtTokens.IF_KEYWORD)
|
||||
|
||||
private fun FlyweightCapableTreeStructure<LighterASTNode>.nameIdentifier(node: LighterASTNode): LighterASTNode? =
|
||||
findChildByType(node, KtTokens.IDENTIFIER)
|
||||
|
||||
|
||||
+11
-1
@@ -102,4 +102,14 @@ object SourceElementPositioningStrategies {
|
||||
LightTreePositioningStrategies.DOT_BY_SELECTOR,
|
||||
PositioningStrategies.DOT_BY_SELECTOR
|
||||
)
|
||||
}
|
||||
|
||||
val WHEN_EXPRESSION = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.WHEN_EXPRESSION,
|
||||
PositioningStrategies.WHEN_EXPRESSION
|
||||
)
|
||||
|
||||
val IF_EXPRESSION = SourceElementPositioningStrategy(
|
||||
LightTreePositioningStrategies.IF_EXPRESSION,
|
||||
PositioningStrategies.IF_EXPRESSION
|
||||
)
|
||||
}
|
||||
|
||||
+4
@@ -28,4 +28,8 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
override val tryExpressionCheckers: Set<FirTryExpressionChecker> = setOf(
|
||||
FirCatchParameterChecker
|
||||
)
|
||||
|
||||
override val whenExpressionCheckers: Set<FirWhenExpressionChecker> = setOf(
|
||||
FirExhaustiveWhenChecker
|
||||
)
|
||||
}
|
||||
|
||||
+4
-1
@@ -1105,7 +1105,10 @@ class ExpressionsConverter(
|
||||
|
||||
private val LighterASTNode.usedAsExpression: Boolean
|
||||
get() {
|
||||
val parent = getParent() ?: return true
|
||||
var parent = getParent() ?: return true
|
||||
if (parent.elementType == ANNOTATED_EXPRESSION) {
|
||||
parent = parent.getParent() ?: return true
|
||||
}
|
||||
val parentTokenType = parent.tokenType
|
||||
if (parentTokenType == BLOCK) return false
|
||||
if (parentTokenType == ELSE || parentTokenType == WHEN_ENTRY) {
|
||||
|
||||
@@ -1625,6 +1625,10 @@ class RawFirBuilder(
|
||||
|
||||
private val KtExpression.usedAsExpression: Boolean
|
||||
get() {
|
||||
var parent = parent
|
||||
if (parent.elementType == KtNodeTypes.ANNOTATED_EXPRESSION) {
|
||||
parent = parent.parent
|
||||
}
|
||||
if (parent is KtBlockExpression) return false
|
||||
when (parent.elementType) {
|
||||
KtNodeTypes.ELSE, KtNodeTypes.WHEN_ENTRY -> {
|
||||
|
||||
@@ -507,6 +507,13 @@ object PositioningStrategies {
|
||||
}
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val IF_EXPRESSION: PositioningStrategy<KtIfExpression> = object : PositioningStrategy<KtIfExpression>() {
|
||||
override fun mark(element: KtIfExpression): List<TextRange> {
|
||||
return markElement(element.ifKeyword)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val WHEN_CONDITION_IN_RANGE: PositioningStrategy<KtWhenConditionInRange> = object : PositioningStrategy<KtWhenConditionInRange>() {
|
||||
override fun mark(element: KtWhenConditionInRange): List<TextRange> {
|
||||
|
||||
@@ -72,7 +72,7 @@ fun main1() {
|
||||
|
||||
1."sdf"
|
||||
1.{}
|
||||
1.if (true) {}
|
||||
1.<!INVALID_IF_AS_EXPRESSION!>if<!> (true) {}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
|
||||
@@ -70,7 +70,7 @@ fun blockReturnValueTypeMatch1() : Int {
|
||||
return if (1 > 2) 1.0 else 2.0
|
||||
}
|
||||
fun blockReturnValueTypeMatch2() : Int {
|
||||
return if (1 > 2) 1
|
||||
return <!INVALID_IF_AS_EXPRESSION!>if<!> (1 > 2) 1
|
||||
}
|
||||
fun blockReturnValueTypeMatch3() : Int {
|
||||
return if (1 > 2) else 1
|
||||
@@ -106,7 +106,7 @@ fun blockReturnValueTypeMatch9() : Int {
|
||||
1.0
|
||||
}
|
||||
fun blockReturnValueTypeMatch10() : Int {
|
||||
return if (1 > 2)
|
||||
return <!INVALID_IF_AS_EXPRESSION!>if<!> (1 > 2)
|
||||
1
|
||||
}
|
||||
fun blockReturnValueTypeMatch11() : Int {
|
||||
|
||||
@@ -29,7 +29,7 @@ fun foo(d: Direction) = when(d) { //no 'else' should be requested
|
||||
Direction.EAST -> 4
|
||||
}
|
||||
|
||||
fun foo1(d: Direction) = when(d) {
|
||||
fun foo1(d: Direction) = <!NO_ELSE_IN_WHEN!>when<!>(d) {
|
||||
Direction.NORTH -> 1
|
||||
Direction.SOUTH -> 2
|
||||
Direction.WEST -> 3
|
||||
@@ -41,7 +41,7 @@ fun bar(c: Color) = when (c) {
|
||||
Color.BLUE -> 3
|
||||
}
|
||||
|
||||
fun bar1(c: Color) = when (c) {
|
||||
fun bar1(c: Color) = <!NO_ELSE_IN_WHEN!>when<!> (c) {
|
||||
Color.RED -> 1
|
||||
Color.GREEN -> 2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
fun foo(x: Unit) = x
|
||||
|
||||
fun test() {
|
||||
if (false);
|
||||
if (true);
|
||||
|
||||
val x = if (false);
|
||||
foo(x)
|
||||
|
||||
val y: Unit = if (false);
|
||||
foo(y)
|
||||
|
||||
foo({if (1==1);}())
|
||||
|
||||
return if (true);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
fun foo(x: Unit) = x
|
||||
|
||||
fun test() {
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ fun testMixedIfAndWhen() =
|
||||
else 1
|
||||
true -> if (true) 42
|
||||
else println()
|
||||
else -> if (true) println()
|
||||
else -> <!INVALID_IF_AS_EXPRESSION!>if<!> (true) println()
|
||||
}
|
||||
else println()
|
||||
|
||||
@@ -28,4 +28,4 @@ fun testWrappedExpressions() =
|
||||
}
|
||||
else {
|
||||
(((((42)) + 1)))
|
||||
}
|
||||
}
|
||||
|
||||
+29
-29
@@ -11,21 +11,21 @@ val mlist = MList()
|
||||
|
||||
fun work() {}
|
||||
|
||||
val xx1 = if (true) 42
|
||||
val xx2: Unit = if (true) 42
|
||||
val xx3 = idAny(if (true) 42)
|
||||
val xx4 = id(if (true) 42)
|
||||
val xx5 = idUnit(if (true) 42)
|
||||
val xx6 = null ?: if (true) 42
|
||||
val xx7 = "" + if (true) 42
|
||||
val xx1 = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
|
||||
val xx2: Unit = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
|
||||
val xx3 = idAny(<!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42)
|
||||
val xx4 = id(<!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42)
|
||||
val xx5 = idUnit(<!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42)
|
||||
val xx6 = null ?: <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
|
||||
val xx7 = "" + <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
|
||||
|
||||
val wxx1 = when { true -> 42 }
|
||||
val wxx2: Unit = when { true -> 42 }
|
||||
val wxx3 = idAny(when { true -> 42 })
|
||||
val wxx4 = id(when { true -> 42 })
|
||||
val wxx5 = idUnit(when { true -> 42 })
|
||||
val wxx6 = null ?: when { true -> 42 }
|
||||
val wxx7 = "" + when { true -> 42 }
|
||||
val wxx1 = <!NO_ELSE_IN_WHEN!>when<!> { true -> 42 }
|
||||
val wxx2: Unit = <!NO_ELSE_IN_WHEN!>when<!> { true -> 42 }
|
||||
val wxx3 = idAny(<!NO_ELSE_IN_WHEN!>when<!> { true -> 42 })
|
||||
val wxx4 = id(<!NO_ELSE_IN_WHEN!>when<!> { true -> 42 })
|
||||
val wxx5 = idUnit(<!NO_ELSE_IN_WHEN!>when<!> { true -> 42 })
|
||||
val wxx6 = null ?: <!NO_ELSE_IN_WHEN!>when<!> { true -> 42 }
|
||||
val wxx7 = "" + <!NO_ELSE_IN_WHEN!>when<!> { true -> 42 }
|
||||
|
||||
val fn1 = { if (true) 42 }
|
||||
val fn2 = { if (true) mlist.add() }
|
||||
@@ -41,24 +41,24 @@ val ufn4: () -> Unit = { when { true -> 42 } }
|
||||
val ufn5: () -> Unit = { when { true -> mlist.add() } }
|
||||
val ufn6: () -> Unit = { when { true -> work() } }
|
||||
|
||||
fun f1() = if (true) work()
|
||||
fun f2() = if (true) mlist.add()
|
||||
fun f3() = if (true) 42
|
||||
fun f4(): Unit = if (true) work()
|
||||
fun f5(): Unit = if (true) mlist.add()
|
||||
fun f6(): Unit = if (true) 42
|
||||
fun g1() = when { true -> work() }
|
||||
fun g2() = when { true -> mlist.add() }
|
||||
fun g3() = when { true -> 42 }
|
||||
fun g4(): Unit = when { true -> work() }
|
||||
fun g5(): Unit = when { true -> mlist.add() }
|
||||
fun g6(): Unit = when { true -> 42 }
|
||||
fun f1() = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) work()
|
||||
fun f2() = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) mlist.add()
|
||||
fun f3() = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
|
||||
fun f4(): Unit = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) work()
|
||||
fun f5(): Unit = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) mlist.add()
|
||||
fun f6(): Unit = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
|
||||
fun g1() = <!NO_ELSE_IN_WHEN!>when<!> { true -> work() }
|
||||
fun g2() = <!NO_ELSE_IN_WHEN!>when<!> { true -> mlist.add() }
|
||||
fun g3() = <!NO_ELSE_IN_WHEN!>when<!> { true -> 42 }
|
||||
fun g4(): Unit = <!NO_ELSE_IN_WHEN!>when<!> { true -> work() }
|
||||
fun g5(): Unit = <!NO_ELSE_IN_WHEN!>when<!> { true -> mlist.add() }
|
||||
fun g6(): Unit = <!NO_ELSE_IN_WHEN!>when<!> { true -> 42 }
|
||||
|
||||
fun foo1(x: String?) {
|
||||
"" + if (true) 42
|
||||
"" + <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 42
|
||||
w@while (true) {
|
||||
x ?: if (true) break
|
||||
x ?: when { true -> break@w }
|
||||
x ?: <!INVALID_IF_AS_EXPRESSION!>if<!> (true) break
|
||||
x ?: <!NO_ELSE_IN_WHEN!>when<!> { true -> break@w }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
fun example() {
|
||||
val a = if (true) true else false
|
||||
val b = if (true) else false
|
||||
val c = if (true) true
|
||||
val c = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) true
|
||||
val d = if (true) true else;
|
||||
val e = if (true) {} else false
|
||||
val f = if (true) true else {}
|
||||
@@ -27,7 +27,7 @@ fun example() {
|
||||
}()
|
||||
|
||||
fun t(): Boolean {
|
||||
return if (true) true
|
||||
return <!INVALID_IF_AS_EXPRESSION!>if<!> (true) true
|
||||
}
|
||||
|
||||
return if (true) true else {}
|
||||
|
||||
Vendored
+2
-2
@@ -99,10 +99,10 @@ fun testImplicitCoercion() {
|
||||
else -> z--
|
||||
}
|
||||
|
||||
var iff = if (true) {
|
||||
var iff = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) {
|
||||
z = 34
|
||||
}
|
||||
val g = if (true) 4
|
||||
val g = <!INVALID_IF_AS_EXPRESSION!>if<!> (true) 4
|
||||
val h = if (false) 4 else {}
|
||||
|
||||
<!INAPPLICABLE_CANDIDATE!>bar<!>(if (true) {
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ fun t1(x: Int) = when(x) {
|
||||
else -> 1
|
||||
}
|
||||
|
||||
fun t5(x: Int) = when (x) {
|
||||
fun t5(x: Int) = <!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
is Int -> 1
|
||||
2 -> 2
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ fun f3(s: Number?) {
|
||||
}
|
||||
|
||||
fun f4(s: Int?) {
|
||||
var u = if (s!! == 42);
|
||||
if (u == Unit) u = if (s == 239);
|
||||
var u = <!INVALID_IF_AS_EXPRESSION!>if<!> (s!! == 42);
|
||||
if (u == Unit) u = <!INVALID_IF_AS_EXPRESSION!>if<!> (s == 239);
|
||||
return u
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ fun getStringLength(obj : Any) : Char? {
|
||||
}
|
||||
|
||||
fun toInt(i: Int?): Int = if (i != null) i else 0
|
||||
fun illegalWhenBody(a: Any): Int = when(a) {
|
||||
fun illegalWhenBody(a: Any): Int = <!NO_ELSE_IN_WHEN!>when<!>(a) {
|
||||
is Int -> a
|
||||
is String -> a
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@ fun test(x: Stmt): String =
|
||||
}
|
||||
|
||||
fun test2(x: Stmt): String =
|
||||
when (x) {
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
is Expr -> "expr"
|
||||
}
|
||||
|
||||
fun test3(x: Expr): String =
|
||||
when (x) {
|
||||
<!NO_ELSE_IN_WHEN!>when<!> (x) {
|
||||
is Stmt -> "stmt"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ sealed class Base {
|
||||
// No else required
|
||||
}
|
||||
|
||||
fun bar() = when (this) {
|
||||
fun bar() = <!NO_ELSE_IN_WHEN!>when<!> (this) {
|
||||
is A -> 1
|
||||
is B.B1 -> 2
|
||||
}
|
||||
@@ -31,4 +31,4 @@ sealed class Base {
|
||||
A.A1 -> 2
|
||||
is A.A2 -> 3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
sealed class A
|
||||
sealed class B : A()
|
||||
|
||||
class C : B()
|
||||
class D : B()
|
||||
|
||||
fun test(a: A): Any {
|
||||
return when (a) {
|
||||
is C -> ""
|
||||
is D -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test2(a: A): Any {
|
||||
return when (a) {
|
||||
is B -> ""
|
||||
}
|
||||
}
|
||||
|
||||
fun test3(a: A): Any {
|
||||
return when (a) {
|
||||
is D -> ""
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
sealed class A
|
||||
sealed class B : A()
|
||||
|
||||
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
sealed class Sealed() {
|
||||
object First: Sealed()
|
||||
open class NonFirst: Sealed() {
|
||||
class NonSecond: NonFirst() {
|
||||
object Third: Sealed()
|
||||
class NonThird: Sealed() {
|
||||
object Fourth: NonFirst()
|
||||
class Fifth: Sealed()
|
||||
}
|
||||
}
|
||||
object Second: Sealed()
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(s: Sealed) = when(s) {
|
||||
Sealed.First -> 1
|
||||
is Sealed.NonFirst -> 2
|
||||
Sealed.NonFirst.Second -> 4
|
||||
Sealed.NonFirst.NonSecond.Third -> 6
|
||||
is Sealed.NonFirst.NonSecond.NonThird -> 8
|
||||
is Sealed.NonFirst.NonSecond.NonThird.Fifth -> 10
|
||||
// no else required
|
||||
}
|
||||
|
||||
fun fooWithElse(s: Sealed) = when(s) {
|
||||
Sealed.First -> 1
|
||||
Sealed.NonFirst.NonSecond.Third -> 6
|
||||
is Sealed.NonFirst.NonSecond.NonThird.Fifth -> 10
|
||||
else -> 0
|
||||
}
|
||||
|
||||
fun fooWithoutElse(s: Sealed) = when(s) {
|
||||
Sealed.First -> 1
|
||||
is Sealed.NonFirst -> 2
|
||||
Sealed.NonFirst.NonSecond.Third -> 6
|
||||
is Sealed.NonFirst.NonSecond.NonThird -> 8
|
||||
is Sealed.NonFirst.NonSecond.NonThird.Fifth -> 10
|
||||
}
|
||||
|
||||
fun barWithoutElse(s: Sealed) = when(s) {
|
||||
Sealed.First -> 1
|
||||
is Sealed.NonFirst -> 2
|
||||
Sealed.NonFirst.Second -> 4
|
||||
is Sealed.NonFirst.NonSecond.NonThird -> 8
|
||||
is Sealed.NonFirst.NonSecond.NonThird.Fifth -> 10
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
sealed class Sealed() {
|
||||
object First: Sealed()
|
||||
open class NonFirst: Sealed() {
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
// ISSUE: KT-13495
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// !LANGUAGE: +AllowSealedInheritorsInDifferentFilesOfSamePackage
|
||||
|
||||
// FILE: Base.kt
|
||||
|
||||
sealed class Base {
|
||||
class A : Base()
|
||||
}
|
||||
|
||||
// FILE: B.kt
|
||||
|
||||
class B : Base()
|
||||
|
||||
// FILE: Container.kt
|
||||
|
||||
class Containter {
|
||||
class C : Base()
|
||||
|
||||
inner class D : Base()
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun test_OK(base: Base) {
|
||||
val x = when (base) {
|
||||
is Base.A -> 1
|
||||
is B -> 2
|
||||
is Containter.C -> 3
|
||||
is Containter.D -> 4
|
||||
}
|
||||
}
|
||||
|
||||
fun test_error_1(base: Base) {
|
||||
val x = when (base) {
|
||||
is B -> 2
|
||||
is Containter.C -> 3
|
||||
is Containter.D -> 4
|
||||
}
|
||||
}
|
||||
|
||||
fun test_error_2(base: Base) {
|
||||
val x = when (base) {
|
||||
is Base.A -> 1
|
||||
is Containter.C -> 3
|
||||
is Containter.D -> 4
|
||||
}
|
||||
}
|
||||
|
||||
fun test_error_3(base: Base) {
|
||||
val x = when (base) {
|
||||
is Base.A -> 1
|
||||
is B -> 2
|
||||
is Containter.D -> 4
|
||||
}
|
||||
}
|
||||
|
||||
fun test_error_4(base: Base) {
|
||||
val x = when (base) {
|
||||
is Base.A -> 1
|
||||
is B -> 2
|
||||
is Containter.C -> 3
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// ISSUE: KT-13495
|
||||
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||
// !LANGUAGE: +AllowSealedInheritorsInDifferentFilesOfSamePackage
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
sealed class Sealed(val x: Int) {
|
||||
object First: Sealed(12)
|
||||
open class NonFirst(x: Int, val y: Int): Sealed(x) {
|
||||
object Second: NonFirst(34, 2)
|
||||
object Third: NonFirst(56, 3)
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(s: Sealed): Int {
|
||||
return when(s) {
|
||||
is Sealed.NonFirst -> 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
sealed class Sealed(val x: Int) {
|
||||
object First: Sealed(12)
|
||||
open class NonFirst(x: Int, val y: Int): Sealed(x) {
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
sealed class Sealed(val x: Int) {
|
||||
object First: Sealed(12)
|
||||
open class NonFirst(x: Int, val y: Int): Sealed(x) {
|
||||
object Second: NonFirst(34, 2)
|
||||
object Third: NonFirst(56, 3)
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(s: Sealed): Int {
|
||||
return when(s) {
|
||||
!is Sealed.NonFirst -> 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
sealed class Sealed(val x: Int) {
|
||||
object First: Sealed(12)
|
||||
open class NonFirst(x: Int, val y: Int): Sealed(x) {
|
||||
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
sealed class Sealed(val x: Int) {
|
||||
interface ITuple {
|
||||
val x: Int
|
||||
val y: Int
|
||||
}
|
||||
class Tuple(override val x: Int, override val y: Int): ITuple
|
||||
object First: Sealed(12)
|
||||
open class NonFirst(tuple: Tuple): Sealed(tuple.x), ITuple {
|
||||
override val y: Int = tuple.y
|
||||
object Second: NonFirst(Tuple(34, 2))
|
||||
class Third: NonFirst(Tuple(56, 3))
|
||||
}
|
||||
}
|
||||
|
||||
fun foo(s: Sealed): Int {
|
||||
return when(s) {
|
||||
is Sealed.First -> 1
|
||||
!is Sealed.ITuple -> 0
|
||||
// else required
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
sealed class Sealed(val x: Int) {
|
||||
interface ITuple {
|
||||
val x: Int
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ sealed class Sealed {
|
||||
}
|
||||
|
||||
fun foo(s: Sealed): Int {
|
||||
return when(s) {
|
||||
return <!NO_ELSE_IN_WHEN!>when<!>(s) {
|
||||
is Sealed.First -> 1
|
||||
!is Any -> 0
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ sealed class Tree {
|
||||
is Node -> this.left.max()
|
||||
}
|
||||
|
||||
fun maxIsClass(): Int = when(this) {
|
||||
fun maxIsClass(): Int = <!NO_ELSE_IN_WHEN!>when<!>(this) {
|
||||
Empty -> -1
|
||||
Leaf -> 0
|
||||
is Node -> this.left.max()
|
||||
@@ -20,4 +20,4 @@ sealed class Tree {
|
||||
is Node -> this.left.max()
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION
|
||||
sealed class Sealed {
|
||||
|
||||
}
|
||||
|
||||
fun foo(s: Sealed): Int {
|
||||
return when(s) {
|
||||
// We do not return anything, so else branch must be here
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !DIAGNOSTICS: -UNUSED_EXPRESSION
|
||||
sealed class Sealed {
|
||||
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@ object CC : C()
|
||||
fun foo(a: A) {
|
||||
if (a is B) {
|
||||
if (a is C) {
|
||||
val t = when (a) {
|
||||
val t = <!NO_ELSE_IN_WHEN!>when<!> (a) {
|
||||
is CC -> "CC"
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,9 @@ fun foo(a: A) {
|
||||
fun foo2(a: A) {
|
||||
if (a is C) {
|
||||
if (a is B) {
|
||||
val t = when (a) {
|
||||
val t = <!NO_ELSE_IN_WHEN!>when<!> (a) {
|
||||
is CC -> "CC"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public fun foo(x: String?, y: String?): Int {
|
||||
while (true) {
|
||||
x ?: <!INVALID_IF_AS_EXPRESSION!>if<!> (y == null) break
|
||||
// y is nullable if x != null
|
||||
y<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
// y is null because of the break
|
||||
return y<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
// FIR_IDENTICAL
|
||||
public fun foo(x: String?, y: String?): Int {
|
||||
while (true) {
|
||||
x ?: if (y == null) break
|
||||
@@ -7,4 +6,4 @@ public fun foo(x: String?, y: String?): Int {
|
||||
}
|
||||
// y is null because of the break
|
||||
return y<!UNSAFE_CALL!>.<!>length
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
fun foo() {}
|
||||
|
||||
val x: Unit? = when ("A") {
|
||||
"B" -> foo()
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
fun foo() {}
|
||||
|
||||
val x: Unit? = <!NO_ELSE_IN_WHEN!>when<!> ("A") {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+9
-9
@@ -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)
|
||||
*
|
||||
|
||||
+1
-1
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -38,4 +38,4 @@ fun test4() {
|
||||
2 -> bar(x, y)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-18
@@ -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"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user