Implementation of exhaustive whens in control flow analysis.
Now control flow analyzer knows when is exhaustive. If despite of this all conditions are accidentally false, jump to error is generated. A set of tests (diagnostic, control flow). #KT-5113 Fixed. #KT-6046 Fixed. #KT-1882 Fixed.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
== foo ==
|
||||
fun foo(flag: Boolean): Int {
|
||||
when (flag) {
|
||||
true -> return 1
|
||||
false -> return 0
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
1 <START>
|
||||
v(flag: Boolean)
|
||||
magic[FAKE_INITIALIZER](flag: Boolean) -> <v0>
|
||||
w(flag|<v0>)
|
||||
2 mark({ when (flag) { true -> return 1 false -> return 0 } })
|
||||
mark(when (flag) { true -> return 1 false -> return 0 })
|
||||
r(flag) -> <v1>
|
||||
mark(true -> return 1)
|
||||
mark(true)
|
||||
r(true) -> <v2>
|
||||
magic[EQUALS_IN_WHEN_CONDITION](true|<v1>, <v2>) -> <v3>
|
||||
jmp?(L4|<v3>) NEXT:[mark(false -> return 0), r(1) -> <v4>]
|
||||
L3 ['when' entry body]:
|
||||
r(1) -> <v4>
|
||||
ret(*|<v4>) L1 NEXT:[<END>]
|
||||
- jmp(L2) NEXT:[merge(when (flag) { true -> return 1 false -> return 0 }|!<v8>, !<v9>) -> <v10>] PREV:[]
|
||||
L4 [next 'when' entry]:
|
||||
mark(false -> return 0) PREV:[jmp?(L4|<v3>)]
|
||||
mark(false)
|
||||
r(false) -> <v5>
|
||||
magic[EQUALS_IN_WHEN_CONDITION](false|<v1>, <v5>) -> <v6>
|
||||
jmp?(L6|<v6>) NEXT:[jmp(error), r(0) -> <v7>]
|
||||
L5 ['when' entry body]:
|
||||
r(0) -> <v7>
|
||||
ret(*|<v7>) L1 NEXT:[<END>]
|
||||
- jmp(L2) NEXT:[merge(when (flag) { true -> return 1 false -> return 0 }|!<v8>, !<v9>) -> <v10>] PREV:[]
|
||||
L6 [next 'when' entry]:
|
||||
jmp(error) NEXT:[<ERROR>] PREV:[jmp?(L6|<v6>)]
|
||||
L2 [after 'when' expression]:
|
||||
- merge(when (flag) { true -> return 1 false -> return 0 }|!<v8>, !<v9>) -> <v10> PREV:[]
|
||||
L1:
|
||||
1 <END> NEXT:[<SINK>] PREV:[ret(*|<v4>) L1, ret(*|<v7>) L1]
|
||||
error:
|
||||
<ERROR> PREV:[jmp(error)]
|
||||
sink:
|
||||
<SINK> PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
@@ -0,0 +1,6 @@
|
||||
fun foo(flag: Boolean): Int {
|
||||
when (flag) {
|
||||
true -> return 1
|
||||
false -> return 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
== foo ==
|
||||
fun foo(flag: Boolean): Int {
|
||||
when (flag) {
|
||||
true -> return 1
|
||||
false -> return 0
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
<v0>: Boolean NEW: magic[FAKE_INITIALIZER](flag: Boolean) -> <v0>
|
||||
flag <v1>: * NEW: r(flag) -> <v1>
|
||||
true <v2>: * NEW: r(true) -> <v2>
|
||||
true <v3>: * NEW: magic[EQUALS_IN_WHEN_CONDITION](true|<v1>, <v2>) -> <v3>
|
||||
1 <v4>: Int NEW: r(1) -> <v4>
|
||||
return 1 !<v8>: *
|
||||
false <v5>: * NEW: r(false) -> <v5>
|
||||
false <v6>: * NEW: magic[EQUALS_IN_WHEN_CONDITION](false|<v1>, <v5>) -> <v6>
|
||||
0 <v7>: Int NEW: r(0) -> <v7>
|
||||
return 0 !<v9>: *
|
||||
when (flag) { true -> return 1 false -> return 0 } <v10>: * NEW: merge(when (flag) { true -> return 1 false -> return 0 }|!<v8>, !<v9>) -> <v10>
|
||||
{ when (flag) { true -> return 1 false -> return 0 } } <v10>: * COPY
|
||||
=====================
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package
|
||||
|
||||
internal fun foo(/*0*/ dir: Direction): kotlin.Int
|
||||
|
||||
internal final enum class Direction : kotlin.Enum<Direction> {
|
||||
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<Direction>
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package
|
||||
|
||||
internal fun foo(/*0*/ x: MyEnum?): kotlin.Int
|
||||
|
||||
internal final enum class MyEnum : kotlin.Enum<MyEnum> {
|
||||
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<MyEnum>
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package
|
||||
|
||||
internal fun foo(/*0*/ dir: Direction): kotlin.Int
|
||||
|
||||
internal final enum class Direction : kotlin.Enum<Direction> {
|
||||
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<Direction>
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package
|
||||
|
||||
internal final enum class E : kotlin.Enum<E> {
|
||||
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<E>
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user