From 117df325c9cdb01e07d591153233c48f0511cad8 Mon Sep 17 00:00:00 2001 From: Artem Kobzar Date: Wed, 13 Jul 2022 15:20:27 +0000 Subject: [PATCH] [JS/IR] fix: add ability to render type constraints into TypeScript definitions. --- .../org/jetbrains/kotlin/ir/backend/js/export/ExportModel.kt | 2 +- .../kotlin/ir/backend/js/export/ExportModelGenerator.kt | 2 +- .../ir/backend/js/export/ExportModelToTsDeclarations.kt | 2 +- .../typescript-export/declarations/declarations.d.ts | 4 ++++ .../testData/typescript-export/declarations/declarations.kt | 3 +++ .../typescript-export/declarations/declarations__main.js | 3 +++ .../typescript-export/declarations/declarations__main.ts | 5 +++++ 7 files changed, 18 insertions(+), 3 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModel.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModel.kt index 42fef339e5c..9e08f8566b0 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModel.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModel.kt @@ -81,7 +81,7 @@ data class ExportedRegularClass( val isAbstract: Boolean = false, override val superClass: ExportedType? = null, override val superInterfaces: List = emptyList(), - val typeParameters: List, + val typeParameters: List, override val members: List, override val nestedClasses: List, override val ir: IrClass, 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 57797261cff..1c36ea1bd83 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 @@ -378,7 +378,7 @@ class ExportModelGenerator( members: List, nestedClasses: List ): ExportedDeclaration { - val typeParameters = klass.typeParameters.map { it.name.identifier } + val typeParameters = klass.typeParameters.map(::exportTypeParameter) // TODO: Handle non-exported super types diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToTsDeclarations.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToTsDeclarations.kt index 16f848ee701..93fb3476f9b 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToTsDeclarations.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelToTsDeclarations.kt @@ -258,7 +258,7 @@ class ExportModelToTsDeclarations { } val renderedTypeParameters = if (typeParameters.isNotEmpty()) { - "<" + typeParameters.joinToString(", ") + ">" + "<" + typeParameters.joinToString(", ") { it.toTypeScript(indent) } + ">" } else { "" } 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 1d97bcafa16..b55bf3b0a8d 100644 --- a/js/js.translator/testData/typescript-export/declarations/declarations.d.ts +++ b/js/js.translator/testData/typescript-export/declarations/declarations.d.ts @@ -234,6 +234,10 @@ declare namespace JS_TESTS { function createNested1(): typeof foo.Parent.Nested1; function createNested2(): foo.Parent.Nested1.Nested2; function createNested3(): foo.Parent.Nested1.Nested2.Companion.Nested3; + class GenericClassWithConstraint { + constructor(test: T); + get test(): T; + } } namespace _objects_ { const foo$Parent$Nested1: { diff --git a/js/js.translator/testData/typescript-export/declarations/declarations.kt b/js/js.translator/testData/typescript-export/declarations/declarations.kt index 0547b75c98c..65c894e3c00 100644 --- a/js/js.translator/testData/typescript-export/declarations/declarations.kt +++ b/js/js.translator/testData/typescript-export/declarations/declarations.kt @@ -295,3 +295,6 @@ fun createNested2(): Parent.Nested1.Nested2 { fun createNested3(): Parent.Nested1.Nested2.Companion.Nested3 { return Parent.Nested1.Nested2.Companion.Nested3() } + +@JsExport +class GenericClassWithConstraint(val test: T) \ 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 314051ae496..e4e24c19f20 100644 --- a/js/js.translator/testData/typescript-export/declarations/declarations__main.js +++ b/js/js.translator/testData/typescript-export/declarations/declarations__main.js @@ -37,6 +37,7 @@ var getParent = JS_TESTS.foo.getParent; var createNested1 = JS_TESTS.foo.createNested1; var createNested2 = JS_TESTS.foo.createNested2; var createNested3 = JS_TESTS.foo.createNested3; +var GenericClassWithConstraint = JS_TESTS.foo.GenericClassWithConstraint; function assert(condition) { if (!condition) { throw "Assertion failed"; @@ -150,5 +151,7 @@ function box() { assert(createNested1() === nested1); assert(createNested2() !== nested2); assert(createNested3() !== nested3); + var genericClassInstance = new GenericClassWithConstraint(new TestInterfaceImpl("test")); + assert(processInterface(genericClassInstance.test) == "Owner TestInterfaceImpl has value 'test'"); 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 f14bbdc9c82..3d60116db47 100644 --- a/js/js.translator/testData/typescript-export/declarations/declarations__main.ts +++ b/js/js.translator/testData/typescript-export/declarations/declarations__main.ts @@ -37,6 +37,7 @@ import getParent = JS_TESTS.foo.getParent; import createNested1 = JS_TESTS.foo.createNested1; import createNested2 = JS_TESTS.foo.createNested2; import createNested3 = JS_TESTS.foo.createNested3; +import GenericClassWithConstraint = JS_TESTS.foo.GenericClassWithConstraint; function assert(condition: boolean) { if (!condition) { @@ -182,5 +183,9 @@ function box(): string { assert(createNested1() === nested1) assert(createNested2() !== nested2) assert(createNested3() !== nested3) + + const genericClassInstance = new GenericClassWithConstraint(new TestInterfaceImpl("test")) + assert(processInterface(genericClassInstance.test) == "Owner TestInterfaceImpl has value 'test'") + return "OK"; } \ No newline at end of file