JS: support SAM conversion
The SAM adapter is generate on declaration site. This is different from the JVM approach. `external fun interface` is banned for now. Reusing interface declaration for the adapter is a hack which reduces code size and makes importing/exporting the adapter effortless.
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JS
|
|
||||||
// SKIP_DCE_DRIVEN
|
// SKIP_DCE_DRIVEN
|
||||||
|
|
||||||
fun interface Foo {
|
fun interface Foo {
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
||||||
|
|
||||||
|
// IGNORE_BACKEND: JVM, JVM_IR, JS_IR
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// SKIP_DCE_DRIVEN
|
||||||
|
|
||||||
|
fun interface Base {
|
||||||
|
fun doStuff(): String
|
||||||
|
}
|
||||||
|
|
||||||
|
fun interface I : Base
|
||||||
|
|
||||||
|
fun interface Proxy : I {
|
||||||
|
|
||||||
|
override fun doStuff(): String = doStuffInt().toString()
|
||||||
|
|
||||||
|
fun doStuffInt(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
fun runBase(b: Base) = b.doStuff()
|
||||||
|
|
||||||
|
fun runI(i: I) = i.doStuff()
|
||||||
|
|
||||||
|
fun runProxy(p: Proxy) = p.doStuff()
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
|
||||||
|
if (runI { "i" } != "i") return "fail1"
|
||||||
|
|
||||||
|
if (runProxy { 10 } != "10") return "fail2"
|
||||||
|
|
||||||
|
return runBase { "OK" }
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
||||||
|
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// SKIP_DCE_DRIVEN
|
||||||
|
|
||||||
|
// MODULE: m1
|
||||||
|
// FILE: m1.kt
|
||||||
|
|
||||||
|
fun interface I {
|
||||||
|
fun f(): String
|
||||||
|
}
|
||||||
|
|
||||||
|
fun rn(i: I) = i.f()
|
||||||
|
|
||||||
|
inline fun rnInline(i: I) = i.f()
|
||||||
|
|
||||||
|
// MODULE: m2(m1)
|
||||||
|
// FILE: m2.kt
|
||||||
|
|
||||||
|
fun rn2(f: () -> String) = rn(f)
|
||||||
|
|
||||||
|
inline fun rn2Inline(noinline f: () -> String) = rnInline(f)
|
||||||
|
|
||||||
|
// MODULE: main(m2)
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
|
||||||
|
if (rn2Inline { "inline" } != "inline") return "fail"
|
||||||
|
|
||||||
|
return rn2 { "OK" }
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JS
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// SKIP_DCE_DRIVEN
|
// SKIP_DCE_DRIVEN
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JS
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// SKIP_DCE_DRIVEN
|
// SKIP_DCE_DRIVEN
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
||||||
|
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// SKIP_DCE_DRIVEN
|
||||||
|
|
||||||
|
// This test should check argument coercion between the SAM and the lambda.
|
||||||
|
// For now it checks that Char is boxed in JS
|
||||||
|
|
||||||
|
fun interface CharToAny {
|
||||||
|
fun invoke(c: Char): Any
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(c: CharToAny): Any = c.invoke('O')
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
|
||||||
|
if (foo { it } !is Char) return "fail"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JS
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// SKIP_DCE_DRIVEN
|
// SKIP_DCE_DRIVEN
|
||||||
|
|
||||||
|
|||||||
+16
-2
@@ -1,11 +1,11 @@
|
|||||||
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
// !LANGUAGE: +NewInference +FunctionalInterfaceConversion +SamConversionPerArgument +SamConversionForKotlinFunctions
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
// IGNORE_BACKEND: JS, JS_IR
|
// IGNORE_BACKEND: JS_IR
|
||||||
// WITH_COROUTINES
|
// WITH_COROUTINES
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|
||||||
import helpers.*
|
import helpers.*
|
||||||
import kotlin.coroutines.startCoroutine
|
import kotlin.coroutines.*
|
||||||
|
|
||||||
fun interface SuspendRunnable {
|
fun interface SuspendRunnable {
|
||||||
suspend fun invoke()
|
suspend fun invoke()
|
||||||
@@ -17,11 +17,25 @@ fun run(r: SuspendRunnable) {
|
|||||||
|
|
||||||
var result = "initial"
|
var result = "initial"
|
||||||
|
|
||||||
|
var resumingCallback: () -> Unit = {}
|
||||||
|
|
||||||
suspend fun bar() {
|
suspend fun bar() {
|
||||||
|
// Generate proper state machine
|
||||||
|
suspendCoroutine<Unit> { cont ->
|
||||||
|
resumingCallback = {
|
||||||
|
cont.resume(Unit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result = "OK"
|
result = "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
run(::bar)
|
run(::bar)
|
||||||
|
|
||||||
|
if (result != "initial") return "fail"
|
||||||
|
|
||||||
|
resumingCallback()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
+15
@@ -11723,11 +11723,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/funInterface/castFromAny.kt");
|
runTest("compiler/testData/codegen/box/funInterface/castFromAny.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("funInterfaceInheritance.kt")
|
||||||
|
public void testFunInterfaceInheritance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inlinedSamWrapper.kt")
|
@TestMetadata("inlinedSamWrapper.kt")
|
||||||
public void testInlinedSamWrapper() throws Exception {
|
public void testInlinedSamWrapper() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/inlinedSamWrapper.kt");
|
runTest("compiler/testData/codegen/box/funInterface/inlinedSamWrapper.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multimodule.kt")
|
||||||
|
public void testMultimodule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nullableSam.kt")
|
@TestMetadata("nullableSam.kt")
|
||||||
public void testNullableSam() throws Exception {
|
public void testNullableSam() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/nullableSam.kt");
|
runTest("compiler/testData/codegen/box/funInterface/nullableSam.kt");
|
||||||
@@ -11738,6 +11748,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("primitiveConversions.kt")
|
||||||
|
public void testPrimitiveConversions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/primitiveConversions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("receiverEvaluatedOnce.kt")
|
@TestMetadata("receiverEvaluatedOnce.kt")
|
||||||
public void testReceiverEvaluatedOnce() throws Exception {
|
public void testReceiverEvaluatedOnce() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
|
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
|
||||||
|
|||||||
+15
@@ -11700,6 +11700,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
public static class FunInterface extends AbstractLightAnalysisModeTest {
|
public static class FunInterface extends AbstractLightAnalysisModeTest {
|
||||||
|
@TestMetadata("funInterfaceInheritance.kt")
|
||||||
|
public void ignoreFunInterfaceInheritance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
private void runTest(String testDataFilePath) throws Exception {
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||||
}
|
}
|
||||||
@@ -11728,6 +11733,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/funInterface/inlinedSamWrapper.kt");
|
runTest("compiler/testData/codegen/box/funInterface/inlinedSamWrapper.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multimodule.kt")
|
||||||
|
public void testMultimodule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nullableSam.kt")
|
@TestMetadata("nullableSam.kt")
|
||||||
public void testNullableSam() throws Exception {
|
public void testNullableSam() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/nullableSam.kt");
|
runTest("compiler/testData/codegen/box/funInterface/nullableSam.kt");
|
||||||
@@ -11738,6 +11748,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("primitiveConversions.kt")
|
||||||
|
public void testPrimitiveConversions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/primitiveConversions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("receiverEvaluatedOnce.kt")
|
@TestMetadata("receiverEvaluatedOnce.kt")
|
||||||
public void testReceiverEvaluatedOnce() throws Exception {
|
public void testReceiverEvaluatedOnce() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
|
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
|
||||||
|
|||||||
+15
@@ -10593,11 +10593,21 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/funInterface/castFromAny.kt");
|
runTest("compiler/testData/codegen/box/funInterface/castFromAny.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("funInterfaceInheritance.kt")
|
||||||
|
public void testFunInterfaceInheritance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inlinedSamWrapper.kt")
|
@TestMetadata("inlinedSamWrapper.kt")
|
||||||
public void testInlinedSamWrapper() throws Exception {
|
public void testInlinedSamWrapper() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/inlinedSamWrapper.kt");
|
runTest("compiler/testData/codegen/box/funInterface/inlinedSamWrapper.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multimodule.kt")
|
||||||
|
public void testMultimodule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nullableSam.kt")
|
@TestMetadata("nullableSam.kt")
|
||||||
public void testNullableSam() throws Exception {
|
public void testNullableSam() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/nullableSam.kt");
|
runTest("compiler/testData/codegen/box/funInterface/nullableSam.kt");
|
||||||
@@ -10608,6 +10618,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("primitiveConversions.kt")
|
||||||
|
public void testPrimitiveConversions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/primitiveConversions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("receiverEvaluatedOnce.kt")
|
@TestMetadata("receiverEvaluatedOnce.kt")
|
||||||
public void testReceiverEvaluatedOnce() throws Exception {
|
public void testReceiverEvaluatedOnce() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
|
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
|
||||||
|
|||||||
+15
@@ -10593,11 +10593,21 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/funInterface/castFromAny.kt");
|
runTest("compiler/testData/codegen/box/funInterface/castFromAny.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("funInterfaceInheritance.kt")
|
||||||
|
public void testFunInterfaceInheritance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inlinedSamWrapper.kt")
|
@TestMetadata("inlinedSamWrapper.kt")
|
||||||
public void testInlinedSamWrapper() throws Exception {
|
public void testInlinedSamWrapper() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/inlinedSamWrapper.kt");
|
runTest("compiler/testData/codegen/box/funInterface/inlinedSamWrapper.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multimodule.kt")
|
||||||
|
public void testMultimodule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nullableSam.kt")
|
@TestMetadata("nullableSam.kt")
|
||||||
public void testNullableSam() throws Exception {
|
public void testNullableSam() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/nullableSam.kt");
|
runTest("compiler/testData/codegen/box/funInterface/nullableSam.kt");
|
||||||
@@ -10608,6 +10618,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("primitiveConversions.kt")
|
||||||
|
public void testPrimitiveConversions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/primitiveConversions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("receiverEvaluatedOnce.kt")
|
@TestMetadata("receiverEvaluatedOnce.kt")
|
||||||
public void testReceiverEvaluatedOnce() throws Exception {
|
public void testReceiverEvaluatedOnce() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
|
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
|
||||||
|
|||||||
Generated
+15
@@ -9073,6 +9073,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/funInterface/basicFunInterfaceConversion.kt");
|
runTest("compiler/testData/codegen/box/funInterface/basicFunInterfaceConversion.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("funInterfaceInheritance.kt")
|
||||||
|
public void testFunInterfaceInheritance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multimodule.kt")
|
||||||
|
public void testMultimodule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nullableSam.kt")
|
@TestMetadata("nullableSam.kt")
|
||||||
public void testNullableSam() throws Exception {
|
public void testNullableSam() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/nullableSam.kt");
|
runTest("compiler/testData/codegen/box/funInterface/nullableSam.kt");
|
||||||
@@ -9083,6 +9093,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("primitiveConversions.kt")
|
||||||
|
public void testPrimitiveConversions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/primitiveConversions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("receiverEvaluatedOnce.kt")
|
@TestMetadata("receiverEvaluatedOnce.kt")
|
||||||
public void testReceiverEvaluatedOnce() throws Exception {
|
public void testReceiverEvaluatedOnce() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
|
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
|
||||||
|
|||||||
+15
@@ -9073,6 +9073,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/funInterface/basicFunInterfaceConversion.kt");
|
runTest("compiler/testData/codegen/box/funInterface/basicFunInterfaceConversion.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("funInterfaceInheritance.kt")
|
||||||
|
public void testFunInterfaceInheritance() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/funInterfaceInheritance.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multimodule.kt")
|
||||||
|
public void testMultimodule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/multimodule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nullableSam.kt")
|
@TestMetadata("nullableSam.kt")
|
||||||
public void testNullableSam() throws Exception {
|
public void testNullableSam() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/nullableSam.kt");
|
runTest("compiler/testData/codegen/box/funInterface/nullableSam.kt");
|
||||||
@@ -9083,6 +9093,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
runTest("compiler/testData/codegen/box/funInterface/partialSam.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("primitiveConversions.kt")
|
||||||
|
public void testPrimitiveConversions() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/funInterface/primitiveConversions.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("receiverEvaluatedOnce.kt")
|
@TestMetadata("receiverEvaluatedOnce.kt")
|
||||||
public void testReceiverEvaluatedOnce() throws Exception {
|
public void testReceiverEvaluatedOnce() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
|
runTest("compiler/testData/codegen/box/funInterface/receiverEvaluatedOnce.kt");
|
||||||
|
|||||||
@@ -131,6 +131,8 @@ public final class Namer {
|
|||||||
|
|
||||||
public static final String IMPORTS_FOR_INLINE_PROPERTY = "$$importsForInline$$";
|
public static final String IMPORTS_FOR_INLINE_PROPERTY = "$$importsForInline$$";
|
||||||
|
|
||||||
|
public static final String SAM_FIELD_NAME = "function$";
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String getFunctionTag(@NotNull CallableDescriptor functionDescriptor, @NotNull JsConfig config) {
|
public static String getFunctionTag(@NotNull CallableDescriptor functionDescriptor, @NotNull JsConfig config) {
|
||||||
String intrinsicTag = ArrayFIF.INSTANCE.getTag(functionDescriptor, config);
|
String intrinsicTag = ArrayFIF.INSTANCE.getTag(functionDescriptor, config);
|
||||||
|
|||||||
@@ -119,6 +119,8 @@ class ClassTranslator private constructor(
|
|||||||
enumInitFunction.body.statements += JsAstUtils.asSyntheticStatement(initInvocation.source(companionDescriptor.source.getPsi()))
|
enumInitFunction.body.statements += JsAstUtils.asSyntheticStatement(initInvocation.source(companionDescriptor.source.getPsi()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maybeConvertInterfaceToSamAdapter(context, constructorFunction)
|
||||||
|
|
||||||
translatePrimaryConstructor(constructorFunction, context, delegationTranslator)
|
translatePrimaryConstructor(constructorFunction, context, delegationTranslator)
|
||||||
addMetadataObject()
|
addMetadataObject()
|
||||||
addMetadataType()
|
addMetadataType()
|
||||||
@@ -562,6 +564,42 @@ class ClassTranslator private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun maybeConvertInterfaceToSamAdapter(context: TranslationContext, constructorFunction: JsFunction) {
|
||||||
|
if (!descriptor.isFun) return
|
||||||
|
|
||||||
|
val paramName = context.scope().declareFreshName("f")
|
||||||
|
constructorFunction.parameters += JsParameter(paramName)
|
||||||
|
constructorFunction.body.statements += JsBinaryOperation(
|
||||||
|
JsBinaryOperator.ASG,
|
||||||
|
pureFqn(Namer.SAM_FIELD_NAME, JsThisRef()),
|
||||||
|
JsNameRef(paramName)
|
||||||
|
).makeStmt()
|
||||||
|
|
||||||
|
val samDescriptor = descriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
|
||||||
|
.filterIsInstance<FunctionDescriptor>()
|
||||||
|
.single { it.modality === Modality.ABSTRACT }
|
||||||
|
|
||||||
|
val function = context.getFunctionObject(samDescriptor)
|
||||||
|
val innerContext = context.newDeclaration(samDescriptor).translateAndAliasParameters(samDescriptor, function.parameters)
|
||||||
|
|
||||||
|
if (samDescriptor.isSuspend) {
|
||||||
|
function.fillCoroutineMetadata(innerContext, samDescriptor, hasController = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
val parameters = listOfNotNull(samDescriptor.extensionReceiverParameter) +
|
||||||
|
samDescriptor.valueParameters +
|
||||||
|
listOfNotNull(innerContext.continuationParameterDescriptor)
|
||||||
|
|
||||||
|
val arguments = parameters.map {
|
||||||
|
TranslationUtils.coerce(innerContext, innerContext.getAliasForDescriptor(it)!!, context.currentModule.builtIns.anyType)
|
||||||
|
}
|
||||||
|
|
||||||
|
function.body = JsBlock(JsReturn(JsInvocation(pureFqn(Namer.SAM_FIELD_NAME, JsThisRef()), arguments)))
|
||||||
|
|
||||||
|
context.addDeclarationStatement(context.addFunctionToPrototype(descriptor, samDescriptor, function))
|
||||||
|
}
|
||||||
|
|
||||||
private fun <T : JsNode> T.withDefaultLocation(): T = apply { source = classDeclaration }
|
private fun <T : JsNode> T.withDefaultLocation(): T = apply { source = classDeclaration }
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+3
-1
@@ -66,7 +66,9 @@ fun TranslationContext.translateAndAliasParameters(
|
|||||||
for (valueParameter in descriptor.valueParameters) {
|
for (valueParameter in descriptor.valueParameters) {
|
||||||
val name = getNameForDescriptor(valueParameter)
|
val name = getNameForDescriptor(valueParameter)
|
||||||
val tmpName = JsScope.declareTemporaryName(name.ident).also { it.descriptor = valueParameter }
|
val tmpName = JsScope.declareTemporaryName(name.ident).also { it.descriptor = valueParameter }
|
||||||
aliases[valueParameter] = JsAstUtils.pureFqn(tmpName, null)
|
val parameterRef = JsAstUtils.pureFqn(tmpName, null)
|
||||||
|
parameterRef.type = valueParameter.type
|
||||||
|
aliases[valueParameter] = parameterRef
|
||||||
targetList += JsParameter(tmpName).apply { hasDefaultValue = valueParameter.hasDefaultValue() }
|
targetList += JsParameter(tmpName).apply { hasDefaultValue = valueParameter.hasDefaultValue() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -545,6 +545,21 @@ public final class TranslationUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAM conversion
|
||||||
|
if ((FunctionTypesKt.isFunctionTypeOrSubtype(from) || FunctionTypesKt.isSuspendFunctionTypeOrSubtype(from))) {
|
||||||
|
ClassifierDescriptor d = to.getConstructor().getDeclarationDescriptor();
|
||||||
|
if (d instanceof ClassDescriptor && ((ClassDescriptor)d).isFun()) {
|
||||||
|
JsName constructorName = context.getInlineableInnerNameForDescriptor(d.getOriginal());
|
||||||
|
if (to.isMarkedNullable()) {
|
||||||
|
JsConditional c = TranslationUtils.notNullConditional(value, new JsNullLiteral(), context);
|
||||||
|
c.setThenExpression(new JsNew(new JsNameRef(constructorName), Collections.singletonList(c.getThenExpression())));
|
||||||
|
value = c;
|
||||||
|
} else {
|
||||||
|
value = new JsNew(new JsNameRef(constructorName), Collections.singletonList(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MetadataProperties.setType(value, to);
|
MetadataProperties.setType(value, to);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user