diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index ee0e5335d39..ae7e3528124 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -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) diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.fir.txt new file mode 100644 index 00000000000..8e060626a81 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.fir.txt @@ -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|/cond|) { + ==($subj$, Boolean(true)) -> { + Int(1) + } + } + + lval y: R|kotlin/Unit| = when (R|/cond|) { + ==($subj$, Boolean(false)) -> { + Int(2) + } + } + + lval z: R|kotlin/Int| = when (R|/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|/cond|) { + ==($subj$, Boolean(true)) -> { + Int(1) + } + ==($subj$, Boolean(false)) -> { + Int(2) + } + } + + lval x: R|kotlin/Int| = when (R|/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|/cond|) { + ==($subj$, Boolean(true)) -> { + Int(1) + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt new file mode 100644 index 00000000000..ddf84b51870 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingBooleanBranch.kt @@ -0,0 +1,33 @@ +fun test_1(cond: Boolean) { + val x = when (cond) { + true -> 1 + } + + val y = when (cond) { + false -> 2 + } + + val z = when (cond) { + true -> 1 + false -> 2 + } +} + +fun test_2(cond: Boolean?) { + val x = 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 + } +} diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.fir.txt new file mode 100644 index 00000000000..791d4a1457f --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.fir.txt @@ -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|/a|) { + ($subj$ is R|kotlin/Int|) -> { + Int(1) + } + ($subj$ is R|kotlin/String|) -> { + Int(2) + } + } + + lval y: R|kotlin/Int| = when (R|/a|) { + else -> { + Int(1) + } + } + + lval z: R|kotlin/Int| = when (R|/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|/a|) { + ($subj$ is R|kotlin/String|) -> { + Int(1) + } + ($subj$ is R|kotlin/Int|) -> { + Int(2) + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt new file mode 100644 index 00000000000..8b95fcac476 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingElse.kt @@ -0,0 +1,23 @@ +fun test(a: Any) { + val x = 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 + } +} diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.fir.txt new file mode 100644 index 00000000000..ae6201fee17 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.fir.txt @@ -0,0 +1,63 @@ +FILE: missingEnumEntry.kt + public final enum class SomeEnum : R|kotlin/Enum| { + private constructor(): R|SomeEnum| { + super|>() + } + + public final static enum entry A: R|SomeEnum| + public final static enum entry B: R|SomeEnum| + public final static fun values(): R|kotlin/Array| { + } + + 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|/enum|) { + ==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> { + Int(1) + } + } + + lval y: R|kotlin/Int| = when (R|/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|/enum|) { + ==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> { + Int(1) + } + ==($subj$, Q|SomeEnum|.R|/SomeEnum.B|) -> { + Int(2) + } + } + + lval y: R|kotlin/Int| = when (R|/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|/enum|) { + ==($subj$, Q|SomeEnum|.R|/SomeEnum.A|) -> { + Int(1) + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt new file mode 100644 index 00000000000..75355434441 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingEnumEntry.kt @@ -0,0 +1,33 @@ +enum class SomeEnum { + A, B +} + +fun test_1(enum: SomeEnum) { + val x = when (enum) { + SomeEnum.A -> 1 + } + + val y = when (enum) { + SomeEnum.A -> 1 + SomeEnum.B -> 2 + } +} + +fun test_2(enum: SomeEnum?) { + val x = 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 + } +} diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.fir.txt new file mode 100644 index 00000000000..0d11593bd9b --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.fir.txt @@ -0,0 +1,84 @@ +FILE: a.kt + public sealed class Base : R|kotlin/Any| { + private constructor(): R|Base| { + super() + } + + } + public final class A : R|Base| { + public constructor(): R|A| { + super() + } + + } +FILE: b.kt + public final object B : R|Base| { + private constructor(): R|B| { + super() + } + + } +FILE: c.kt + public final fun test_1(base: R|Base|): R|kotlin/Unit| { + lval x: R|kotlin/Unit| = when (R|/base|) { + ($subj$ is R|A|) -> { + Int(1) + } + } + + lval y: R|kotlin/Unit| = when (R|/base|) { + ==($subj$, Q|B|) -> { + Int(1) + } + } + + lval z: R|kotlin/Int| = when (R|/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|/base|) { + ($subj$ is R|A|) -> { + Int(1) + } + ($subj$ is R|B|) -> { + Int(2) + } + } + + lval y: R|kotlin/Unit| = when (R|/base|) { + ($subj$ is R|A|) -> { + Int(1) + } + ==($subj$, Q|B|) -> { + Int(2) + } + } + + lval z: R|kotlin/Int| = when (R|/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|/base|) { + ($subj$ is R|A|) -> { + Int(1) + } + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt new file mode 100644 index 00000000000..9300b82cb1f --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/negative/missingSealedInheritor.kt @@ -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 = when (base) { + is A -> 1 + } + + val y = when (base) { + B -> 1 + } + + val z = when (base) { + is A -> 1 + B -> 2 + } +} + +fun test_2(base: Base?) { + val x = when (base) { + is A -> 1 + is B -> 2 + } + + val y = 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 + } +} diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.dot b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.dot similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.dot rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.dot diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.kt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndDNNType.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndDNNType.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.kt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveWhenAndFlexibleType.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveWhenAndFlexibleType.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.kt similarity index 78% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.kt index ca517f63c3d..f6a79b2e097 100644 --- a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_boolean.kt +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_boolean.kt @@ -1,5 +1,5 @@ fun test_1(b: Boolean) { - val x = when (b) { + val x = 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 = when (b) { true -> 1 false -> 2 } diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.kt similarity index 84% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.kt index c502f35e046..ac2e4c7bbb1 100644 --- a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enum.kt +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enum.kt @@ -3,12 +3,12 @@ enum class Enum { } fun test_1(e: Enum) { - val a = when (e) { + val a = when (e) { Enum.A -> 1 Enum.B -> 2 } - val b = when (e) { + val b = 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 = when (e) { Enum.A -> 1 Enum.B -> 2 Enum.C -> 3 diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.kt similarity index 89% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.kt index ab00bc6dab8..463216e5e5f 100644 --- a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_enumJava.kt +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_enumJava.kt @@ -7,12 +7,12 @@ public enum JavaEnum { // FILE: main.kt fun test_1(e: JavaEnum) { - val a = when (e) { + val a = when (e) { JavaEnum.A -> 1 JavaEnum.B -> 2 }.plus(0) - val b = when (e) { + val b = 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 = when (e) { JavaEnum.A -> 1 JavaEnum.B -> 2 JavaEnum.C -> 3 diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.kt similarity index 86% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.kt index 78547c73258..c37b08fc716 100644 --- a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedClass.kt +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedClass.kt @@ -7,12 +7,12 @@ sealed class Base { class C : Base() fun test_1(e: Base) { - val a = when (e) { + val a = when (e) { is Base.A -> 1 is Base.A.B -> 2 } - val b = when (e) { + val b = 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 = when (e) { is Base.A -> 1 is Base.A.B -> 2 is C -> 3 diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.kt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedObject.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedObject.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.fir.txt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.fir.txt similarity index 100% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.fir.txt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.fir.txt diff --git a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.kt b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt similarity index 83% rename from compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.kt rename to compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt index 523b7eca50a..7ed050ea810 100644 --- a/compiler/fir/analysis-tests/testData/resolve/exhaustiveness_sealedSubClass.kt +++ b/compiler/fir/analysis-tests/testData/resolve/exhaustiveness/positive/exhaustiveness_sealedSubClass.kt @@ -32,23 +32,23 @@ fun test_1(e: A) { } fun test_2(e: A) { - val a = when (e) { + val a = when (e) { is D -> 1 is E -> 2 }.plus(0) - val b = when (e) { + val b = when (e) { is B -> 1 is D -> 2 is E -> 3 }.plus(0) - val c = when (e) { + val c = when (e) { is B -> 1 is D -> 2 }.plus(0) - val d = when (e) { + val d = when (e) { is C -> 1 }.plus(0) } diff --git a/compiler/fir/analysis-tests/testData/resolve/whenElse.kt b/compiler/fir/analysis-tests/testData/resolve/whenElse.kt index 831c7f173ab..8dcd09a23e6 100644 --- a/compiler/fir/analysis-tests/testData/resolve/whenElse.kt +++ b/compiler/fir/analysis-tests/testData/resolve/whenElse.kt @@ -16,12 +16,12 @@ fun get(f: Boolean) = if (f) {A.A1} else {""} fun case2() { val flag: Any = get(false) //string - val l1 = when (flag!!) { // should be NO_ELSE_IN_WHEN + val l1 = 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 = 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 {""} fun case2() { val flag: Any = get(true) //A - val l1 = when (flag!!) {// should be NO_ELSE_IN_WHEN + val l1 = 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 = 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 = 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 = when (flag) {// should be NO_ELSE_IN_WHEN A.A1 -> B() //should be INCOMPATIBLE_TYPES A.A2 -> B() //should be INCOMPATIBLE_TYPES } diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index 604282878a9..f7da3ebcfff 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -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") diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index 2324378a3ec..ea8708480aa 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -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") diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt index 0088e1d7b9f..add59c21a70 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/Main.kt @@ -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) { @@ -23,6 +19,7 @@ fun main(args: Array) { alias("FunctionCallChecker") alias("VariableAssignmentChecker") alias("TryExpressionChecker") + alias("WhenExpressionChecker") } val declarationPackage = "org.jetbrains.kotlin.fir.analysis.checkers.declaration" diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt index f4e8d19e20a..f3e5f53d1bf 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ComposedExpressionCheckers.kt @@ -23,12 +23,15 @@ internal class ComposedExpressionCheckers : ExpressionCheckers() { get() = _variableAssignmentCheckers override val tryExpressionCheckers: Set get() = _tryExpressionCheckers + override val whenExpressionCheckers: Set + get() = _whenExpressionCheckers private val _basicExpressionCheckers: MutableSet = mutableSetOf() private val _qualifiedAccessCheckers: MutableSet = mutableSetOf() private val _functionCallCheckers: MutableSet = mutableSetOf() private val _variableAssignmentCheckers: MutableSet = mutableSetOf() private val _tryExpressionCheckers: MutableSet = mutableSetOf() + private val _whenExpressionCheckers: MutableSet = 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 } } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt index 72e167d29e2..116e76cfb52 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/ExpressionCheckers.kt @@ -22,10 +22,12 @@ abstract class ExpressionCheckers { open val functionCallCheckers: Set = emptySet() open val variableAssignmentCheckers: Set = emptySet() open val tryExpressionCheckers: Set = emptySet() + open val whenExpressionCheckers: Set = emptySet() @CheckersComponentInternal internal val allBasicExpressionCheckers: Set get() = basicExpressionCheckers @CheckersComponentInternal internal val allQualifiedAccessCheckers: Set get() = qualifiedAccessCheckers + allBasicExpressionCheckers @CheckersComponentInternal internal val allFunctionCallCheckers: Set get() = functionCallCheckers + allQualifiedAccessCheckers @CheckersComponentInternal internal val allVariableAssignmentCheckers: Set get() = variableAssignmentCheckers + allBasicExpressionCheckers @CheckersComponentInternal internal val allTryExpressionCheckers: Set get() = tryExpressionCheckers + allBasicExpressionCheckers + @CheckersComponentInternal internal val allWhenExpressionCheckers: Set get() = whenExpressionCheckers + allBasicExpressionCheckers } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt index 3f7f70d9f3d..b0c400b7185 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExpressionCheckerAliases.kt @@ -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 typealias FirQualifiedAccessChecker = FirExpressionChecker typealias FirFunctionCallChecker = FirExpressionChecker typealias FirVariableAssignmentChecker = FirExpressionChecker typealias FirTryExpressionChecker = FirExpressionChecker +typealias FirWhenExpressionChecker = FirExpressionChecker diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt new file mode 100644 index 00000000000..d48242f3b0f --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirExhaustiveWhenChecker.kt @@ -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 +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt index ba5376b9c2a..ba53b856b84 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ExpressionCheckersDiagnosticComponent.kt @@ -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) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index d62a2cd707d..6b5de471d3b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -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") diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 0ac8ab7e8c9..8dbba130ef8 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -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(SourceElementPositioningStrategies.WHEN_EXPRESSION) + val INVALID_IF_AS_EXPRESSION by error0(SourceElementPositioningStrategies.IF_EXPRESSION) + // Extended checkers group val REDUNDANT_VISIBILITY_MODIFIER by warning0(SourceElementPositioningStrategies.VISIBILITY_MODIFIER) val REDUNDANT_MODALITY_MODIFIER by warning0(SourceElementPositioningStrategies.MODALITY_MODIFIER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt index dd80267b25a..f4b21c77cbb 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/LightTreePositioningStrategies.kt @@ -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 + ): List { + 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 + ): List { + return markElement(tree.ifKeyword(node) ?: node, startOffset, endOffset, tree, node) + } + } } fun FirSourceElement.hasValOrVar(): Boolean = @@ -354,6 +376,12 @@ private fun FlyweightCapableTreeStructure.dotOperator(node: Ligh private fun FlyweightCapableTreeStructure.initKeyword(node: LighterASTNode): LighterASTNode? = findChildByType(node, KtTokens.INIT_KEYWORD) +private fun FlyweightCapableTreeStructure.whenKeyword(node: LighterASTNode): LighterASTNode? = + findChildByType(node, KtTokens.WHEN_KEYWORD) + +private fun FlyweightCapableTreeStructure.ifKeyword(node: LighterASTNode): LighterASTNode? = + findChildByType(node, KtTokens.IF_KEYWORD) + private fun FlyweightCapableTreeStructure.nameIdentifier(node: LighterASTNode): LighterASTNode? = findChildByType(node, KtTokens.IDENTIFIER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt index 86c42f79947..4d4e326d73f 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/SourceElementPositioningStrategies.kt @@ -102,4 +102,14 @@ object SourceElementPositioningStrategies { LightTreePositioningStrategies.DOT_BY_SELECTOR, PositioningStrategies.DOT_BY_SELECTOR ) -} \ No newline at end of file + + val WHEN_EXPRESSION = SourceElementPositioningStrategy( + LightTreePositioningStrategies.WHEN_EXPRESSION, + PositioningStrategies.WHEN_EXPRESSION + ) + + val IF_EXPRESSION = SourceElementPositioningStrategy( + LightTreePositioningStrategies.IF_EXPRESSION, + PositioningStrategies.IF_EXPRESSION + ) +} diff --git a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt index 4ffda04a3ec..fb52cf9a047 100644 --- a/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/entrypoint/src/org/jetbrains/kotlin/fir/checkers/CommonExpressionCheckers.kt @@ -28,4 +28,8 @@ object CommonExpressionCheckers : ExpressionCheckers() { override val tryExpressionCheckers: Set = setOf( FirCatchParameterChecker ) + + override val whenExpressionCheckers: Set = setOf( + FirExhaustiveWhenChecker + ) } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index c5250d5a05f..43a3f9b436e 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -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) { diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 7c960eebca1..834fc288308 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -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 -> { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index 14fd5581a38..65684cefd04 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -507,6 +507,13 @@ object PositioningStrategies { } } + @JvmField + val IF_EXPRESSION: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: KtIfExpression): List { + return markElement(element.ifKeyword) + } + } + @JvmField val WHEN_CONDITION_IN_RANGE: PositioningStrategy = object : PositioningStrategy() { override fun mark(element: KtWhenConditionInRange): List { diff --git a/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.fir.kt b/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.fir.kt index 6a62617d900..14ccbb2caa7 100644 --- a/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.fir.kt +++ b/compiler/testData/diagnostics/tests/FunctionCalleeExpressions.fir.kt @@ -72,7 +72,7 @@ fun main1() { 1."sdf" 1.{} - 1.if (true) {} + 1.if (true) {} } fun test() { diff --git a/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt b/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt index 628041e7526..8a956ae6273 100644 --- a/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt +++ b/compiler/testData/diagnostics/tests/FunctionReturnTypes.fir.kt @@ -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 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 if (1 > 2) 1 } fun blockReturnValueTypeMatch11() : Int { diff --git a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1185enums.fir.kt b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1185enums.fir.kt index 80b24b11bdc..48a32d9ed13 100644 --- a/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1185enums.fir.kt +++ b/compiler/testData/diagnostics/tests/controlFlowAnalysis/kt1185enums.fir.kt @@ -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) = 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) = when (c) { Color.RED -> 1 Color.GREEN -> 2 -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/controlStructures/emptyIf.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/emptyIf.fir.kt deleted file mode 100644 index 5da2c7adbbe..00000000000 --- a/compiler/testData/diagnostics/tests/controlStructures/emptyIf.fir.kt +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/controlStructures/emptyIf.kt b/compiler/testData/diagnostics/tests/controlStructures/emptyIf.kt index 13ce5412108..e12b774f2dd 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/emptyIf.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/emptyIf.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL fun foo(x: Unit) = x fun test() { diff --git a/compiler/testData/diagnostics/tests/controlStructures/ifWhenToAnyComplexExpressions.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/ifWhenToAnyComplexExpressions.fir.kt index bd173b19cde..280f15a6478 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/ifWhenToAnyComplexExpressions.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/ifWhenToAnyComplexExpressions.fir.kt @@ -11,7 +11,7 @@ fun testMixedIfAndWhen() = else 1 true -> if (true) 42 else println() - else -> if (true) println() + else -> if (true) println() } else println() @@ -28,4 +28,4 @@ fun testWrappedExpressions() = } else { (((((42)) + 1))) - } \ No newline at end of file + } diff --git a/compiler/testData/diagnostics/tests/controlStructures/ifWhenWithoutElse.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/ifWhenWithoutElse.fir.kt index ee00a4e882d..263daaaa536 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/ifWhenWithoutElse.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/ifWhenWithoutElse.fir.kt @@ -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 = 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 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 = 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 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() = 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 foo1(x: String?) { - "" + if (true) 42 + "" + if (true) 42 w@while (true) { - x ?: if (true) break - x ?: when { true -> break@w } + x ?: if (true) break + x ?: when { true -> break@w } } } diff --git a/compiler/testData/diagnostics/tests/controlStructures/improperElseInExpression.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/improperElseInExpression.fir.kt index c36cb381506..bc9b8f49d94 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/improperElseInExpression.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/improperElseInExpression.fir.kt @@ -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 = 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 if (true) true } return if (true) true else {} diff --git a/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.fir.kt index 2588f6cc895..2aa1d500c0d 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/kt770.kt351.kt735_StatementType.fir.kt @@ -99,10 +99,10 @@ fun testImplicitCoercion() { else -> z-- } - var iff = if (true) { + var iff = if (true) { z = 34 } - val g = if (true) 4 + val g = if (true) 4 val h = if (false) 4 else {} bar(if (true) { diff --git a/compiler/testData/diagnostics/tests/controlStructures/when.kt234.kt973.fir.kt b/compiler/testData/diagnostics/tests/controlStructures/when.kt234.kt973.fir.kt index fc5d5665024..baa658b8210 100644 --- a/compiler/testData/diagnostics/tests/controlStructures/when.kt234.kt973.fir.kt +++ b/compiler/testData/diagnostics/tests/controlStructures/when.kt234.kt973.fir.kt @@ -25,7 +25,7 @@ fun t1(x: Int) = when(x) { else -> 1 } -fun t5(x: Int) = when (x) { +fun t5(x: Int) = when (x) { is Int -> 1 2 -> 2 } diff --git a/compiler/testData/diagnostics/tests/dataFlow/EmptyIf.fir.kt b/compiler/testData/diagnostics/tests/dataFlow/EmptyIf.fir.kt index 4b3db89acdc..71a28eb64f4 100644 --- a/compiler/testData/diagnostics/tests/dataFlow/EmptyIf.fir.kt +++ b/compiler/testData/diagnostics/tests/dataFlow/EmptyIf.fir.kt @@ -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 = if (s!! == 42); + if (u == Unit) u = if (s == 239); return u -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt b/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt index f1075938464..90242dc54a5 100644 --- a/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt +++ b/compiler/testData/diagnostics/tests/infos/SmartCasts.fir.kt @@ -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 = when(a) { is Int -> a is String -> a } diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt index afef06f3764..c393564b456 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnRoot.fir.kt @@ -13,11 +13,11 @@ fun test(x: Stmt): String = } fun test2(x: Stmt): String = - when (x) { + when (x) { is Expr -> "expr" } fun test3(x: Expr): String = - when (x) { + when (x) { is Stmt -> "stmt" - } \ No newline at end of file + } diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt index d19eb6011fc..fab86d219d0 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTree.fir.kt @@ -15,7 +15,7 @@ sealed class Base { // No else required } - fun bar() = when (this) { + fun bar() = when (this) { is A -> 1 is B.B1 -> 2 } @@ -31,4 +31,4 @@ sealed class Base { A.A1 -> 2 is A.A2 -> 3 } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.fir.kt deleted file mode 100644 index 68a39439d7c..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.fir.kt +++ /dev/null @@ -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 -> "" - } -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.kt index 5991129f143..35acddf35c2 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveOnTriangleStar.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL sealed class A sealed class B : A() diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.fir.kt deleted file mode 100644 index 5c46abf6f29..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.fir.kt +++ /dev/null @@ -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 -} - diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.kt index b7afa1df5ac..58e1f50baf9 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWhenMultipleInner.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL sealed class Sealed() { object First: Sealed() open class NonFirst: Sealed() { diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.fir.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.fir.kt deleted file mode 100644 index 302a7bd38d8..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.fir.kt +++ /dev/null @@ -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 - } -} diff --git a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.kt b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.kt index d72d40c9102..50bf4002221 100644 --- a/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.kt +++ b/compiler/testData/diagnostics/tests/sealed/ExhaustiveWithFreedom.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // ISSUE: KT-13495 // !DIAGNOSTICS: -UNUSED_VARIABLE // !LANGUAGE: +AllowSealedInheritorsInDifferentFilesOfSamePackage diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.fir.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.fir.kt deleted file mode 100644 index 9c5be055bd6..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.fir.kt +++ /dev/null @@ -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 - } -} - diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.kt index 439de1ee3fe..1aebcb54486 100644 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.kt +++ b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhen.kt @@ -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) { diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.fir.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.fir.kt deleted file mode 100644 index 77cbfbf26c7..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.fir.kt +++ /dev/null @@ -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 - } -} - diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.kt index 0d02f2c6757..6ad07912e17 100644 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.kt +++ b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenNegated.kt @@ -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) { diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.fir.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.fir.kt deleted file mode 100644 index e2d3b79c3c0..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.fir.kt +++ /dev/null @@ -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 - } -} - diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.kt index d8f20b9c3fc..8b78455629e 100644 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.kt +++ b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAdditionalCase.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL sealed class Sealed(val x: Int) { interface ITuple { val x: Int diff --git a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAnyCase.fir.kt b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAnyCase.fir.kt index e9e4eed0755..fc235670129 100644 --- a/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAnyCase.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/NonExhaustiveWhenWithAnyCase.fir.kt @@ -7,7 +7,7 @@ sealed class Sealed { } fun foo(s: Sealed): Int { - return when(s) { + return when(s) { is Sealed.First -> 1 !is Any -> 0 } diff --git a/compiler/testData/diagnostics/tests/sealed/TreeWhenFunctionalNoIs.fir.kt b/compiler/testData/diagnostics/tests/sealed/TreeWhenFunctionalNoIs.fir.kt index c2d43bfb3cc..9aabfe0ddb5 100644 --- a/compiler/testData/diagnostics/tests/sealed/TreeWhenFunctionalNoIs.fir.kt +++ b/compiler/testData/diagnostics/tests/sealed/TreeWhenFunctionalNoIs.fir.kt @@ -9,7 +9,7 @@ sealed class Tree { is Node -> this.left.max() } - fun maxIsClass(): Int = when(this) { + fun maxIsClass(): Int = 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 } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.fir.kt b/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.fir.kt deleted file mode 100644 index 9271a1b4474..00000000000 --- a/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.fir.kt +++ /dev/null @@ -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 - } -} - diff --git a/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.kt b/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.kt index ea45861d7cd..05304d09f67 100644 --- a/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.kt +++ b/compiler/testData/diagnostics/tests/sealed/WhenOnEmptySealed.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_EXPRESSION sealed class Sealed { diff --git a/compiler/testData/diagnostics/tests/smartCasts/kt27221_irrelevantClasses.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/kt27221_irrelevantClasses.fir.kt index 337c36e7ba1..51270bfde33 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/kt27221_irrelevantClasses.fir.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/kt27221_irrelevantClasses.fir.kt @@ -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 = 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 = when (a) { is CC -> "CC" } } } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.fir.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.fir.kt new file mode 100644 index 00000000000..e1d79e1e21d --- /dev/null +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.fir.kt @@ -0,0 +1,9 @@ +public fun foo(x: String?, y: String?): Int { + while (true) { + x ?: if (y == null) break + // y is nullable if x != null + y.length + } + // y is null because of the break + return y.length +} diff --git a/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.kt b/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.kt index ef2399abbe4..520459f73a9 100644 --- a/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.kt +++ b/compiler/testData/diagnostics/tests/smartCasts/loops/elvisIfBreakInsideWhileTrue.kt @@ -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.length -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/unit/nullableUnit.fir.kt b/compiler/testData/diagnostics/tests/unit/nullableUnit.fir.kt deleted file mode 100644 index 42d2f77036a..00000000000 --- a/compiler/testData/diagnostics/tests/unit/nullableUnit.fir.kt +++ /dev/null @@ -1,5 +0,0 @@ -fun foo() {} - -val x: Unit? = when ("A") { - "B" -> foo() -} diff --git a/compiler/testData/diagnostics/tests/unit/nullableUnit.kt b/compiler/testData/diagnostics/tests/unit/nullableUnit.kt index 03d7ed33876..2c886979558 100644 --- a/compiler/testData/diagnostics/tests/unit/nullableUnit.kt +++ b/compiler/testData/diagnostics/tests/unit/nullableUnit.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL fun foo() {} val x: Unit? = when ("A") { diff --git a/compiler/testData/diagnostics/tests/when/ElseOnNullableEnum.fir.kt b/compiler/testData/diagnostics/tests/when/ElseOnNullableEnum.fir.kt index 31da011183f..830e0ff2104 100644 --- a/compiler/testData/diagnostics/tests/when/ElseOnNullableEnum.fir.kt +++ b/compiler/testData/diagnostics/tests/when/ElseOnNullableEnum.fir.kt @@ -12,7 +12,7 @@ enum class E { A, B } -fun test(e: E?) = when (e) { +fun test(e: E?) = when (e) { E.A -> 1 E.B -> 2 } diff --git a/compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.fir.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.fir.kt similarity index 54% rename from compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.fir.kt rename to compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.fir.kt index 0a39652a6fd..298acefd490 100644 --- a/compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.fir.kt +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.fir.kt @@ -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 when(arg) { + 2 == 2 -> "truth" + 2 == 1 -> "falsehood" } } diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.kt index 3b0933f5354..11e7d5f8d1c 100644 --- a/compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.kt +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveBooleanComplex.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveEnumIs.fir.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveEnumIs.fir.kt index 278ee04bced..398609150ba 100644 --- a/compiler/testData/diagnostics/tests/when/ExhaustiveEnumIs.fir.kt +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveEnumIs.fir.kt @@ -12,7 +12,7 @@ enum class MyEnum { } fun foo(x: MyEnum): Int { - return when (x) { + return when (x) { is MyEnum.A -> 1 is MyEnum.B -> 2 is MyEnum.C -> 3 diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveEnumMixed.fir.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveEnumMixed.fir.kt index 481970e4455..aaea91337b6 100644 --- a/compiler/testData/diagnostics/tests/when/ExhaustiveEnumMixed.fir.kt +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveEnumMixed.fir.kt @@ -13,7 +13,7 @@ enum class MyEnum { } fun foo(x: MyEnum): Int { - return when (x) { + return when (x) { MyEnum.A -> 1 is MyEnum.B -> 2 is MyEnum.C -> 3 diff --git a/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.fir.kt b/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.fir.kt deleted file mode 100644 index 382c03583e0..00000000000 --- a/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.fir.kt +++ /dev/null @@ -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 -} diff --git a/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.kt b/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.kt index d08e040bc97..21b7d43fe64 100644 --- a/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.kt +++ b/compiler/testData/diagnostics/tests/when/NoElseExpectedUnit.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * diff --git a/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.fir.kt b/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.fir.kt deleted file mode 100644 index 81081046fa7..00000000000 --- a/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.fir.kt +++ /dev/null @@ -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 -} diff --git a/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.kt b/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.kt index 5cc1a2be78f..fd65ecfa23b 100644 --- a/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.kt +++ b/compiler/testData/diagnostics/tests/when/NoElseNoExpectedType.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * diff --git a/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.fir.kt b/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.fir.kt deleted file mode 100644 index 69423511de3..00000000000 --- a/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.fir.kt +++ /dev/null @@ -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 - } -} diff --git a/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.kt b/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.kt index 6822f03a47a..de869792156 100644 --- a/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.kt +++ b/compiler/testData/diagnostics/tests/when/NoElseReturnedNonUnit.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * diff --git a/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.fir.kt b/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.fir.kt deleted file mode 100644 index 94b8f840ec2..00000000000 --- a/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.fir.kt +++ /dev/null @@ -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 -> {} - } -} diff --git a/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.kt b/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.kt index 4a5dbe3116a..8b60f0b072c 100644 --- a/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.kt +++ b/compiler/testData/diagnostics/tests/when/NoElseReturnedUnit.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * diff --git a/compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.kt b/compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.kt index 545d5c3cc55..1b798926dff 100644 --- a/compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.kt +++ b/compiler/testData/diagnostics/tests/when/NonExhaustiveBooleanNullable.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (POSITIVE) * diff --git a/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.fir.kt b/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.fir.kt deleted file mode 100644 index c3014d5ef6f..00000000000 --- a/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.fir.kt +++ /dev/null @@ -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 - } -} diff --git a/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.kt b/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.kt index b9480bf6cc4..bb9451bca98 100644 --- a/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.kt +++ b/compiler/testData/diagnostics/tests/when/NonExhaustivePlatformEnum.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) * diff --git a/compiler/testData/diagnostics/tests/when/NonExhaustiveWithNullabilityCheck.fir.kt b/compiler/testData/diagnostics/tests/when/NonExhaustiveWithNullabilityCheck.fir.kt index e0bcb365303..9e4351e95bc 100644 --- a/compiler/testData/diagnostics/tests/when/NonExhaustiveWithNullabilityCheck.fir.kt +++ b/compiler/testData/diagnostics/tests/when/NonExhaustiveWithNullabilityCheck.fir.kt @@ -13,7 +13,7 @@ enum class X { A, B } fun foo(arg: X?): Int { if (arg != null) { - return when (arg) { + return when (arg) { X.B -> 2 } } diff --git a/compiler/testData/diagnostics/tests/when/TopLevelSealed.fir.kt b/compiler/testData/diagnostics/tests/when/TopLevelSealed.fir.kt deleted file mode 100644 index b7577c720de..00000000000 --- a/compiler/testData/diagnostics/tests/when/TopLevelSealed.fir.kt +++ /dev/null @@ -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" - } -} diff --git a/compiler/testData/diagnostics/tests/when/TopLevelSealed.kt b/compiler/testData/diagnostics/tests/when/TopLevelSealed.kt index 14d6fd04291..6581b1c9cc1 100644 --- a/compiler/testData/diagnostics/tests/when/TopLevelSealed.kt +++ b/compiler/testData/diagnostics/tests/when/TopLevelSealed.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_VARIABLE /* * KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE) diff --git a/compiler/testData/diagnostics/tests/when/kt4434.fir.kt b/compiler/testData/diagnostics/tests/when/kt4434.fir.kt index 46abd84179d..8a378378379 100644 --- a/compiler/testData/diagnostics/tests/when/kt4434.fir.kt +++ b/compiler/testData/diagnostics/tests/when/kt4434.fir.kt @@ -27,7 +27,7 @@ fun foo(): Int { fun bar(): Int { val a = "a" if (a.length > 0) { - return when (a) { + return when (a) { "a" -> 1 } } diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/nestedWhenWithSubject.fir.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/nestedWhenWithSubject.fir.kt index 1be42fe50ee..bec1af3affc 100644 --- a/compiler/testData/diagnostics/tests/when/withSubjectVariable/nestedWhenWithSubject.fir.kt +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/nestedWhenWithSubject.fir.kt @@ -38,4 +38,4 @@ fun test4() { 2 -> bar(x, y) } } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.fir.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.fir.kt deleted file mode 100644 index 882e2c17b76..00000000000 --- a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.fir.kt +++ /dev/null @@ -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" - } -} diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt index 1b9f4988ed8..fe94c3c103b 100644 --- a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToEnum.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +VariableDeclarationInWhenSubject // !DIAGNOSTICS: -UNUSED_VARIABLE diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.fir.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.fir.kt deleted file mode 100644 index 7e66946fe0b..00000000000 --- a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.fir.kt +++ /dev/null @@ -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" - } -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.kt b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.kt index bde8ea93959..9fe474c40fc 100644 --- a/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.kt +++ b/compiler/testData/diagnostics/tests/when/withSubjectVariable/smartcastToSealed.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !LANGUAGE: +VariableDeclarationInWhenSubject // !DIAGNOSTICS: -UNUSED_VARIABLE