From adad0b46287222b01b7fa4243c3f1f97670ad36f Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Fri, 18 Mar 2022 09:45:14 +0000 Subject: [PATCH] [JS IR] Fix export of nested enums Merge-request: KT-MR-5916 Merged-by: Ilya Goncharov ^KT-51211 fixed --- .../backend/js/export/ExportModelGenerator.kt | 16 +++++++-------- .../testData/box/export/exportEnumClass.kt | 14 +++++++++++++ .../declarations/declarations.d.ts | 20 +++++++++++++++++++ .../declarations/declarations.kt | 8 ++++++++ .../declarations/declarations__main.js | 9 +++++++++ .../declarations/declarations__main.ts | 12 +++++++++++ 6 files changed, 71 insertions(+), 8 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt index 6d7002d1f7f..37b415dc92e 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt @@ -61,18 +61,18 @@ class ExportModelGenerator( return when (candidate) { is IrSimpleFunction -> exportFunction(candidate) is IrProperty -> exportProperty(candidate) - is IrClass -> { - if (candidate.isEnumClass) { - exportEnumClass(candidate) - } else { - exportClass(candidate) - } - } + is IrClass -> exportClass(candidate) is IrField -> null else -> error("Can't export declaration $candidate") } } + private fun exportClass(candidate: IrClass) = if (candidate.isEnumClass) { + exportEnumClass(candidate) + } else { + exportOrdinaryClass(candidate) + } + private fun exportFunction(function: IrSimpleFunction): ExportedDeclaration? { return when (val exportability = functionExportability(function)) { is Exportability.NotNeeded -> null @@ -221,7 +221,7 @@ class ExportModelGenerator( return Exportability.Allowed } - private fun exportClass( + private fun exportOrdinaryClass( klass: IrClass ): ExportedDeclaration? { when (val exportability = classExportability(klass)) { diff --git a/js/js.translator/testData/box/export/exportEnumClass.kt b/js/js.translator/testData/box/export/exportEnumClass.kt index 334d94787ec..593c06b6b4b 100644 --- a/js/js.translator/testData/box/export/exportEnumClass.kt +++ b/js/js.translator/testData/box/export/exportEnumClass.kt @@ -39,6 +39,14 @@ enum class Bar { fun bay() = name } +@JsExport +class OuterClass { + enum class NestedEnum { + A, + B; + } +} + // FILE: test.js function box() { if (this["export_enum_class"].Foo.A !== this["export_enum_class"].Foo.A) return "fail1" @@ -82,5 +90,11 @@ function box() { if (this["export_enum_class"].Foo.A.ordinal !== 0) return "fail25" if (this["export_enum_class"].Foo.B.ordinal !== 1) return "fail26" + if (this["export_enum_class"].OuterClass.NestedEnum.A.name !== "A") return "fail27" + if (this["export_enum_class"].OuterClass.NestedEnum.B.name !== "B") return "fail28" + + if (this["export_enum_class"].OuterClass.NestedEnum.A.ordinal !== 0) return "fail29" + if (this["export_enum_class"].OuterClass.NestedEnum.B.ordinal !== 1) return "fail30" + return "OK" } \ No newline at end of file diff --git a/js/js.translator/testData/typescript-export/declarations/declarations.d.ts b/js/js.translator/testData/typescript-export/declarations/declarations.d.ts index a6f40549ea7..794974ca5b4 100644 --- a/js/js.translator/testData/typescript-export/declarations/declarations.d.ts +++ b/js/js.translator/testData/typescript-export/declarations/declarations.d.ts @@ -142,5 +142,25 @@ declare namespace JS_TESTS { readonly __doNotUseIt: __doNotImplementIt; } function processInterface(test: foo.TestInterface): string; + class OuterClass { + constructor(); + } + namespace OuterClass { + abstract class NestedEnum { + private constructor(); + static get A(): foo.OuterClass.NestedEnum & { + get name(): "A"; + get ordinal(): 0; + }; + static get B(): foo.OuterClass.NestedEnum & { + get name(): "B"; + get ordinal(): 1; + }; + static values(): Array; + static valueOf(value: string): foo.OuterClass.NestedEnum; + get name(): "A" | "B"; + get ordinal(): 0 | 1; + } + } } } diff --git a/js/js.translator/testData/typescript-export/declarations/declarations.kt b/js/js.translator/testData/typescript-export/declarations/declarations.kt index b552e8c7cbe..2f04aff32f0 100644 --- a/js/js.translator/testData/typescript-export/declarations/declarations.kt +++ b/js/js.translator/testData/typescript-export/declarations/declarations.kt @@ -205,4 +205,12 @@ class TestInterfaceImpl(override val value: String) : TestInterface { @JsExport fun processInterface(test: TestInterface): String { return "Owner ${test.getOwnerName()} has value '${test.value}'" +} + +@JsExport +class OuterClass { + enum class NestedEnum { + A, + B + } } \ No newline at end of file diff --git a/js/js.translator/testData/typescript-export/declarations/declarations__main.js b/js/js.translator/testData/typescript-export/declarations/declarations__main.js index e0495942d5e..4a654d8bff2 100644 --- a/js/js.translator/testData/typescript-export/declarations/declarations__main.js +++ b/js/js.translator/testData/typescript-export/declarations/declarations__main.js @@ -29,6 +29,7 @@ var TestDataClass = JS_TESTS.foo.TestDataClass; var TestEnumClass = JS_TESTS.foo.TestEnumClass; var TestInterfaceImpl = JS_TESTS.foo.TestInterfaceImpl; var processInterface = JS_TESTS.foo.processInterface; +var OuterClass = JS_TESTS.foo.OuterClass; function assert(condition) { if (!condition) { throw "Assertion failed"; @@ -117,5 +118,13 @@ function box() { assert(processInterface(new TestInterfaceImpl("bar")) == "Owner TestInterfaceImpl has value 'bar'"); // @ts-expect-error "Just test that this code will throw compilation error for a user" assert(processInterface({ value: "bar", getOwnerName: function () { return "RandomObject"; } }) == "Owner RandomObject has value 'bar'"); + assert(OuterClass.NestedEnum.valueOf("A") === OuterClass.NestedEnum.A); + assert(OuterClass.NestedEnum.valueOf("B") === OuterClass.NestedEnum.B); + assert(OuterClass.NestedEnum.values().indexOf(OuterClass.NestedEnum.A) != -1); + assert(OuterClass.NestedEnum.values().indexOf(OuterClass.NestedEnum.B) != -1); + assert(OuterClass.NestedEnum.A.name === "A"); + assert(OuterClass.NestedEnum.B.name === "B"); + assert(OuterClass.NestedEnum.A.ordinal === 0); + assert(OuterClass.NestedEnum.B.ordinal === 1); return "OK"; } diff --git a/js/js.translator/testData/typescript-export/declarations/declarations__main.ts b/js/js.translator/testData/typescript-export/declarations/declarations__main.ts index f3a7e35f790..2e7804e611a 100644 --- a/js/js.translator/testData/typescript-export/declarations/declarations__main.ts +++ b/js/js.translator/testData/typescript-export/declarations/declarations__main.ts @@ -29,6 +29,7 @@ import TestDataClass = JS_TESTS.foo.TestDataClass; import TestEnumClass = JS_TESTS.foo.TestEnumClass; import TestInterfaceImpl = JS_TESTS.foo.TestInterfaceImpl; import processInterface = JS_TESTS.foo.processInterface; +import OuterClass = JS_TESTS.foo.OuterClass; function assert(condition: boolean) { if (!condition) { @@ -140,5 +141,16 @@ function box(): string { // @ts-expect-error "Just test that this code will throw compilation error for a user" assert(processInterface({ value: "bar", getOwnerName: () => "RandomObject" }) == "Owner RandomObject has value 'bar'") + assert(OuterClass.NestedEnum.valueOf("A") === OuterClass.NestedEnum.A) + assert(OuterClass.NestedEnum.valueOf("B") === OuterClass.NestedEnum.B) + + assert(OuterClass.NestedEnum.values().indexOf(OuterClass.NestedEnum.A) != -1) + assert(OuterClass.NestedEnum.values().indexOf(OuterClass.NestedEnum.B) != -1) + + assert(OuterClass.NestedEnum.A.name === "A") + assert(OuterClass.NestedEnum.B.name === "B") + assert(OuterClass.NestedEnum.A.ordinal === 0) + assert(OuterClass.NestedEnum.B.ordinal === 1) + return "OK"; } \ No newline at end of file