From b5ad5edc0810de3f2cc8ffbc6d9558ffb4f4f50d Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Thu, 20 Apr 2023 16:41:58 +0200 Subject: [PATCH] [PL][JS] Add test for handling external declarations ^KT-57378 --- .../klibABI/externalDeclarations/lib1/l1.js | 19 ++++++++++ .../klibABI/externalDeclarations/lib1/l1.js.1 | 19 ++++++++++ .../klibABI/externalDeclarations/lib1/l1.kt | 9 +++++ .../klibABI/externalDeclarations/lib1/l1.kt.1 | 9 +++++ .../externalDeclarations/lib1/module.info | 7 ++++ .../klibABI/externalDeclarations/lib2/l2.js | 25 ++++++++++++ .../klibABI/externalDeclarations/lib2/l2.kt | 38 +++++++++++++++++++ .../externalDeclarations/lib2/module.info | 2 + .../klibABI/externalDeclarations/main/m.kt | 31 +++++++++++++++ .../externalDeclarations/main/module.info | 2 + .../klibABI/externalDeclarations/project.info | 7 ++++ ...JsPartialLinkageNoICTestCaseGenerated.java | 5 +++ ...JsPartialLinkageNoICTestCaseGenerated.java | 5 +++ ...PartialLinkageWithICTestCaseGenerated.java | 5 +++ .../FirNativePartialLinkageTestGenerated.java | 6 +++ .../NativePartialLinkageTestGenerated.java | 6 +++ .../AbstractNativePartialLinkageTest.kt | 11 ++++-- 17 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/klibABI/externalDeclarations/lib1/l1.js create mode 100644 compiler/testData/klibABI/externalDeclarations/lib1/l1.js.1 create mode 100644 compiler/testData/klibABI/externalDeclarations/lib1/l1.kt create mode 100644 compiler/testData/klibABI/externalDeclarations/lib1/l1.kt.1 create mode 100644 compiler/testData/klibABI/externalDeclarations/lib1/module.info create mode 100644 compiler/testData/klibABI/externalDeclarations/lib2/l2.js create mode 100644 compiler/testData/klibABI/externalDeclarations/lib2/l2.kt create mode 100644 compiler/testData/klibABI/externalDeclarations/lib2/module.info create mode 100644 compiler/testData/klibABI/externalDeclarations/main/m.kt create mode 100644 compiler/testData/klibABI/externalDeclarations/main/module.info create mode 100644 compiler/testData/klibABI/externalDeclarations/project.info diff --git a/compiler/testData/klibABI/externalDeclarations/lib1/l1.js b/compiler/testData/klibABI/externalDeclarations/lib1/l1.js new file mode 100644 index 00000000000..f385080f145 --- /dev/null +++ b/compiler/testData/klibABI/externalDeclarations/lib1/l1.js @@ -0,0 +1,19 @@ +function AbstractExternalClass() {} +AbstractExternalClass.prototype.abstractFunction = function() { + throw new Error("Calling abstract function AbstractExternalClass.abstractFunction"); +} +AbstractExternalClass.prototype.removedAbstractFunction = function() { + throw new Error("Calling abstract function AbstractExternalClass.removedAbstractFunction"); +} +// AbstractExternalClass.prototype.addedAbstractFunction = function() { +// throw new Error("Calling abstract function AbstractExternalClass.addedAbstractFunction"); +// } +AbstractExternalClass.prototype.function = function() { + return "AbstractExternalClass.function"; +} +AbstractExternalClass.prototype.removedFunction = function() { + return "AbstractExternalClass.removedFunction"; +} +// AbstractExternalClass.prototype.addedFunction = function() { +// return "AbstractExternalClass.addedFunction"; +// } diff --git a/compiler/testData/klibABI/externalDeclarations/lib1/l1.js.1 b/compiler/testData/klibABI/externalDeclarations/lib1/l1.js.1 new file mode 100644 index 00000000000..2c96afe3fce --- /dev/null +++ b/compiler/testData/klibABI/externalDeclarations/lib1/l1.js.1 @@ -0,0 +1,19 @@ +function AbstractExternalClass() {} +AbstractExternalClass.prototype.abstractFunction = function() { + throw new Error("Calling abstract function AbstractExternalClass.abstractFunction"); +} +// AbstractExternalClass.prototype.removedAbstractFunction = function() { +// throw new Error("Calling abstract function AbstractExternalClass.removedAbstractFunction"); +// } +AbstractExternalClass.prototype.addedAbstractFunction = function() { + throw new Error("Calling abstract function AbstractExternalClass.addedAbstractFunction"); +} +AbstractExternalClass.prototype.function = function() { + return "AbstractExternalClass.function"; +} +// AbstractExternalClass.prototype.removedFunction = function() { +// return "AbstractExternalClass.removedFunction"; +// } +AbstractExternalClass.prototype.addedFunction = function() { + return "AbstractExternalClass.addedFunction"; +} diff --git a/compiler/testData/klibABI/externalDeclarations/lib1/l1.kt b/compiler/testData/klibABI/externalDeclarations/lib1/l1.kt new file mode 100644 index 00000000000..31ce392c215 --- /dev/null +++ b/compiler/testData/klibABI/externalDeclarations/lib1/l1.kt @@ -0,0 +1,9 @@ +abstract external class AbstractExternalClass { + abstract fun abstractFunction(): String + abstract fun removedAbstractFunction(): String +// abstract fun addedAbstractFunction(): String + + fun function(): String + fun removedFunction(): String +// fun addedFunction(): String +} diff --git a/compiler/testData/klibABI/externalDeclarations/lib1/l1.kt.1 b/compiler/testData/klibABI/externalDeclarations/lib1/l1.kt.1 new file mode 100644 index 00000000000..62e98c38af6 --- /dev/null +++ b/compiler/testData/klibABI/externalDeclarations/lib1/l1.kt.1 @@ -0,0 +1,9 @@ +abstract external class AbstractExternalClass { + abstract fun abstractFunction(): String +// abstract fun removedAbstractFunction(): String + abstract fun addedAbstractFunction(): String + + fun function(): String +// fun removedFunction(): String + fun addedFunction(): String +} diff --git a/compiler/testData/klibABI/externalDeclarations/lib1/module.info b/compiler/testData/klibABI/externalDeclarations/lib1/module.info new file mode 100644 index 00000000000..c80e48ec945 --- /dev/null +++ b/compiler/testData/klibABI/externalDeclarations/lib1/module.info @@ -0,0 +1,7 @@ +STEP 0: + dependencies: stdlib +STEP 1: + dependencies: stdlib + modifications: + U : l1.kt.1 -> l1.kt + U : l1.js.1 -> l1.js diff --git a/compiler/testData/klibABI/externalDeclarations/lib2/l2.js b/compiler/testData/klibABI/externalDeclarations/lib2/l2.js new file mode 100644 index 00000000000..988d4d12a68 --- /dev/null +++ b/compiler/testData/klibABI/externalDeclarations/lib2/l2.js @@ -0,0 +1,25 @@ +function ExternalClassInheritedFromAbstractExternalClass() {} +ExternalClassInheritedFromAbstractExternalClass.prototype = Object.create(AbstractExternalClass.prototype); +ExternalClassInheritedFromAbstractExternalClass.prototype.abstractFunction = function() { + return "ExternalClassInheritedFromAbstractExternalClass.abstractFunction"; +} +ExternalClassInheritedFromAbstractExternalClass.prototype.removedAbstractFunction = function() { + return "ExternalClassInheritedFromAbstractExternalClass.removedAbstractFunction"; +} + +function OpenExternalClass() {} +OpenExternalClass.prototype.function = function() { + return "OpenExternalClass.function" +} + +function ExternalInterfaceInheritedFromOpenExternalClass() {} +ExternalInterfaceInheritedFromOpenExternalClass.prototype = Object.create(OpenExternalClass.prototype); +ExternalInterfaceInheritedFromOpenExternalClass.prototype.abstractFunction = function() { + throw new Error("Calling abstract function ExternalInterfaceInheritedFromOpenExternalClass.abstractFunction"); +} + +function ExternalClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass() {} +ExternalClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass.prototype = Object.create(ExternalInterfaceInheritedFromOpenExternalClass.prototype); +ExternalClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass.prototype.abstractFunction = function() { + return "ExternalClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass.abstractFunction" +} diff --git a/compiler/testData/klibABI/externalDeclarations/lib2/l2.kt b/compiler/testData/klibABI/externalDeclarations/lib2/l2.kt new file mode 100644 index 00000000000..59a0fd4459e --- /dev/null +++ b/compiler/testData/klibABI/externalDeclarations/lib2/l2.kt @@ -0,0 +1,38 @@ +@Suppress("ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED") +external class ExternalClassInheritedFromAbstractExternalClass : AbstractExternalClass { +// override fun abstractFunction(): String + override fun removedAbstractFunction(): String +} + +fun ExternalClassInheritedFromAbstractExternalClass.callRemovedFunction() = removedFunction() + +class RegularClassInheritedFromAbstractExternalClass : AbstractExternalClass() { + override fun abstractFunction() = "RegularClassInheritedFromAbstractExternalClass.abstractFunction" + override fun removedAbstractFunction() = "RegularClassInheritedFromAbstractExternalClass.removedAbstractFunction" +} + +fun RegularClassInheritedFromAbstractExternalClass.callRemovedFunction() = removedFunction() + +open external class OpenExternalClass { + fun function(): String +} + +@Suppress("INTERFACE_WITH_SUPERCLASS") +external interface ExternalInterfaceInheritedFromOpenExternalClass : OpenExternalClass { + fun abstractFunction(): String +} + +external class ExternalClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass : ExternalInterfaceInheritedFromOpenExternalClass { + override fun abstractFunction(): String +} + +class RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass : + ExternalInterfaceInheritedFromOpenExternalClass, + /* Note: Have to explicitly inherit from 'OpenExternalClass' becase otherwise JS codegen sees that + * class 'RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass' is inherited only from + * interface 'ExternalInterfaceInheritedFromOpenExternalClass' and does not figure out that a bridge has to be + * generated for function 'function' inherited from 'OpenExternalClass'. + */ + OpenExternalClass() { + override fun abstractFunction(): String = "RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass.abstractFunction" +} diff --git a/compiler/testData/klibABI/externalDeclarations/lib2/module.info b/compiler/testData/klibABI/externalDeclarations/lib2/module.info new file mode 100644 index 00000000000..391aab979a6 --- /dev/null +++ b/compiler/testData/klibABI/externalDeclarations/lib2/module.info @@ -0,0 +1,2 @@ +STEP 0: + dependencies: stdlib, lib1 \ No newline at end of file diff --git a/compiler/testData/klibABI/externalDeclarations/main/m.kt b/compiler/testData/klibABI/externalDeclarations/main/m.kt new file mode 100644 index 00000000000..e5955cbd697 --- /dev/null +++ b/compiler/testData/klibABI/externalDeclarations/main/m.kt @@ -0,0 +1,31 @@ +import abitestutils.abiTest +import abitestutils.TestBuilder + +fun box() = abiTest { + val ecifaec = ExternalClassInheritedFromAbstractExternalClass() + val rcifaec = RegularClassInheritedFromAbstractExternalClass() + val ecifeiifoec = ExternalClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass() + val rcifeiifoec = RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass() + + expectSuccess("ExternalClassInheritedFromAbstractExternalClass.abstractFunction") { ecifaec.abstractFunction() } + expectSuccess("ExternalClassInheritedFromAbstractExternalClass.removedAbstractFunction") { ecifaec.removedAbstractFunction() } + expectRuntimeFailure("Calling abstract function AbstractExternalClass.addedAbstractFunction") { ecifaec.addedAbstractFunction() } + expectSuccess("AbstractExternalClass.function") { ecifaec.function() } + expectFailure(linkage("Function 'removedFunction' can not be called: No function found for symbol '/ExternalClassInheritedFromAbstractExternalClass.removedFunction'")) { ecifaec.callRemovedFunction() } + expectSuccess("AbstractExternalClass.addedFunction") { ecifaec.addedFunction() } + + expectSuccess("RegularClassInheritedFromAbstractExternalClass.abstractFunction") { rcifaec.abstractFunction() } + expectSuccess("RegularClassInheritedFromAbstractExternalClass.removedAbstractFunction") { rcifaec.removedAbstractFunction() } + expectFailure(nonImplementedCallable("function 'addedAbstractFunction'", "class 'RegularClassInheritedFromAbstractExternalClass'")) { rcifaec.addedAbstractFunction() } + expectSuccess("AbstractExternalClass.function") { rcifaec.function() } + expectFailure(linkage("Function 'removedFunction' can not be called: No function found for symbol '/RegularClassInheritedFromAbstractExternalClass.removedFunction'")) { rcifaec.callRemovedFunction() } + expectSuccess("AbstractExternalClass.addedFunction") { rcifaec.addedFunction() } + + expectSuccess("OpenExternalClass.function") { ecifeiifoec.function() } + expectSuccess("ExternalClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass.abstractFunction") { ecifeiifoec.abstractFunction() } + expectSuccess("OpenExternalClass.function") { rcifeiifoec.function() } + expectSuccess("RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass.abstractFunction") { rcifeiifoec.abstractFunction() } +} + +private inline fun TestBuilder.expectRuntimeFailure(errorMessage: String, noinline block: () -> Any) = + expectFailure(custom { throwable -> throwable !is Exception && throwable.message == errorMessage }) { block() } diff --git a/compiler/testData/klibABI/externalDeclarations/main/module.info b/compiler/testData/klibABI/externalDeclarations/main/module.info new file mode 100644 index 00000000000..959e68004dc --- /dev/null +++ b/compiler/testData/klibABI/externalDeclarations/main/module.info @@ -0,0 +1,2 @@ +STEP 1: + dependencies: stdlib, lib1, lib2 diff --git a/compiler/testData/klibABI/externalDeclarations/project.info b/compiler/testData/klibABI/externalDeclarations/project.info new file mode 100644 index 00000000000..d175e5f27f1 --- /dev/null +++ b/compiler/testData/klibABI/externalDeclarations/project.info @@ -0,0 +1,7 @@ +MODULES: lib1, lib2, main + +STEP 0: + libs: lib1, lib2 + +STEP 1: + libs: lib1, main diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsPartialLinkageNoICTestCaseGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsPartialLinkageNoICTestCaseGenerated.java index c3a61fae222..11c83fd4a8c 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsPartialLinkageNoICTestCaseGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsPartialLinkageNoICTestCaseGenerated.java @@ -60,6 +60,11 @@ public class FirJsPartialLinkageNoICTestCaseGenerated extends AbstractFirJsParti runTest("compiler/testData/klibABI/classTransformations/"); } + @TestMetadata("externalDeclarations") + public void testExternalDeclarations() throws Exception { + runTest("compiler/testData/klibABI/externalDeclarations/"); + } + @TestMetadata("functionTransformations") public void testFunctionTransformations() throws Exception { runTest("compiler/testData/klibABI/functionTransformations/"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/JsPartialLinkageNoICTestCaseGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/JsPartialLinkageNoICTestCaseGenerated.java index 265eddf8846..a87888c07b4 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/JsPartialLinkageNoICTestCaseGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/JsPartialLinkageNoICTestCaseGenerated.java @@ -60,6 +60,11 @@ public class JsPartialLinkageNoICTestCaseGenerated extends AbstractJsPartialLink runTest("compiler/testData/klibABI/classTransformations/"); } + @TestMetadata("externalDeclarations") + public void testExternalDeclarations() throws Exception { + runTest("compiler/testData/klibABI/externalDeclarations/"); + } + @TestMetadata("functionTransformations") public void testFunctionTransformations() throws Exception { runTest("compiler/testData/klibABI/functionTransformations/"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/JsPartialLinkageWithICTestCaseGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/JsPartialLinkageWithICTestCaseGenerated.java index 17f98de9ca3..c7cd27b18f8 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/JsPartialLinkageWithICTestCaseGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/JsPartialLinkageWithICTestCaseGenerated.java @@ -60,6 +60,11 @@ public class JsPartialLinkageWithICTestCaseGenerated extends AbstractJsPartialLi runTest("compiler/testData/klibABI/classTransformations/"); } + @TestMetadata("externalDeclarations") + public void testExternalDeclarations() throws Exception { + runTest("compiler/testData/klibABI/externalDeclarations/"); + } + @TestMetadata("functionTransformations") public void testFunctionTransformations() throws Exception { runTest("compiler/testData/klibABI/functionTransformations/"); diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/FirNativePartialLinkageTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/FirNativePartialLinkageTestGenerated.java index bcdd2b0c8ee..649581125bc 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/FirNativePartialLinkageTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/FirNativePartialLinkageTestGenerated.java @@ -62,6 +62,12 @@ public class FirNativePartialLinkageTestGenerated extends AbstractNativePartialL runTest("compiler/testData/klibABI/classTransformations/"); } + @Test + @TestMetadata("externalDeclarations") + public void testExternalDeclarations() throws Exception { + runTest("compiler/testData/klibABI/externalDeclarations/"); + } + @Test @TestMetadata("functionTransformations") public void testFunctionTransformations() throws Exception { diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativePartialLinkageTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativePartialLinkageTestGenerated.java index 5d37c8d5db5..ea8f4200abf 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativePartialLinkageTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativePartialLinkageTestGenerated.java @@ -60,6 +60,12 @@ public class NativePartialLinkageTestGenerated extends AbstractNativePartialLink runTest("compiler/testData/klibABI/classTransformations/"); } + @Test + @TestMetadata("externalDeclarations") + public void testExternalDeclarations() throws Exception { + runTest("compiler/testData/klibABI/externalDeclarations/"); + } + @Test @TestMetadata("functionTransformations") public void testFunctionTransformations() throws Exception { diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/AbstractNativePartialLinkageTest.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/AbstractNativePartialLinkageTest.kt index 13c8820c2a0..a7033f67dac 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/AbstractNativePartialLinkageTest.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/AbstractNativePartialLinkageTest.kt @@ -57,9 +57,14 @@ abstract class AbstractNativePartialLinkageTest : AbstractNativeSimpleTest() { override fun onNonEmptyBuildDirectory(directory: File) = backupDirectoryContents(directory) // Temporarily mute TA tests on FIR FE with caches. - override fun isIgnoredTest(projectInfo: ProjectInfo) = super.isIgnoredTest(projectInfo) - || (projectInfo.name == "typeAliasChanges" && testModeName.endsWith("STATIC_EVERYWHERE") - && this@AbstractNativePartialLinkageTest::class.java.simpleName.startsWith("Fir")) + override fun isIgnoredTest(projectInfo: ProjectInfo) = when { + super.isIgnoredTest(projectInfo) -> true + projectInfo.name == "typeAliasChanges" + && testModeName.endsWith("STATIC_EVERYWHERE") + && this@AbstractNativePartialLinkageTest::class.java.simpleName.startsWith("Fir") -> true + projectInfo.name == "externalDeclarations" -> true + else -> false + } override fun onIgnoredTest() = throw TestAbortedException() }