1 /* This package name is like this so that 2 1) the artificial stack frames look pretty, and 3 2) the IDE reliably navigates to this file. */ 4 package _COROUTINE 5 6 /** 7 * A collection of artificial stack trace elements to be included in stack traces by the coroutines machinery. 8 * 9 * There are typically two ways in which one can encounter an artificial stack frame: 10 * 1. By using the debug mode, via the stacktrace recovery mechanism; see 11 * [stacktrace recovery](https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/topics/debugging.md#stacktrace-recovery) 12 * documentation. The usual way to enable the debug mode is with the [kotlinx.coroutines.DEBUG_PROPERTY_NAME] system 13 * property. 14 * 2. By looking at the output of DebugProbes; see the 15 * [kotlinx-coroutines-debug](https://github.com/Kotlin/kotlinx.coroutines/tree/master/kotlinx-coroutines-debug) module. 16 */ 17 internal class ArtificialStackFrames { 18 /** 19 * Returns an artificial stack trace element denoting the boundary between coroutine creation and its execution. 20 * 21 * Appearance of this function in stack traces does not mean that it was called. Instead, it is used as a marker 22 * that separates the part of the stack trace with the code executed in a coroutine from the stack trace of the code 23 * that launched the coroutine. 24 * 25 * In earlier versions of kotlinx-coroutines, this was displayed as "(Coroutine creation stacktrace)", which caused 26 * problems for tooling that processes stack traces: https://github.com/Kotlin/kotlinx.coroutines/issues/2291 27 * 28 * Note that presence of this marker in a stack trace implies that coroutine creation stack traces were enabled. 29 */ coroutineCreationnull30 fun coroutineCreation(): StackTraceElement = Exception().artificialFrame(_CREATION::class.java.simpleName) 31 32 /** 33 * Returns an artificial stack trace element denoting a coroutine boundary. 34 * 35 * Appearance of this function in stack traces does not mean that it was called. Instead, when one coroutine invokes 36 * another, this is used as a marker in the stack trace to denote where the execution of one coroutine ends and that 37 * of another begins. 38 * 39 * In earlier versions of kotlinx-coroutines, this was displayed as "(Coroutine boundary)", which caused 40 * problems for tooling that processes stack traces: https://github.com/Kotlin/kotlinx.coroutines/issues/2291 41 */ 42 fun coroutineBoundary(): StackTraceElement = Exception().artificialFrame(_BOUNDARY::class.java.simpleName) 43 } 44 45 // These are needed for the IDE navigation to detect that this file does contain the definition. 46 private class _CREATION 47 private class _BOUNDARY 48 49 internal val ARTIFICIAL_FRAME_PACKAGE_NAME = "_COROUTINE" 50 51 /** 52 * Forms an artificial stack frame with the given class name. 53 * 54 * It consists of the following parts: 55 * 1. The package name, it seems, is needed for the IDE to detect stack trace elements reliably. It is `_COROUTINE` since 56 * this is a valid identifier. 57 * 2. Class names represents what type of artificial frame this is. 58 * 3. The method name is `_`. The methods not being present in class definitions does not seem to affect navigation. 59 */ 60 private fun Throwable.artificialFrame(name: String): StackTraceElement = 61 with(stackTrace[0]) { StackTraceElement(ARTIFICIAL_FRAME_PACKAGE_NAME + "." + name, "_", fileName, lineNumber) } 62