[PL][JS] Add test for handling external declarations

^KT-57378
This commit is contained in:
Dmitriy Dolovov
2023-04-20 16:41:58 +02:00
committed by Space Team
parent 4afc5315ca
commit b5ad5edc08
17 changed files with 203 additions and 3 deletions
@@ -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";
// }
@@ -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";
}
@@ -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
}
@@ -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
}
@@ -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
@@ -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"
}
@@ -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"
}
@@ -0,0 +1,2 @@
STEP 0:
dependencies: stdlib, lib1
@@ -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() }
@@ -0,0 +1,2 @@
STEP 1:
dependencies: stdlib, lib1, lib2
@@ -0,0 +1,7 @@
MODULES: lib1, lib2, main
STEP 0:
libs: lib1, lib2
STEP 1:
libs: lib1, main
@@ -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/");
@@ -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/");
@@ -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/");
@@ -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 {
@@ -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 {
@@ -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()
}