From 848c2afdb4396489cd69ffb4c399f467cd90bc07 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Mon, 29 Jun 2015 18:11:55 +0300 Subject: [PATCH] "is" over enum entry is now an error + new tests + test fixes --- .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../PatternMatchingTypingVisitor.java | 6 +++ .../fullJdk/synchronized/nonLocalReturn.kt | 14 +++---- .../diagnostics/tests/enum/ifEnumEntry.kt | 6 +++ .../diagnostics/tests/enum/ifEnumEntry.txt | 37 +++++++++++++++++++ .../diagnostics/tests/enum/isEnumEntry.kt | 6 +++ .../diagnostics/tests/enum/isEnumEntry.txt | 37 +++++++++++++++++++ .../tests/when/ExhaustiveEnumIs.kt | 6 +-- .../tests/when/ExhaustiveEnumMixed.kt | 4 +- .../checkers/JetDiagnosticsTestGenerated.java | 12 ++++++ 11 files changed, 118 insertions(+), 12 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/enum/ifEnumEntry.kt create mode 100644 compiler/testData/diagnostics/tests/enum/ifEnumEntry.txt create mode 100644 compiler/testData/diagnostics/tests/enum/isEnumEntry.kt create mode 100644 compiler/testData/diagnostics/tests/enum/isEnumEntry.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 14e09bad62e..078556686d8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -600,6 +600,7 @@ public interface Errors { DiagnosticFactory0 USELESS_CAST = DiagnosticFactory0.create(WARNING, AS_TYPE); DiagnosticFactory0 CAST_NEVER_SUCCEEDS = DiagnosticFactory0.create(WARNING); DiagnosticFactory0 DYNAMIC_NOT_ALLOWED = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 IS_ENUM_ENTRY = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 IMPLICIT_CAST_TO_UNIT_OR_ANY = DiagnosticFactory1.create(WARNING); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 2fa4ca6bf72..5eed0c12740 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -337,6 +337,7 @@ public class DefaultErrorMessages { MAP.put(USELESS_CAST, "No cast needed"); MAP.put(CAST_NEVER_SUCCEEDS, "This cast can never succeed"); MAP.put(DYNAMIC_NOT_ALLOWED, "Dynamic types are not allowed in this position"); + MAP.put(IS_ENUM_ENTRY, "'is' over enum entry is not allowed, use comparison instead"); MAP.put(USELESS_NULLABLE_CHECK, "Non-null type is checked for instance of nullable type"); MAP.put(WRONG_SETTER_PARAMETER_TYPE, "Setter parameter type must be equal to the type of the property, i.e. ''{0}''", RENDER_TYPE, RENDER_TYPE); MAP.put(WRONG_GETTER_RETURN_TYPE, "Getter return type must be equal to the type of the property, i.e. ''{0}''", RENDER_TYPE, RENDER_TYPE); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.java index fe83a05a997..7b3bfc36917 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/PatternMatchingTypingVisitor.java @@ -22,9 +22,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.cfg.WhenChecker; +import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; +import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.kotlin.resolve.PossiblyBareType; import org.jetbrains.kotlin.resolve.TypeResolutionContext; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; @@ -311,6 +313,10 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor { if (TypesPackage.isDynamic(targetType)) { context.trace.report(DYNAMIC_NOT_ALLOWED.on(typeReferenceAfterIs)); } + ClassDescriptor targetDescriptor = TypeUtils.getClassDescriptor(targetType); + if (targetDescriptor != null && DescriptorUtils.isEnumEntry(targetDescriptor)) { + context.trace.report(IS_ENUM_ENTRY.on(typeReferenceAfterIs)); + } if (!subjectType.isMarkedNullable() && targetType.isMarkedNullable()) { JetTypeElement element = typeReferenceAfterIs.getTypeElement(); diff --git a/compiler/testData/codegen/boxWithStdlib/fullJdk/synchronized/nonLocalReturn.kt b/compiler/testData/codegen/boxWithStdlib/fullJdk/synchronized/nonLocalReturn.kt index 3c2cd1bbe2f..e99c25ae77a 100644 --- a/compiler/testData/codegen/boxWithStdlib/fullJdk/synchronized/nonLocalReturn.kt +++ b/compiler/testData/codegen/boxWithStdlib/fullJdk/synchronized/nonLocalReturn.kt @@ -29,13 +29,13 @@ class TestLocal(val name: String, val executionType: ExecutionType) : Callable local() - is ExecutionType.NON_LOCAL_SIMPLE -> nonLocalSimple() - is ExecutionType.NON_LOCAL_EXCEPTION -> nonLocalWithException() - is ExecutionType.NON_LOCAL_FINALLY -> nonLocalWithFinally() - is ExecutionType.NON_LOCAL_EXCEPTION_AND_FINALLY -> nonLocalWithExceptionAndFinally() - is ExecutionType.NON_LOCAL_EXCEPTION_AND_FINALLY_WITH_RETURN -> nonLocalWithExceptionAndFinallyWithReturn() - is ExecutionType.NON_LOCAL_NESTED -> nonLocalNested() + ExecutionType.LOCAL -> local() + ExecutionType.NON_LOCAL_SIMPLE -> nonLocalSimple() + ExecutionType.NON_LOCAL_EXCEPTION -> nonLocalWithException() + ExecutionType.NON_LOCAL_FINALLY -> nonLocalWithFinally() + ExecutionType.NON_LOCAL_EXCEPTION_AND_FINALLY -> nonLocalWithExceptionAndFinally() + ExecutionType.NON_LOCAL_EXCEPTION_AND_FINALLY_WITH_RETURN -> nonLocalWithExceptionAndFinallyWithReturn() + ExecutionType.NON_LOCAL_NESTED -> nonLocalNested() else -> "fail" } } diff --git a/compiler/testData/diagnostics/tests/enum/ifEnumEntry.kt b/compiler/testData/diagnostics/tests/enum/ifEnumEntry.kt new file mode 100644 index 00000000000..83a69cd1f9b --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/ifEnumEntry.kt @@ -0,0 +1,6 @@ +enum class MyEnum { + FIRST, + SECOND +} + +fun foo(me: MyEnum): Boolean = if (me is MyEnum.FIRST) true else false \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/enum/ifEnumEntry.txt b/compiler/testData/diagnostics/tests/enum/ifEnumEntry.txt new file mode 100644 index 00000000000..90989ea4583 --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/ifEnumEntry.txt @@ -0,0 +1,37 @@ +package + +internal fun foo(/*0*/ me: MyEnum): kotlin.Boolean + +internal final enum class MyEnum : kotlin.Enum { + public enum entry FIRST : MyEnum { + private constructor FIRST() + 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 SECOND : MyEnum { + private constructor SECOND() + 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/enum/isEnumEntry.kt b/compiler/testData/diagnostics/tests/enum/isEnumEntry.kt new file mode 100644 index 00000000000..83603442a48 --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/isEnumEntry.kt @@ -0,0 +1,6 @@ +enum class MyEnum { + FIRST, + SECOND +} + +fun foo(me: MyEnum): Boolean = me is MyEnum.FIRST \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/enum/isEnumEntry.txt b/compiler/testData/diagnostics/tests/enum/isEnumEntry.txt new file mode 100644 index 00000000000..90989ea4583 --- /dev/null +++ b/compiler/testData/diagnostics/tests/enum/isEnumEntry.txt @@ -0,0 +1,37 @@ +package + +internal fun foo(/*0*/ me: MyEnum): kotlin.Boolean + +internal final enum class MyEnum : kotlin.Enum { + public enum entry FIRST : MyEnum { + private constructor FIRST() + 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 SECOND : MyEnum { + private constructor SECOND() + 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/ExhaustiveEnumIs.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveEnumIs.kt index 3c58abd2073..4f695b0e3bd 100644 --- a/compiler/testData/diagnostics/tests/when/ExhaustiveEnumIs.kt +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveEnumIs.kt @@ -4,8 +4,8 @@ enum class MyEnum { fun foo(x: MyEnum): Int { return when (x) { - is MyEnum.A -> 1 - is MyEnum.B -> 2 - is MyEnum.C -> 3 + is MyEnum.A -> 1 + is MyEnum.B -> 2 + is MyEnum.C -> 3 } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/when/ExhaustiveEnumMixed.kt b/compiler/testData/diagnostics/tests/when/ExhaustiveEnumMixed.kt index 6ff1b9e4ba9..a71d189a3a6 100644 --- a/compiler/testData/diagnostics/tests/when/ExhaustiveEnumMixed.kt +++ b/compiler/testData/diagnostics/tests/when/ExhaustiveEnumMixed.kt @@ -5,7 +5,7 @@ enum class MyEnum { fun foo(x: MyEnum): Int { return when (x) { MyEnum.A -> 1 - is MyEnum.B -> 2 - is MyEnum.C -> 3 + is MyEnum.B -> 2 + is MyEnum.C -> 3 } } \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 66e704d44ac..ff2bcebd025 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -4965,6 +4965,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("ifEnumEntry.kt") + public void testIfEnumEntry() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/ifEnumEntry.kt"); + doTest(fileName); + } + @TestMetadata("importEnumFromJava.kt") public void testImportEnumFromJava() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/importEnumFromJava.kt"); @@ -4995,6 +5001,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("isEnumEntry.kt") + public void testIsEnumEntry() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/isEnumEntry.kt"); + doTest(fileName); + } + @TestMetadata("javaEnumValueOfMethod.kt") public void testJavaEnumValueOfMethod() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/enum/javaEnumValueOfMethod.kt");