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.EvaluateExceptionUtil
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl 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.ClassType
import com.sun.jdi.InvalidStackFrameException import com.sun.jdi.InvalidStackFrameException
import com.sun.jdi.ObjectReference 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_FUN_VAR_SUFFIX
import org.jetbrains.kotlin.codegen.inline.INLINE_TRANSFORMATION_SUFFIX import org.jetbrains.kotlin.codegen.inline.INLINE_TRANSFORMATION_SUFFIX
import org.jetbrains.kotlin.codegen.inline.NUMBERED_FUNCTION_PREFIX 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.isInsideInlineFunctionBody
import org.jetbrains.kotlin.idea.debugger.numberOfInlinedFunctions import org.jetbrains.kotlin.idea.debugger.numberOfInlinedFunctions
import org.jetbrains.kotlin.idea.util.application.runReadAction 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.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
class FrameVisitor(context: EvaluationContextImpl) { class FrameVisitor(val context: EvaluationContextImpl) {
private val scope = context.debugProcess.searchScope private val scope = context.debugProcess.searchScope
private val frame = context.frameProxy private val frame = context.frameProxy
@@ -95,7 +98,31 @@ class FrameVisitor(context: EvaluationContextImpl) {
} }
private fun fail(message: String, shouldFail: Boolean): Value? { 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? { private fun findThis(asmType: Type?): Value? {
@@ -23,7 +23,7 @@ class Outer {
// outer isn't captured in lambda // outer isn't captured in lambda
lambda { lambda {
// EXPRESSION: foo() + 2 // EXPRESSION: foo() + 2
// RESULT: Cannot find local variable: name = this // RESULT: java.lang.AssertionError : Cannot find local variable: name = this
//Breakpoint! //Breakpoint!
val a = 1 val a = 1
} }
@@ -16,7 +16,7 @@ fun main(args: Array<String>) {
fun myLocalFun3() { fun myLocalFun3() {
// EXPRESSION: myLocalFun1() + 1 // EXPRESSION: myLocalFun1() + 1
// RESULT: Cannot find local variable: name = myLocalFun1 // RESULT: java.lang.AssertionError : Cannot find local variable: name = myLocalFun1
//Breakpoint! //Breakpoint!
myLocalFun1() + 1 myLocalFun1() + 1
} }
@@ -56,7 +56,7 @@ fun main(args: Array<String>) {
i = 1 i = 1
fun myLocalFun7() { fun myLocalFun7() {
// EXPRESSION: myLocalFun6() + 1 // EXPRESSION: myLocalFun6() + 1
// RESULT: Cannot find local variable: name = myLocalFun6 // RESULT: java.lang.AssertionError : Cannot find local variable: name = myLocalFun6
//Breakpoint! //Breakpoint!
myLocalFun6() + 1 myLocalFun6() + 1
} }
@@ -15,4 +15,4 @@ fun foo(f: () -> Unit) {
// PRINT_FRAME // PRINT_FRAME
// EXPRESSION: val1 // 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 // PRINT_FRAME
// EXPRESSION: val1 // 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} frame = invoke:7, FrameLambdaNotUsedKt$main$1 {frameLambdaNotUsed}
this = this = {frameLambdaNotUsed.FrameLambdaNotUsedKt$main$1@uniqueID}Function0<kotlin.Unit> this = this = {frameLambdaNotUsed.FrameLambdaNotUsedKt$main$1@uniqueID}Function0<kotlin.Unit>
field = arity: int = 0 (sp = Lambda.!EXT!) field = arity: int = 0 (sp = Lambda.!EXT!)