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