Calling coroutines/suspend functions via reflection


#1

So I want to call coroutines/suspend functions via reflection. I hacked around until I got something working, see below. Can anyone confirm that this is the proper way to call suspend functions via reflection?

class FieldGetterCoroutine(
    private val callable: KCallable<*>,
    private val params: Array<ParamInfo>
) {
    suspend fun invoke(receiver: Any): Any? {
        return suspendCoroutineOrReturn { cont ->
            val args = arrayOfNulls<Any?>(params.size)

            for (i in params.indices) {
                val param = params[i]

                args[i] = when (param.kind) {
                    ParamKind.THIS -> receiver
                    ParamKind.CONTINUATION -> cont
                    else -> /* some other cases, not that relevant */
                }
            }

            try {
                return@suspendCoroutineOrReturn callable.call(*args)
            } catch (e: InvocationTargetException) {
                throw e.targetException
            }
        }
    }
}

#2

Anyone? @elizarov maybe? :slight_smile:

Also, would it make sense to add a callSuspending() to KFunction (or maybe KCallable) in standard library, to help anyone else that wants to do this?


#3

Yes. I confirm that that is the indented way to call suspending functions via reflection. Adding a specialized means to Kotlin reflection for them is to be considered when coroutines get graduated and drop their experimental part package name (we cannot reference experimental package from reflection, so doing it now is out of the question).


#4

Excellent. Thank you!