diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java index a71cd7e6668..d2cacdcdd3f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/JetControlFlowProcessor.java @@ -1354,6 +1354,11 @@ public class JetControlFlowProcessor { if (!isElse) { builder.bindLabel(nextLabel); + // For the last entry of exhaustive when, + // attempt to jump further should lead to error, not to "done" + if (!iterator.hasNext() && WhenChecker.isWhenExhaustive(expression, trace)) { + builder.jumpToError(expression); + } } } builder.bindLabel(doneLabel); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.java b/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.java index 262e93cc671..94793287460 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/WhenChecker.java @@ -98,7 +98,7 @@ public final class WhenChecker { return notEmpty; } - private static boolean isWhenExhaustive(@NotNull JetWhenExpression expression, @NotNull BindingTrace trace) { + public static boolean isWhenExhaustive(@NotNull JetWhenExpression expression, @NotNull BindingTrace trace) { JetType type = whenSubjectType(expression, trace.getBindingContext()); if (type == null) return false; ClassDescriptor classDescriptor = getClassDescriptorOfTypeIfEnum(type); diff --git a/compiler/testData/cfg/controlStructures/whenExhaustive.instructions b/compiler/testData/cfg/controlStructures/whenExhaustive.instructions new file mode 100644 index 00000000000..b2a62fcd3e8 --- /dev/null +++ b/compiler/testData/cfg/controlStructures/whenExhaustive.instructions @@ -0,0 +1,46 @@ +== foo == +fun foo(flag: Boolean): Int { + when (flag) { + true -> return 1 + false -> return 0 + } +} +--------------------- +L0: + 1 + v(flag: Boolean) + magic[FAKE_INITIALIZER](flag: Boolean) -> + w(flag|) + 2 mark({ when (flag) { true -> return 1 false -> return 0 } }) + mark(when (flag) { true -> return 1 false -> return 0 }) + r(flag) -> + mark(true -> return 1) + mark(true) + r(true) -> + magic[EQUALS_IN_WHEN_CONDITION](true|, ) -> + jmp?(L4|) NEXT:[mark(false -> return 0), r(1) -> ] +L3 ['when' entry body]: + r(1) -> + ret(*|) L1 NEXT:[] +- jmp(L2) NEXT:[merge(when (flag) { true -> return 1 false -> return 0 }|!, !) -> ] PREV:[] +L4 [next 'when' entry]: + mark(false -> return 0) PREV:[jmp?(L4|)] + mark(false) + r(false) -> + magic[EQUALS_IN_WHEN_CONDITION](false|, ) -> + jmp?(L6|) NEXT:[jmp(error), r(0) -> ] +L5 ['when' entry body]: + r(0) -> + ret(*|) L1 NEXT:[] +- jmp(L2) NEXT:[merge(when (flag) { true -> return 1 false -> return 0 }|!, !) -> ] PREV:[] +L6 [next 'when' entry]: + jmp(error) NEXT:[] PREV:[jmp?(L6|)] +L2 [after 'when' expression]: +- merge(when (flag) { true -> return 1 false -> return 0 }|!, !) -> PREV:[] +L1: + 1 NEXT:[] PREV:[ret(*|) L1, ret(*|) L1] +error: + PREV:[jmp(error)] +sink: + PREV:[, ] +===================== diff --git a/compiler/testData/cfg/controlStructures/whenExhaustive.kt b/compiler/testData/cfg/controlStructures/whenExhaustive.kt new file mode 100644 index 00000000000..e39b2f9c996 --- /dev/null +++ b/compiler/testData/cfg/controlStructures/whenExhaustive.kt @@ -0,0 +1,6 @@ +fun foo(flag: Boolean): Int { + when (flag) { + true -> return 1 + false -> return 0 + } +} \ No newline at end of file diff --git a/compiler/testData/cfg/controlStructures/whenExhaustive.values b/compiler/testData/cfg/controlStructures/whenExhaustive.values new file mode 100644 index 00000000000..c4dbd978b6b --- /dev/null +++ b/compiler/testData/cfg/controlStructures/whenExhaustive.values @@ -0,0 +1,21 @@ +== foo == +fun foo(flag: Boolean): Int { + when (flag) { + true -> return 1 + false -> return 0 + } +} +--------------------- + : Boolean NEW: magic[FAKE_INITIALIZER](flag: Boolean) -> +flag : * NEW: r(flag) -> +true : * NEW: r(true) -> +true : * NEW: magic[EQUALS_IN_WHEN_CONDITION](true|, ) -> +1 : Int NEW: r(1) -> +return 1 !: * +false : * NEW: r(false) -> +false : * NEW: magic[EQUALS_IN_WHEN_CONDITION](false|, ) -> +0 : Int NEW: r(0) -> +return 0 !: * +when (flag) { true -> return 1 false -> return 0 } : * NEW: merge(when (flag) { true -> return 1 false -> return 0 }|!, !) -> +{ when (flag) { true -> return 1 false -> return 0 } } : * COPY +===================== diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveInitialization.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveInitialization.kt new file mode 100644 index 00000000000..0e15e5efb3d --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveInitialization.kt @@ -0,0 +1,15 @@ +enum class Direction { + NORTH, SOUTH, WEST, EAST +} + +fun foo(dir: Direction): Int { + val res: Int + // See KT-6046: res is always initialized + when (dir) { + Direction.NORTH -> res = 1 + Direction.SOUTH -> res = 2 + Direction.WEST -> res = 3 + Direction.EAST -> res = 4 + } + return res +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveInitialization.txt b/compiler/testData/diagnostics/tests/when/ExhaustiveInitialization.txt new file mode 100644 index 00000000000..cd0c733a48c --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveInitialization.txt @@ -0,0 +1,57 @@ +package + +internal fun foo(/*0*/ dir: Direction): kotlin.Int + +internal final enum class Direction : kotlin.Enum { + public enum entry NORTH : Direction { + private constructor NORTH() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Direction): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public enum entry SOUTH : Direction { + private constructor SOUTH() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Direction): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public enum entry WEST : Direction { + private constructor WEST() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Direction): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public enum entry EAST : Direction { + private constructor EAST() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Direction): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + private constructor Direction() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Direction): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Direction + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveNullable.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveNullable.kt new file mode 100644 index 00000000000..19edb89d8fd --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveNullable.kt @@ -0,0 +1,14 @@ +enum class MyEnum { + A, B +} + +fun foo(x: MyEnum?): Int { + val y: Int + // See KT-6046: y is always initialized + when (x) { + MyEnum.A -> y = 1 + MyEnum.B -> y = 2 + null -> y = 0 + } + return y +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveNullable.txt b/compiler/testData/diagnostics/tests/when/ExhaustiveNullable.txt new file mode 100644 index 00000000000..4ad0fa7a11f --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveNullable.txt @@ -0,0 +1,37 @@ +package + +internal fun foo(/*0*/ x: MyEnum?): kotlin.Int + +internal final enum class MyEnum : kotlin.Enum { + public enum entry A : MyEnum { + private constructor A() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: MyEnum): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public enum entry B : MyEnum { + private constructor B() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: MyEnum): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + private constructor MyEnum() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: MyEnum): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): MyEnum + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveReturn.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveReturn.kt new file mode 100644 index 00000000000..11c764c8ccd --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveReturn.kt @@ -0,0 +1,13 @@ +enum class Direction { + NORTH, SOUTH, WEST, EAST +} + +fun foo(dir: Direction): Int { + when (dir) { + Direction.NORTH -> return 1 + Direction.SOUTH -> return 2 + Direction.WEST -> return 3 + Direction.EAST -> return 4 + } + // See KT-1882: no return is needed at the end +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveReturn.txt b/compiler/testData/diagnostics/tests/when/ExhaustiveReturn.txt new file mode 100644 index 00000000000..cd0c733a48c --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveReturn.txt @@ -0,0 +1,57 @@ +package + +internal fun foo(/*0*/ dir: Direction): kotlin.Int + +internal final enum class Direction : kotlin.Enum { + public enum entry NORTH : Direction { + private constructor NORTH() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Direction): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public enum entry SOUTH : Direction { + private constructor SOUTH() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Direction): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public enum entry WEST : Direction { + private constructor WEST() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Direction): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public enum entry EAST : Direction { + private constructor EAST() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Direction): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + private constructor Direction() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: Direction): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): Direction + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/when/PropertyNotInitialized.kt b/compiler/testData/diagnostics/tests/when/PropertyNotInitialized.kt new file mode 100644 index 00000000000..c286b1e93c3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/PropertyNotInitialized.kt @@ -0,0 +1,16 @@ +// See KT-5113 +enum class E { + A, + B +} + +class Outer(e: E) { + private val prop: Int + init { + when(e ) { + // When is exhaustive, property is always initialized + E.A -> prop = 1 + E.B -> prop = 2 + } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/when/PropertyNotInitialized.txt b/compiler/testData/diagnostics/tests/when/PropertyNotInitialized.txt new file mode 100644 index 00000000000..5196a4d37c5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/when/PropertyNotInitialized.txt @@ -0,0 +1,43 @@ +package + +internal final enum class E : kotlin.Enum { + public enum entry A : E { + private constructor A() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + public enum entry B : E { + private constructor B() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + } + + private constructor E() + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public final override /*1*/ /*fake_override*/ fun name(): kotlin.String + public final override /*1*/ /*fake_override*/ fun ordinal(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E + public final /*synthesized*/ fun values(): kotlin.Array +} + +internal final class Outer { + public constructor Outer(/*0*/ e: E) + private final val prop: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java index c7e485e3e45..b82b8b574ec 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/ControlFlowTestGenerated.java @@ -219,6 +219,12 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest { String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/whenConditions.kt"); doTest(fileName); } + + @TestMetadata("whenExhaustive.kt") + public void testWhenExhaustive() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/whenExhaustive.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/cfg/conventions") diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java index 1cf1da2b3c7..3091c05e5d9 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/PseudoValueTestGenerated.java @@ -221,6 +221,12 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest { String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/whenConditions.kt"); doTest(fileName); } + + @TestMetadata("whenExhaustive.kt") + public void testWhenExhaustive() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/cfg/controlStructures/whenExhaustive.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/cfg/conventions") diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 3afd052a6b0..cd3f56a3ec9 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -12921,6 +12921,24 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("ExhaustiveInitialization.kt") + public void testExhaustiveInitialization() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/ExhaustiveInitialization.kt"); + doTest(fileName); + } + + @TestMetadata("ExhaustiveNullable.kt") + public void testExhaustiveNullable() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/ExhaustiveNullable.kt"); + doTest(fileName); + } + + @TestMetadata("ExhaustiveReturn.kt") + public void testExhaustiveReturn() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/ExhaustiveReturn.kt"); + doTest(fileName); + } + @TestMetadata("kt4434.kt") public void testKt4434() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/kt4434.kt"); @@ -12975,6 +12993,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("PropertyNotInitialized.kt") + public void testPropertyNotInitialized() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/PropertyNotInitialized.kt"); + doTest(fileName); + } + @TestMetadata("When.kt") public void testWhen() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/When.kt");