All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jvmMain.debug.CoroutineDebugging.kt Maven / Gradle / Ivy

The newest version!
/* This package name is like this so that
1) the artificial stack frames look pretty, and
2) the IDE reliably navigates to this file. */
package _COROUTINE

/**
 * A collection of artificial stack trace elements to be included in stack traces by the coroutines machinery.
 *
 * There are typically two ways in which one can encounter an artificial stack frame:
 * 1. By using the debug mode, via the stacktrace recovery mechanism; see
 * [stacktrace recovery](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/topics/debugging.md#stacktrace-recovery)
 * documentation. The usual way to enable the debug mode is with the [kotlinx.coroutines.DEBUG_PROPERTY_NAME] system
 * property.
 * 2. By looking at the output of DebugProbes; see the
 * [kotlinx-coroutines-debug](https://github.com/Kotlin/kotlinx.coroutines/tree/master/kotlinx-coroutines-debug) module.
 */
internal class ArtificialStackFrames {
    /**
     * Returns an artificial stack trace element denoting the boundary between coroutine creation and its execution.
     *
     * Appearance of this function in stack traces does not mean that it was called. Instead, it is used as a marker
     * that separates the part of the stack trace with the code executed in a coroutine from the stack trace of the code
     * that launched the coroutine.
     *
     * In earlier versions of kotlinx-coroutines, this was displayed as "(Coroutine creation stacktrace)", which caused
     * problems for tooling that processes stack traces: https://github.com/Kotlin/kotlinx.coroutines/issues/2291
     *
     * Note that presence of this marker in a stack trace implies that coroutine creation stack traces were enabled.
     */
    fun coroutineCreation(): StackTraceElement = Exception().artificialFrame(_CREATION::class.java.simpleName)

    /**
     * Returns an artificial stack trace element denoting a coroutine boundary.
     *
     * Appearance of this function in stack traces does not mean that it was called. Instead, when one coroutine invokes
     * another, this is used as a marker in the stack trace to denote where the execution of one coroutine ends and that
     * of another begins.
     *
     * In earlier versions of kotlinx-coroutines, this was displayed as "(Coroutine boundary)", which caused
     * problems for tooling that processes stack traces: https://github.com/Kotlin/kotlinx.coroutines/issues/2291
     */
    fun coroutineBoundary(): StackTraceElement = Exception().artificialFrame(_BOUNDARY::class.java.simpleName)
}

// These are needed for the IDE navigation to detect that this file does contain the definition.
private class _CREATION
private class _BOUNDARY

internal val ARTIFICIAL_FRAME_PACKAGE_NAME = "_COROUTINE"

/**
 * Forms an artificial stack frame with the given class name.
 *
 * It consists of the following parts:
 * 1. The package name, it seems, is needed for the IDE to detect stack trace elements reliably. It is `_COROUTINE` since
 * this is a valid identifier.
 * 2. Class names represents what type of artificial frame this is.
 * 3. The method name is `_`. The methods not being present in class definitions does not seem to affect navigation.
 */
private fun Throwable.artificialFrame(name: String): StackTraceElement =
    with(stackTrace[0]) { StackTraceElement(ARTIFICIAL_FRAME_PACKAGE_NAME + "." + name, "_", fileName, lineNumber) }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy