Skip to content

Commit 99b4758

Browse files
authored
Test invariant that IDEA evaluator depends on (#2525)
Fixes #2522
1 parent 40f79ff commit 99b4758

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.coroutines
6+
7+
import org.junit.Test
8+
import kotlin.coroutines.*
9+
import kotlin.test.*
10+
11+
class IntellijIdeaDebuggerEvaluatorCompatibilityTest {
12+
13+
/*
14+
* This test verifies that our CoroutineScope is accessible to IDEA debugger.
15+
*
16+
* Consider the following scenario:
17+
* ```
18+
* runBlocking<Unit> { // this: CoroutineScope
19+
* println("runBlocking")
20+
* }
21+
* ```
22+
* user puts breakpoint to `println` line, opens "Evaluate" window
23+
* and executes `launch { println("launch") }`. They (obviously) expect it to work, but
24+
* it won't: `{}` in `runBlocking` is `SuspendLambda` and `this` is an unused implicit receiver
25+
* that is removed by the compiler (because it's unused).
26+
*
27+
* But we still want to provide consistent user experience for functions with `CoroutineScope` receiver,
28+
* for that IDEA debugger tries to retrieve the scope via `kotlin.coroutines.coroutineContext[Job] as? CoroutineScope`
29+
* and with this test we're fixing this behaviour.
30+
*
31+
* Note that this behaviour is not carved in stone: IDEA fallbacks to `kotlin.coroutines.coroutineContext` for the context if necessary.
32+
*/
33+
34+
@Test
35+
fun testScopeIsAccessible() = runBlocking<Unit> {
36+
verify()
37+
38+
withContext(Job()) {
39+
verify()
40+
}
41+
42+
coroutineScope {
43+
verify()
44+
}
45+
46+
supervisorScope {
47+
verify()
48+
}
49+
50+
}
51+
52+
private suspend fun verify() {
53+
val ctx = coroutineContext
54+
assertTrue { ctx.job is CoroutineScope }
55+
}
56+
}

0 commit comments

Comments
 (0)