diff --git a/compiler/testData/codegen/box/coroutines/reflect/callSuspend.kt b/compiler/testData/codegen/box/coroutines/reflect/callSuspend.kt new file mode 100644 index 00000000000..ef928adf75d --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/reflect/callSuspend.kt @@ -0,0 +1,65 @@ +// !LANGUAGE: +ReleaseCoroutines +// WITH_COROUTINES +// WITH_REFLECT + +import helpers.* +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* +import kotlin.reflect.full.callSuspend + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +class A { + suspend fun noArgs() = "OK" + + suspend fun twoArgs(a: String, b: String) = "$a$b" +} + +suspend fun twoArgs(a: String, b: String) = "$a$b" + +fun ordinary() = "OK" + +var log = "" + +var proceed = {} + +suspend fun suspendHere() = suspendCoroutineUninterceptedOrReturn { cont -> + proceed = { + cont.resumeWith(SuccessOrFailure.success(Unit)) + } + COROUTINE_SUSPENDED +} + +suspend fun suspending() { + log += "before;" + suspendHere() + log += "after;" +} + +fun box(): String { + var res: String? = "" + builder { + res = A::class.members.find { it.name == "noArgs" }?.callSuspend(A()) as String? + } + if (res != "OK") return res ?: "FAIL 1" + builder { + res = A::class.members.find { it.name == "twoArgs" }?.callSuspend(A(), "O", "K") as String? + } + if (res != "OK") return res ?: "FAIL 2" + builder { + res = ::twoArgs.callSuspend("O", "K") as String? + } + if (res != "OK") return res ?: "FAIL 3" + builder { + res = ::ordinary.callSuspend() as String? + } + builder { + ::suspending.callSuspend() + } + log += "suspended;" + proceed() + if (log != "before;suspended;after;") return log + return res ?: "FAIL 4" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/reflect/callSuspendBy.kt b/compiler/testData/codegen/box/coroutines/reflect/callSuspendBy.kt new file mode 100644 index 00000000000..90cf4b498f1 --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/reflect/callSuspendBy.kt @@ -0,0 +1,73 @@ +// !LANGUAGE: +ReleaseCoroutines +// WITH_COROUTINES +// WITH_REFLECT + +import helpers.* +import kotlin.coroutines.* +import kotlin.coroutines.intrinsics.* +import kotlin.reflect.full.callSuspendBy + +fun builder(c: suspend () -> Unit) { + c.startCoroutine(EmptyContinuation) +} + +class A { + suspend fun noArgs() = "OK" + + suspend fun twoArgs(a: String, b: String) = "$a$b" +} + +suspend fun twoArgs(a: String, b: String) = "$a$b" + +fun ordinary() = "OK" + +suspend fun withDefault(s: String = "OK") = s + +var log = "" + +var proceed = {} + +suspend fun suspendHere() = suspendCoroutineUninterceptedOrReturn { cont -> + proceed = { + cont.resumeWith(SuccessOrFailure.success(Unit)) + } + COROUTINE_SUSPENDED +} + +suspend fun suspending() { + log += "before;" + suspendHere() + log += "after;" +} + +fun box(): String { + var res: String? = "" + builder { + val callable = A::class.members.find { it.name == "noArgs" }!! + res = callable.callSuspendBy(mapOf(callable.parameters.first() to A())) as String? + } + if (res != "OK") return res ?: "FAIL 1" + builder { + val callable = A::class.members.find { it.name == "twoArgs" }!! + res = callable.callSuspendBy(mapOf(callable.parameters[0] to A(), callable.parameters[1] to "O", callable.parameters[2] to "K")) as String? + } + if (res != "OK") return res ?: "FAIL 2" + builder { + res = ::twoArgs.callSuspendBy(mapOf(::twoArgs.parameters[0] to "O", ::twoArgs.parameters[1] to "K")) as String? + } + if (res != "OK") return res ?: "FAIL 3" + builder { + res = ::ordinary.callSuspendBy(emptyMap()) as String? + } + if (res != "OK") return res ?: "FAIL 4" + builder { + res = ::withDefault.callSuspendBy(emptyMap()) as String? + } + builder { + ::suspending.callSuspendBy(emptyMap()) + } + log += "suspended;" + proceed() + if (log != "before;suspended;after;") return log + return res ?: "FAIL 5" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/coroutines/reflect/isSuspend12.kt b/compiler/testData/codegen/box/coroutines/reflect/isSuspend12.kt new file mode 100644 index 00000000000..3fdb775757a --- /dev/null +++ b/compiler/testData/codegen/box/coroutines/reflect/isSuspend12.kt @@ -0,0 +1,15 @@ +// LANGUAGE_VERSION: 1.2 +// WITH_COROUTINES +// WITH_REFLECT + +import helpers.* +import kotlin.coroutines.experimental.* + +class A { + fun noArgs() = "OK" +} + +fun box(): String { + if (A::noArgs.isSuspend) return "FAIL" + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/modifiers/functions.kt b/compiler/testData/codegen/box/reflection/modifiers/functions.kt index f82fa0424a3..699f2ae0436 100644 --- a/compiler/testData/codegen/box/reflection/modifiers/functions.kt +++ b/compiler/testData/codegen/box/reflection/modifiers/functions.kt @@ -9,6 +9,7 @@ import kotlin.test.assertTrue import kotlin.test.assertFalse +import kotlin.reflect.full.isSuspend inline fun inline() {} class External { external fun external() } @@ -60,6 +61,7 @@ fun box(): String { assertFalse(::inlineProperty.getter.isExternal) assertTrue(::inlineProperty.getter.isInline) assertTrue(::inlineProperty.setter.isInline) + assertFalse(::inlineProperty.isSuspend) return "OK" } diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index af176b186e1..d8e92ed7c64 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -7390,6 +7390,34 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } } + @TestMetadata("compiler/testData/codegen/box/coroutines/reflect") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Reflect extends AbstractBlackBoxCodegenTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInReflect() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/reflect"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("callSuspend.kt") + public void testCallSuspend() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/callSuspend.kt"); + } + + @TestMetadata("callSuspendBy.kt") + public void testCallSuspendBy() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/callSuspendBy.kt"); + } + + @TestMetadata("isSuspend12.kt") + public void testIsSuspend12() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/isSuspend12.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 1c79cbee92e..d43337c32d7 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -7390,6 +7390,34 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes } } + @TestMetadata("compiler/testData/codegen/box/coroutines/reflect") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Reflect extends AbstractLightAnalysisModeTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInReflect() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/reflect"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("callSuspend.kt") + public void testCallSuspend() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/callSuspend.kt"); + } + + @TestMetadata("callSuspendBy.kt") + public void testCallSuspendBy() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/callSuspendBy.kt"); + } + + @TestMetadata("isSuspend12.kt") + public void testIsSuspend12() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/isSuspend12.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index ebaf00160b8..e2148077901 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -7390,6 +7390,34 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes } } + @TestMetadata("compiler/testData/codegen/box/coroutines/reflect") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Reflect extends AbstractIrBlackBoxCodegenTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); + } + + public void testAllFilesPresentInReflect() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/reflect"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); + } + + @TestMetadata("callSuspend.kt") + public void testCallSuspend() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/callSuspend.kt"); + } + + @TestMetadata("callSuspendBy.kt") + public void testCallSuspendBy() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/callSuspendBy.kt"); + } + + @TestMetadata("isSuspend12.kt") + public void testIsSuspend12() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/isSuspend12.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt b/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt index 16a9ee3091b..3668115aa27 100644 --- a/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt +++ b/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.generators.tests diff --git a/core/builtins/src/kotlin/reflect/KCallable.kt b/core/builtins/src/kotlin/reflect/KCallable.kt index b1f60b8cce1..e3086721c50 100644 --- a/core/builtins/src/kotlin/reflect/KCallable.kt +++ b/core/builtins/src/kotlin/reflect/KCallable.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. */ package kotlin.reflect @@ -87,4 +76,10 @@ public interface KCallable : KAnnotatedElement { */ @SinceKotlin("1.1") public val isAbstract: Boolean + + /** + * `true` if this is a suspending function. + */ + @SinceKotlin("1.3") + public val isSuspend: Boolean } diff --git a/core/builtins/src/kotlin/reflect/KFunction.kt b/core/builtins/src/kotlin/reflect/KFunction.kt index 46b05f2e1d7..359d3cfd8c1 100644 --- a/core/builtins/src/kotlin/reflect/KFunction.kt +++ b/core/builtins/src/kotlin/reflect/KFunction.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. */ package kotlin.reflect @@ -56,5 +45,5 @@ public interface KFunction : KCallable, Function { * `true` if this is a suspending function. */ @SinceKotlin("1.1") - public val isSuspend: Boolean + public override val isSuspend: Boolean } diff --git a/core/reflection.jvm/src/kotlin/reflect/full/KCallables.kt b/core/reflection.jvm/src/kotlin/reflect/full/KCallables.kt index 634371373ee..2f8d3df450f 100644 --- a/core/reflection.jvm/src/kotlin/reflect/full/KCallables.kt +++ b/core/reflection.jvm/src/kotlin/reflect/full/KCallables.kt @@ -1,23 +1,15 @@ /* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. */ @file:JvmName("KCallables") package kotlin.reflect.full +import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn +import kotlin.coroutines.Continuation import kotlin.reflect.* +import kotlin.reflect.jvm.internal.* /** * Returns a parameter representing the `this` instance needed to call this callable, @@ -49,3 +41,26 @@ val KCallable<*>.valueParameters: List fun KCallable<*>.findParameterByName(name: String): KParameter? { return parameters.singleOrNull { it.name == name } } + +/** + * Calls a callable in the current suspend context. If the callable is not a suspend function, behaves as [KCallable.call]. + * Otherwise, calls the suspend function with current continuation. + */ +@SinceKotlin("1.3") +suspend fun KCallable.callSuspend(vararg args: Any?): R { + if (!this.isSuspend) return call(*args) + if (this !is KFunction<*>) throw IllegalArgumentException("Cannot callSuspend on a property $this: suspend properties are not supported yet") + return suspendCoroutineUninterceptedOrReturn { call(*args, it) } +} + +/** + * Calls a callable in the current suspend context. If the callable is not a suspend function, behaves as [KCallable.callBy]. + * Otherwise, calls the suspend function with current continuation. + */ +@SinceKotlin("1.3") +suspend fun KCallable.callSuspendBy(args: Map): R { + if (!this.isSuspend) return callBy(args) + if (this !is KFunction<*>) throw IllegalArgumentException("Cannot callSuspendBy on a property $this: suspend properties are not supported yet") + val kCallable = asKCallableImpl() ?: throw KotlinReflectionInternalError("This callable does not support a default call: $this") + return suspendCoroutineUninterceptedOrReturn { kCallable.callDefaultMethod(args, it) } +} \ No newline at end of file diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt index fbdb5a0b579..6549f5f735f 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. */ package kotlin.reflect.jvm.internal @@ -21,6 +10,7 @@ import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor import java.lang.reflect.Type import java.util.* +import kotlin.coroutines.Continuation import kotlin.reflect.* import kotlin.reflect.jvm.javaType @@ -107,11 +97,11 @@ internal abstract class KCallableImpl : KCallable { } override fun callBy(args: Map): R { - return if (isAnnotationConstructor) callAnnotationConstructor(args) else callDefaultMethod(args) + return if (isAnnotationConstructor) callAnnotationConstructor(args) else callDefaultMethod(args, null) } // See ArgumentGenerator#generate - private fun callDefaultMethod(args: Map): R { + internal fun callDefaultMethod(args: Map, continuationArgument: Continuation<*>?): R { val parameters = parameters val arguments = ArrayList(parameters.size) var mask = 0 @@ -144,6 +134,10 @@ internal abstract class KCallableImpl : KCallable { } } + if (continuationArgument != null) { + arguments.add(continuationArgument) + } + if (!anyOptional) { return call(*arguments.toTypedArray()) } diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt index 6184ebe8401..8c87d86737d 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt @@ -1,17 +1,6 @@ /* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. */ package kotlin.reflect.jvm.internal @@ -120,6 +109,8 @@ internal abstract class KPropertyImpl private constructor( override val isConst: Boolean get() = descriptor.isConst + override val isSuspend: Boolean get() = false + override fun equals(other: Any?): Boolean { val that = other.asKPropertyImpl() ?: return false return container == that.container && name == that.name && signature == that.signature && boundReceiver == that.boundReceiver diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java index c06329c705c..735b4e7c8b6 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java @@ -6230,6 +6230,34 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/coroutines/reflect") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Reflect extends AbstractIrJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath); + } + + public void testAllFilesPresentInReflect() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/reflect"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS_IR, true); + } + + @TestMetadata("callSuspend.kt") + public void testCallSuspend() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/callSuspend.kt"); + } + + @TestMetadata("callSuspendBy.kt") + public void testCallSuspendBy() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/callSuspendBy.kt"); + } + + @TestMetadata("isSuspend12.kt") + public void testIsSuspend12() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/isSuspend12.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index d9148983f1b..3f2abde3472 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -7080,6 +7080,34 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { } } + @TestMetadata("compiler/testData/codegen/box/coroutines/reflect") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Reflect extends AbstractJsCodegenBoxTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath); + } + + public void testAllFilesPresentInReflect() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/reflect"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true); + } + + @TestMetadata("callSuspend.kt") + public void testCallSuspend() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/callSuspend.kt"); + } + + @TestMetadata("callSuspendBy.kt") + public void testCallSuspendBy() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/callSuspendBy.kt"); + } + + @TestMetadata("isSuspend12.kt") + public void testIsSuspend12() throws Exception { + runTest("compiler/testData/codegen/box/coroutines/reflect/isSuspend12.kt"); + } + } + @TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/CallableReference.java b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/CallableReference.java index ca5ee1df378..d44bf7892af 100644 --- a/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/CallableReference.java +++ b/libraries/stdlib/jvm/runtime/kotlin/jvm/internal/CallableReference.java @@ -166,4 +166,10 @@ public abstract class CallableReference implements KCallable, Serializable { public boolean isAbstract() { return getReflected().isAbstract(); } + + @Override + @SinceKotlin(version = "1.3") + public boolean isSuspend() { + return getReflected().isSuspend(); + } }