Skip to content

Commit b0c54ed

Browse files
committed
Support special characters in coroutine names in JSON dumps
1 parent 0a19a24 commit b0c54ed

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ internal object DebugProbesImpl {
184184
val coroutinesInfoAsJson = ArrayList<String>(size)
185185
for (info in coroutinesInfo) {
186186
val context = info.context
187-
val name = context[CoroutineName.Key]?.name?.toStringWithQuotes()
188-
val dispatcher = context[CoroutineDispatcher.Key]?.toStringWithQuotes()
187+
val name = context[CoroutineName.Key]?.name?.toStringRepr()
188+
val dispatcher = context[CoroutineDispatcher.Key]?.toStringRepr()
189189
coroutinesInfoAsJson.add(
190190
"""
191191
{
@@ -221,7 +221,7 @@ internal object DebugProbesImpl {
221221
{
222222
"declaringClass": "${element.className}",
223223
"methodName": "${element.methodName}",
224-
"fileName": ${element.fileName?.toStringWithQuotes()},
224+
"fileName": ${element.fileName?.toStringRepr()},
225225
"lineNumber": ${element.lineNumber}
226226
}
227227
""".trimIndent()
@@ -231,7 +231,7 @@ internal object DebugProbesImpl {
231231
return "[${stackTraceElementsInfoAsJson.joinToString()}]"
232232
}
233233

234-
private fun Any.toStringWithQuotes() = "\"$this\""
234+
private fun Any.toStringRepr() = toString().repr()
235235

236236
/*
237237
* Internal (JVM-public) method used by IDEA debugger as of 1.4-M3.
@@ -307,7 +307,6 @@ internal object DebugProbesImpl {
307307
* Internal (JVM-public) method used by IDEA debugger as of 1.4-M3.
308308
* It is similar to [enhanceStackTraceWithThreadDumpImpl], but uses debugger-facing [DebugCoroutineInfo] type.
309309
*/
310-
@Suppress("unused")
311310
fun enhanceStackTraceWithThreadDump(
312311
info: DebugCoroutineInfo,
313312
coroutineTrace: List<StackTraceElement>
@@ -592,3 +591,19 @@ internal object DebugProbesImpl {
592591

593592
private val StackTraceElement.isInternalMethod: Boolean get() = className.startsWith("kotlinx.coroutines")
594593
}
594+
595+
private fun String.repr(): String = buildString {
596+
append('"')
597+
for (c in this@repr) {
598+
when (c) {
599+
'"' -> append("\\\"")
600+
'\\' -> append("\\\\")
601+
'\b' -> append("\\b")
602+
'\n' -> append("\\n")
603+
'\r' -> append("\\r")
604+
'\t' -> append("\\t")
605+
else -> append(c)
606+
}
607+
}
608+
append('"')
609+
}

kotlinx-coroutines-debug/test/DumpCoroutineInfoAsJsonAndReferencesTest.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ class DumpCoroutineInfoAsJsonAndReferencesTest : DebugTestBase() {
2929
fun testDumpOfNamedCoroutine() =
3030
runTestWithNamedDeferred("Name")
3131

32+
@Test
33+
fun testDumpOfNamedCoroutineWithSpecialCharacters() =
34+
runTestWithNamedDeferred("Name with\n \"special\" characters\\/\t\b")
35+
3236
@Test
3337
fun testDumpWithNoCoroutines() {
3438
val dumpResult = DebugProbesImpl.dumpCoroutinesInfoAsJsonAndReferences()

0 commit comments

Comments
 (0)