Print source file location/contents if possible (EA-120038)

This commit is contained in:
Yan Zhulanow
2018-05-24 00:01:49 +03:00
parent fc6057e34f
commit 4dfcb72fa1
5 changed files with 35 additions and 8 deletions
@@ -18,7 +18,7 @@ package org.jetbrains.kotlin.idea.debugger.evaluate
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.debugger.jdi.StackFrameProxyImpl
import com.intellij.openapi.diagnostic.Attachment
import com.sun.jdi.ClassType
import com.sun.jdi.InvalidStackFrameException
import com.sun.jdi.ObjectReference
@@ -30,14 +30,17 @@ import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.inline.INLINE_FUN_VAR_SUFFIX
import org.jetbrains.kotlin.codegen.inline.INLINE_TRANSFORMATION_SUFFIX
import org.jetbrains.kotlin.codegen.inline.NUMBERED_FUNCTION_PREFIX
import org.jetbrains.kotlin.idea.debugger.DebuggerUtils
import org.jetbrains.kotlin.idea.debugger.isInsideInlineFunctionBody
import org.jetbrains.kotlin.idea.debugger.numberOfInlinedFunctions
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.idea.util.attachment.mergeAttachments
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.org.objectweb.asm.Type
class FrameVisitor(context: EvaluationContextImpl) {
class FrameVisitor(val context: EvaluationContextImpl) {
private val scope = context.debugProcess.searchScope
private val frame = context.frameProxy
@@ -95,7 +98,31 @@ class FrameVisitor(context: EvaluationContextImpl) {
}
private fun fail(message: String, shouldFail: Boolean): Value? {
return if (shouldFail) throw EvaluateExceptionUtil.createEvaluateException(message) else null
if (!shouldFail) {
return null
}
val location = frame?.location()
val locationText = location?.run { "Location: ${sourceName()}:${lineNumber()}" } ?: "No location available"
val sourceName = location?.sourceName()
val declaringTypeName = location?.declaringType()?.name()?.replace('.', '/')?.let { JvmClassName.byInternalName(it) }
val sourceFile = if (sourceName != null && declaringTypeName != null) {
DebuggerUtils.findSourceFileForClassIncludeLibrarySources(context.project, scope, declaringTypeName, sourceName)
} else {
null
}
val sourceFileText = runReadAction { sourceFile?.text }
if (sourceName != null && sourceFileText != null) {
val attachments = mergeAttachments(Attachment(sourceName, sourceFileText), Attachment("location.txt", locationText))
LOG.error(message, attachments)
}
throw EvaluateExceptionUtil.createEvaluateException(message)
}
private fun findThis(asmType: Type?): Value? {
@@ -23,7 +23,7 @@ class Outer {
// outer isn't captured in lambda
lambda {
// EXPRESSION: foo() + 2
// RESULT: Cannot find local variable: name = this
// RESULT: java.lang.AssertionError : Cannot find local variable: name = this
//Breakpoint!
val a = 1
}
@@ -16,7 +16,7 @@ fun main(args: Array<String>) {
fun myLocalFun3() {
// EXPRESSION: myLocalFun1() + 1
// RESULT: Cannot find local variable: name = myLocalFun1
// RESULT: java.lang.AssertionError : Cannot find local variable: name = myLocalFun1
//Breakpoint!
myLocalFun1() + 1
}
@@ -56,7 +56,7 @@ fun main(args: Array<String>) {
i = 1
fun myLocalFun7() {
// EXPRESSION: myLocalFun6() + 1
// RESULT: Cannot find local variable: name = myLocalFun6
// RESULT: java.lang.AssertionError : Cannot find local variable: name = myLocalFun6
//Breakpoint!
myLocalFun6() + 1
}
@@ -15,4 +15,4 @@ fun foo(f: () -> Unit) {
// PRINT_FRAME
// EXPRESSION: val1
// RESULT: Cannot find local variable: name = val1
// RESULT: java.lang.AssertionError : Cannot find local variable: name = val1
@@ -20,7 +20,7 @@ fun foo(f: () -> Unit) {
// PRINT_FRAME
// EXPRESSION: val1
// RESULT: Cannot find local variable: name = val1
// RESULT: java.lang.AssertionError : Cannot find local variable: name = val1
frame = invoke:7, FrameLambdaNotUsedKt$main$1 {frameLambdaNotUsed}
this = this = {frameLambdaNotUsed.FrameLambdaNotUsedKt$main$1@uniqueID}Function0<kotlin.Unit>
field = arity: int = 0 (sp = Lambda.!EXT!)