Enum implementing exported interface

[JS IR] Not export get instance enum function

[JS IR] Enum corresponding class is not considered in export

[JS IR] All enums are abstract and with private constructor

[JS IR] Any methods is left in d.ts

[JS IR] Make enum with declarations inside corresponding class

[JS IR] Export of interface through fake override

[JS IR] Include enum entry corresponding class members into export model

Merge-request: KT-MR-5031

^KT-49779 fixed
^KT-49773 fixed
This commit is contained in:
Ilya Goncharov
2021-11-24 12:25:50 +00:00
committed by Space
parent 4181429c7e
commit 1481ad21f5
17 changed files with 440 additions and 41 deletions
+11 -9
View File
@@ -29,6 +29,7 @@ enum class Bar {
init {
d = "d2"
}
fun huh() = "huh"
};
val foo = ordinal
@@ -66,19 +67,20 @@ function box() {
if (this["export_enum_class"].Bar.A.bay() !== "A") return "fail15"
if (this["export_enum_class"].Bar.B.bay() !== "B") return "fail16"
if (this["export_enum_class"].Bar.B.constructor.prototype.hasOwnProperty('baz')) return "fail17"
if (this["export_enum_class"].Bar.B.constructor.prototype.hasOwnProperty('d')) return "fail17"
if (this["export_enum_class"].Bar.B.constructor.prototype.hasOwnProperty('huh')) return "fail18"
if (this["export_enum_class"].Foo.valueOf("A") !== this["export_enum_class"].Foo.A) return "fail18"
if (this["export_enum_class"].Foo.valueOf("B") !== this["export_enum_class"].Foo.B) return "fail19"
if (this["export_enum_class"].Foo.valueOf("A") !== this["export_enum_class"].Foo.A) return "fail19"
if (this["export_enum_class"].Foo.valueOf("B") !== this["export_enum_class"].Foo.B) return "fail20"
if (this["export_enum_class"].Foo.values().indexOf(this["export_enum_class"].Foo.A) === -1) return "fail20"
if (this["export_enum_class"].Foo.values().indexOf(this["export_enum_class"].Foo.B) === -1) return "fail21"
if (this["export_enum_class"].Foo.values().indexOf(this["export_enum_class"].Foo.A) === -1) return "fail21"
if (this["export_enum_class"].Foo.values().indexOf(this["export_enum_class"].Foo.B) === -1) return "fail22"
if (this["export_enum_class"].Foo.A.name !== "A") return "fail22"
if (this["export_enum_class"].Foo.B.name !== "B") return "fail23"
if (this["export_enum_class"].Foo.A.name !== "A") return "fail23"
if (this["export_enum_class"].Foo.B.name !== "B") return "fail24"
if (this["export_enum_class"].Foo.A.ordinal !== 0) return "fail24"
if (this["export_enum_class"].Foo.B.ordinal !== 1) return "fail23"
if (this["export_enum_class"].Foo.A.ordinal !== 0) return "fail25"
if (this["export_enum_class"].Foo.B.ordinal !== 1) return "fail26"
return "OK"
}
@@ -100,7 +100,7 @@ declare namespace JS_TESTS {
readonly prop: string;
}
}
class TestEnumClass {
abstract class TestEnumClass {
private constructor();
readonly constructorParameter: string;
static readonly A: foo.TestEnumClass & {
@@ -37,5 +37,62 @@ declare namespace JS_TESTS {
const O2: {
foo(): number;
} & foo.OC;
interface I3 {
readonly foo: string;
bar: string;
readonly baz: string;
bay(): string;
readonly __doNotUseIt: __doNotImplementIt;
}
function getI3(): foo.I3;
function getA(): foo.I3;
function getB(): foo.I3;
function getC(): foo.I3;
abstract class A2 implements foo.I3 {
constructor();
abstract readonly foo: string;
abstract bar: string;
abstract readonly baz: string;
abstract bay(): string;
readonly __doNotUseIt: __doNotImplementIt;
}
class B2 extends foo.A2 {
constructor();
readonly foo: string;
bar: string;
readonly baz: string;
bay(): string;
}
class C2 extends foo.B2 {
constructor();
readonly foo: string;
bar: string;
baz: string;
bay(): string;
}
abstract class EC implements foo.I3 {
private constructor();
static readonly EC1: foo.EC & {
readonly name: "EC1";
readonly ordinal: 0;
};
static readonly EC2: foo.EC & {
readonly name: "EC2";
readonly ordinal: 1;
};
static readonly EC3: foo.EC & {
readonly name: "EC3";
readonly ordinal: 2;
};
readonly foo: string;
bar: string;
bay(): string;
static values(): Array<foo.EC>;
static valueOf(value: string): foo.EC;
readonly name: "EC1" | "EC2" | "EC3";
readonly ordinal: 0 | 1 | 2;
abstract readonly baz: string;
readonly __doNotUseIt: __doNotImplementIt;
}
}
}
@@ -7,22 +7,23 @@
// MODULE: JS_TESTS
// FILE: inheritance.kt
@file:JsExport
package foo
@JsExport
external interface I<T, out S, in U> {
var x: T
val y: S
fun z(u: U)
}
@JsExport
external interface I2 {
var x: String
val y: Boolean
fun z(z: Int)
}
@JsExport
abstract class AC : I2 {
override var x = "AC"
override abstract val y: Boolean
@@ -32,6 +33,7 @@ abstract class AC : I2 {
abstract val acAbstractProp: String
}
@JsExport
open class OC(
override val y: Boolean,
override val acAbstractProp: String
@@ -43,11 +45,121 @@ open class OC(
private fun privateFun(): String = "privateFun"
}
@JsExport
final class FC : OC(true, "FC")
@JsExport
object O1 : OC(true, "O1")
@JsExport
object O2 : OC(true, "O2") {
@JsName("foo") // TODO: Should work without JsName
fun foo(): Int = 10
}
}
@JsExport
interface I3 {
val foo: String
var bar: String
val baz: String
fun bay(): String
}
@JsExport
fun getI3(): I3 = object : I3 {
override val foo: String = "fooI3"
override var bar: String = "barI3"
override var baz: String = "bazI3"
override fun bay(): String = "bayI3"
}
abstract class A : I3
@JsExport
fun getA(): I3 = object : A() {
override val foo: String = "fooA"
override var bar: String = "barA"
override var baz: String = "bazA"
override fun bay(): String = "bayA"
}
open class B : A() {
override val foo: String = "fooB"
override var bar: String = "barB"
override val baz: String = "bazB"
override fun bay(): String = "bayB"
}
@JsExport
fun getB(): I3 = B()
open class C : B() {
override val foo: String = "fooC"
override var bar: String = "barC"
override var baz: String = "bazC"
override fun bay(): String = "bayC"
}
@JsExport
fun getC(): I3 = C()
@JsExport
abstract class A2 : I3
@JsExport
open class B2 : A2() {
override val foo: String = "fooB2"
override var bar: String = "barB2"
override val baz: String = "bazB2"
override fun bay(): String = "bayB2"
}
@JsExport
open class C2 : B2() {
override val foo: String = "fooC2"
override var bar: String = "barC2"
override var baz: String = "bazC2"
override fun bay(): String = "bayC2"
}
@JsExport
enum class EC : I3 {
EC1 {
override var baz = "ec1"
val bah = "bah"
fun huh() = "huh"
},
EC2 {
override var baz = "ec2"
},
EC3 {
override var baz = "ec3"
};
override val foo: String = "foo"
override var bar = "bar"
override fun bay(): String = "bay"
}
@@ -17,6 +17,13 @@ var AC = JS_TESTS.foo.AC;
var FC = JS_TESTS.foo.FC;
var O1 = JS_TESTS.foo.O1;
var O2 = JS_TESTS.foo.O2;
var getI3 = JS_TESTS.foo.getI3;
var getA = JS_TESTS.foo.getA;
var getB = JS_TESTS.foo.getB;
var getC = JS_TESTS.foo.getC;
var B2 = JS_TESTS.foo.B2;
var C2 = JS_TESTS.foo.C2;
var EC = JS_TESTS.foo.EC;
var Impl = /** @class */ (function (_super) {
__extends(Impl, _super);
function Impl() {
@@ -36,6 +43,16 @@ var Impl = /** @class */ (function (_super) {
});
return Impl;
}(AC));
// class A2Impl extends A2 {
// bar: string = "barA2"
// readonly baz: string = "bazA2"
// readonly foo: string = "fooA2"
//
// bay(): string {
// return "bayA2";
// }
//
// }
function box() {
var impl = new Impl();
if (impl.acProp !== "acProp")
@@ -66,5 +83,87 @@ function box() {
return "Fail 9";
if (O2.foo() != 10)
return "Fail 10";
if (getI3().foo != "fooI3")
return "Fail 11";
if (getI3().bar != "barI3")
return "Fail 12";
if (getI3().baz != "bazI3")
return "Fail 13";
if (getI3().bay() != "bayI3")
return "Fail 14";
if (getA().foo != "fooA")
return "Fail 15";
if (getA().bar != "barA")
return "Fail 16";
if (getA().baz != "bazA")
return "Fail 17";
if (getA().bay() != "bayA")
return "Fail 18";
if (getB().foo != "fooB")
return "Fail 19";
if (getB().bar != "barB")
return "Fail 20";
if (getB().baz != "bazB")
return "Fail 21";
if (getB().bay() != "bayB")
return "Fail 22";
if (getC().foo != "fooC")
return "Fail 23";
if (getC().bar != "barC")
return "Fail 24";
if (getC().baz != "bazC")
return "Fail 25";
if (getC().bay() != "bayC")
return "Fail 26";
// const a2Impl = new A2Impl()
// if (a2Impl.foo != "fooA2") return "Fail 27"
// if (a2Impl.bar != "barA2") return "Fail 28"
// if (a2Impl.baz != "bazA2") return "Fail 29"
// if (a2Impl.bay() != "bayA2") return "Fail 30"
var b2 = new B2();
if (b2.foo != "fooB2")
return "Fail 31";
if (b2.bar != "barB2")
return "Fail 32";
if (b2.baz != "bazB2")
return "Fail 33";
if (b2.bay() != "bayB2")
return "Fail 34";
var c2 = new C2();
if (c2.foo != "fooC2")
return "Fail 35";
if (c2.bar != "barC2")
return "Fail 36";
if (c2.baz != "bazC2")
return "Fail 37";
c2.baz = "bazC2-2";
if (c2.baz != "bazC2-2")
return "Fail 38";
if (c2.bay() != "bayC2")
return "Fail 39";
if (EC.EC1.foo != "foo")
return "Fail 40";
if (EC.EC1.bar != "bar")
return "Fail 41";
if (EC.EC1.baz != "ec1")
return "Fail 42";
if (EC.EC1.bay() != "bay")
return "Fail 43";
if (EC.EC2.foo != "foo")
return "Fail 44";
if (EC.EC2.bar != "bar")
return "Fail 45";
if (EC.EC2.baz != "ec2")
return "Fail 46";
if (EC.EC2.bay() != "bay")
return "Fail 47";
if (EC.EC3.foo != "foo")
return "Fail 48";
if (EC.EC3.bar != "bar")
return "Fail 49";
if (EC.EC3.baz != "ec3")
return "Fail 50";
if (EC.EC3.bay() != "bay")
return "Fail 51";
return "OK";
}
@@ -3,6 +3,13 @@ import AC = JS_TESTS.foo.AC;
import FC = JS_TESTS.foo.FC;
import O1 = JS_TESTS.foo.O1;
import O2 = JS_TESTS.foo.O2;
import getI3 = JS_TESTS.foo.getI3;
import getA = JS_TESTS.foo.getA;
import getB = JS_TESTS.foo.getB;
import getC = JS_TESTS.foo.getC;
import B2 = JS_TESTS.foo.B2;
import C2 = JS_TESTS.foo.C2;
import EC = JS_TESTS.foo.EC;
class Impl extends AC {
z(z: number): void {
@@ -12,6 +19,18 @@ class Impl extends AC {
get y(): boolean { return true; }
}
// TODO: Uncomment with fix of export open properties
// class A2Impl extends A2 {
// bar: string = "barA2"
// readonly baz: string = "bazA2"
// readonly foo: string = "fooA2"
//
// bay(): string {
// return "bayA2";
// }
//
// }
function box(): string {
const impl = new Impl();
if (impl.acProp !== "acProp") return "Fail 1";
@@ -36,5 +55,60 @@ function box(): string {
if (O2.acAbstractProp != "O2") return "Fail 9";
if (O2.foo() != 10) return "Fail 10";
if (getI3().foo != "fooI3") return "Fail 11"
if (getI3().bar != "barI3") return "Fail 12"
if (getI3().baz != "bazI3") return "Fail 13"
if (getI3().bay() != "bayI3") return "Fail 14"
if (getA().foo != "fooA") return "Fail 15"
if (getA().bar != "barA") return "Fail 16"
if (getA().baz != "bazA") return "Fail 17"
if (getA().bay() != "bayA") return "Fail 18"
if (getB().foo != "fooB") return "Fail 19"
if (getB().bar != "barB") return "Fail 20"
if (getB().baz != "bazB") return "Fail 21"
if (getB().bay() != "bayB") return "Fail 22"
if (getC().foo != "fooC") return "Fail 23"
if (getC().bar != "barC") return "Fail 24"
if (getC().baz != "bazC") return "Fail 25"
if (getC().bay() != "bayC") return "Fail 26"
// const a2Impl = new A2Impl()
// if (a2Impl.foo != "fooA2") return "Fail 27"
// if (a2Impl.bar != "barA2") return "Fail 28"
// if (a2Impl.baz != "bazA2") return "Fail 29"
// if (a2Impl.bay() != "bayA2") return "Fail 30"
const b2 = new B2()
if (b2.foo != "fooB2") return "Fail 31"
if (b2.bar != "barB2") return "Fail 32"
if (b2.baz != "bazB2") return "Fail 33"
if (b2.bay() != "bayB2") return "Fail 34"
const c2 = new C2()
if (c2.foo != "fooC2") return "Fail 35"
if (c2.bar != "barC2") return "Fail 36"
if (c2.baz != "bazC2") return "Fail 37"
c2.baz = "bazC2-2"
if (c2.baz != "bazC2-2") return "Fail 38"
if (c2.bay() != "bayC2") return "Fail 39"
if (EC.EC1.foo != "foo") return "Fail 40"
if (EC.EC1.bar != "bar") return "Fail 41"
if (EC.EC1.baz != "ec1") return "Fail 42"
if (EC.EC1.bay() != "bay") return "Fail 43"
if (EC.EC2.foo != "foo") return "Fail 44"
if (EC.EC2.bar != "bar") return "Fail 45"
if (EC.EC2.baz != "ec2") return "Fail 46"
if (EC.EC2.bay() != "bay") return "Fail 47"
if (EC.EC3.foo != "foo") return "Fail 48"
if (EC.EC3.bar != "bar") return "Fail 49"
if (EC.EC3.baz != "ec3") return "Fail 50"
if (EC.EC3.bay() != "bay") return "Fail 51"
return "OK";
}
@@ -33,4 +33,19 @@ declare namespace JS_TESTS {
constructor();
}
}
abstract class EnumClass {
private constructor();
static readonly EC1: EnumClass & {
readonly name: "EC1";
readonly ordinal: 0;
};
static readonly EC2: EnumClass & {
readonly name: "EC2";
readonly ordinal: 1;
};
static values(): Array<EnumClass>;
static valueOf(value: string): EnumClass;
readonly name: "EC1" | "EC2";
readonly ordinal: 0 | 1;
}
}
@@ -54,4 +54,9 @@ open class Class {
@JsName("publicFun") // TODO: Should work without JsName
public fun publicFun() = 10
public class publicClass
}
enum class EnumClass {
EC1,
EC2
}