JVM: parse KotlinDebug when regenerating anonymous objects
This commit is contained in:
+3
-4
@@ -20,6 +20,7 @@ import com.intellij.util.containers.ConcurrentFactoryMap
|
||||
import com.sun.jdi.Location
|
||||
import com.sun.jdi.ReferenceType
|
||||
import com.sun.jdi.VirtualMachine
|
||||
import org.jetbrains.kotlin.codegen.inline.SMAP
|
||||
import org.jetbrains.kotlin.idea.caches.project.implementingModules
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.core.util.getLineCount
|
||||
@@ -74,7 +75,7 @@ fun createWeakBytecodeDebugInfoStorage(): ConcurrentMap<BinaryCacheKey, Bytecode
|
||||
}
|
||||
}
|
||||
|
||||
class BytecodeDebugInfo(val smapData: SmapData?, val lineTableMapping: Map<BytecodeMethodKey, Map<String, Set<Int>>>)
|
||||
class BytecodeDebugInfo(val smapData: SMAP?, val lineTableMapping: Map<BytecodeMethodKey, Map<String, Set<Int>>>)
|
||||
|
||||
data class BytecodeMethodKey(val methodName: String, val signature: String)
|
||||
|
||||
@@ -259,9 +260,7 @@ private fun inlinedLinesNumbers(
|
||||
val debugInfo = readBytecodeInfo(project, jvmClassName, virtualFile) ?: return listOf()
|
||||
val smapData = debugInfo.smapData ?: return listOf()
|
||||
|
||||
val smap = smapData.kotlinStrata ?: return listOf()
|
||||
|
||||
val mappingsToInlinedFile = smap.fileMappings.filter { it.name == inlineFileName }
|
||||
val mappingsToInlinedFile = smapData.fileMappings.filter { it.name == inlineFileName }
|
||||
val mappingIntervals = mappingsToInlinedFile.flatMap { it.lineMappings }
|
||||
|
||||
return mappingIntervals.asSequence().filter { rangeMapping -> rangeMapping.hasMappingForSource(inlineLineNumber) }
|
||||
|
||||
+11
-47
@@ -7,9 +7,7 @@ package org.jetbrains.kotlin.idea.debugger
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.codegen.inline.FileMapping
|
||||
import org.jetbrains.kotlin.codegen.inline.SMAP
|
||||
import org.jetbrains.kotlin.codegen.inline.SMAPParser
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
||||
@@ -22,36 +20,27 @@ enum class SourceLineKind {
|
||||
}
|
||||
|
||||
fun mapStacktraceLineToSource(
|
||||
smapData: SmapData,
|
||||
smapData: SMAP,
|
||||
line: Int,
|
||||
project: Project,
|
||||
lineKind: SourceLineKind,
|
||||
searchScope: GlobalSearchScope
|
||||
): Pair<KtFile, Int>? {
|
||||
val smap = when (lineKind) {
|
||||
SourceLineKind.CALL_LINE -> smapData.kotlinDebugStrata
|
||||
SourceLineKind.EXECUTED_LINE -> smapData.kotlinStrata
|
||||
val interval = smapData.findRange(line) ?: return null
|
||||
val location = when (lineKind) {
|
||||
SourceLineKind.CALL_LINE -> interval.callSite
|
||||
SourceLineKind.EXECUTED_LINE -> interval.mapDestToSource(line)
|
||||
} ?: return null
|
||||
|
||||
val mappingInfo = smap.fileMappings.firstOrNull {
|
||||
it.getIntervalIfContains(line) != null
|
||||
} ?: return null
|
||||
|
||||
val jvmName = JvmClassName.byInternalName(mappingInfo.path)
|
||||
val jvmName = JvmClassName.byInternalName(location.path)
|
||||
val sourceFile = DebuggerUtils.findSourceFileForClassIncludeLibrarySources(
|
||||
project, searchScope, jvmName, mappingInfo.name
|
||||
project, searchScope, jvmName, location.file
|
||||
) ?: return null
|
||||
|
||||
val interval = mappingInfo.getIntervalIfContains(line)!!
|
||||
val sourceLine = when (lineKind) {
|
||||
SourceLineKind.CALL_LINE -> interval.source - 1
|
||||
SourceLineKind.EXECUTED_LINE -> interval.mapDestToSource(line) - 1
|
||||
}
|
||||
|
||||
return sourceFile to sourceLine
|
||||
return sourceFile to location.line - 1
|
||||
}
|
||||
|
||||
fun readDebugInfo(bytes: ByteArray): SmapData? {
|
||||
fun readDebugInfo(bytes: ByteArray): SMAP? {
|
||||
val cr = ClassReader(bytes)
|
||||
var debugInfo: String? = null
|
||||
cr.accept(object : ClassVisitor(Opcodes.API_VERSION) {
|
||||
@@ -59,30 +48,5 @@ fun readDebugInfo(bytes: ByteArray): SmapData? {
|
||||
debugInfo = debug
|
||||
}
|
||||
}, ClassReader.SKIP_FRAMES and ClassReader.SKIP_CODE)
|
||||
return debugInfo?.let(::SmapData)
|
||||
return debugInfo?.let(SMAPParser::parseOrNull)
|
||||
}
|
||||
|
||||
class SmapData(debugInfo: String) {
|
||||
var kotlinStrata: SMAP?
|
||||
var kotlinDebugStrata: SMAP?
|
||||
|
||||
init {
|
||||
val intervals = debugInfo.split(SMAP.END).filter(String::isNotBlank)
|
||||
when (intervals.count()) {
|
||||
1 -> {
|
||||
kotlinStrata = SMAPParser.parse(intervals[0] + SMAP.END)
|
||||
kotlinDebugStrata = null
|
||||
}
|
||||
2 -> {
|
||||
kotlinStrata = SMAPParser.parse(intervals[0] + SMAP.END)
|
||||
kotlinDebugStrata = SMAPParser.parse(intervals[1] + SMAP.END)
|
||||
}
|
||||
else -> {
|
||||
kotlinStrata = null
|
||||
kotlinDebugStrata = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FileMapping.getIntervalIfContains(destLine: Int) = lineMappings.firstOrNull { it.contains(destLine) }
|
||||
|
||||
Reference in New Issue
Block a user