diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionCache.kt b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionCache.kt index 5af28367661..e4506dc6e72 100644 --- a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionCache.kt +++ b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionCache.kt @@ -84,7 +84,7 @@ class KotlinEvaluateExpressionCache(val project: Project) { private fun canBeEvaluatedInThisContext(compiledData: CompiledDataDescriptor, context: EvaluationContextImpl): Boolean { return compiledData.parameters.all { (p): Boolean -> val (name, jetType) = p - val value = context.getFrameProxy()?.getStackFrame()?.findLocalVariable(name, failIfNotFound = false) + val value = context.findLocalVariable(name, asmType = null, checkType = false, failIfNotFound = false) if (value == null) return@all false val thisDescriptor = value.asmType.getClassDescriptor() diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt index b13a3920367..11d0c397db5 100644 --- a/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt +++ b/idea/src/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluationBuilder.kt @@ -61,6 +61,11 @@ import org.jetbrains.jet.plugin.debugger.evaluate.KotlinEvaluateExpressionCache. import org.jetbrains.jet.lang.resolve.BindingContext import com.sun.jdi.StackFrame import com.sun.jdi.VirtualMachine +import org.jetbrains.jet.codegen.AsmUtil +import com.sun.jdi.InvalidStackFrameException + +private val RECEIVER_NAME = "\$receiver" +private val THIS_NAME = "this" object KotlinEvaluationBuilder: EvaluatorBuilder { override fun build(codeFragment: PsiElement, position: SourcePosition?): ExpressionEvaluator { @@ -94,14 +99,13 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, isCompiledDataFromCache = false extractAndCompile(fragment, position) } - val args = context.getArgumentsByNames(compiledData.parameters.getParameterNames()) - val result = runEval4j(context, compiledData, args) + val result = runEval4j(context, compiledData) val virtualMachine = context.getDebugProcess().getVirtualMachineProxy().getVirtualMachine() // If bytecode was taken from cache and exception was thrown - recompile bytecode and run eval4j again if (isCompiledDataFromCache && result is ExceptionThrown && result.kind == ExceptionThrown.ExceptionKind.BROKEN_CODE) { - return runEval4j(context, extractAndCompile(codeFragment, sourcePosition), args).toJdiValue(virtualMachine) + return runEval4j(context, extractAndCompile(codeFragment, sourcePosition)).toJdiValue(virtualMachine) } return result.toJdiValue(virtualMachine) @@ -140,17 +144,14 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, return CompiledDataDescriptor(outputFiles.first().asByteArray(), sourcePosition, funName, extractedFunction.getParametersForDebugger()) } - private fun runEval4j( - context: EvaluationContextImpl, - compiledData: CompiledDataDescriptor, - args: List - ): InterpreterResult { + private fun runEval4j(context: EvaluationContextImpl, compiledData: CompiledDataDescriptor): InterpreterResult { val virtualMachine = context.getDebugProcess().getVirtualMachineProxy().getVirtualMachine() var resultValue: InterpreterResult? = null ClassReader(compiledData.bytecodes).accept(object : ClassVisitor(ASM5) { override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor? { if (name == compiledData.funName) { + val args = context.getArgumentsForEval4j(compiledData.parameters.getParameterNames(), Type.getArgumentTypes(desc)) return object : MethodNode(Opcodes.ASM5, access, name, desc, signature, exceptions) { override fun visitEnd() { resultValue = interpreterLoop( @@ -182,10 +183,6 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, return jdiValue.asJdiValue(vm, jdiValue.asmType) } - private fun SuspendContext.getInvokePolicy(): Int { - return if (getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD) ObjectReference.INVOKE_SINGLE_THREADED else 0 - } - private fun JetNamedFunction.getParametersForDebugger(): ParametersDescriptor { return ApplicationManager.getApplication()?.runReadAction(Computable { val parameters = ParametersDescriptor() @@ -194,7 +191,7 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, if (descriptor != null) { val receiver = descriptor.getReceiverParameter() if (receiver != null) { - parameters.add("this", receiver.getType()) + parameters.add(THIS_NAME, receiver.getType()) } descriptor.getValueParameters().forEach { @@ -206,12 +203,8 @@ class KotlinEvaluator(val codeFragment: JetCodeFragment, })!! } - private fun EvaluationContextImpl.getArgumentsByNames(parameterNames: List): List { - val frames = getFrameProxy()?.getStackFrame() - if (frames != null) { - return parameterNames.map { frames.findLocalVariable(it)!! } - } - return Collections.emptyList() + private fun EvaluationContextImpl.getArgumentsForEval4j(parameterNames: List, parameterTypes: Array): List { + return parameterNames.zip(parameterTypes).map { this.findLocalVariable(it.first, it.second, checkType = false, failIfNotFound = true)!! } } private fun createClassFileFactory(codeFragment: JetCodeFragment, extractedFunction: JetNamedFunction): ClassFileFactory { @@ -301,22 +294,87 @@ fun checkForSyntacticErrors(file: JetFile) { } } -fun StackFrame.findLocalVariable(name: String, failIfNotFound: Boolean = true): Value? { - return try { +private fun SuspendContext.getInvokePolicy(): Int { + return if (getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD) ObjectReference.INVOKE_SINGLE_THREADED else 0 +} + +fun EvaluationContextImpl.findLocalVariable(name: String, asmType: Type?, checkType: Boolean, failIfNotFound: Boolean): Value? { + val frame = getFrameProxy()?.getStackFrame() + if (frame == null) return null + try { when (name) { - "this" -> thisObject().asValue() - else -> getValue(visibleVariableByName(name)).asValue() + THIS_NAME -> { + val thisObject = frame.thisObject() + if (thisObject != null) { + val eval4jValue = thisObject.asValue() + if (isValueOfCorrectType(eval4jValue, asmType, true)) return eval4jValue + } + + val receiver = findLocalVariable(RECEIVER_NAME, asmType, checkType = true, failIfNotFound = false) + if (receiver != null) return receiver + + val this0 = findLocalVariable(AsmUtil.CAPTURED_THIS_FIELD, asmType, checkType = true, failIfNotFound = false) + if (this0 != null) return this0 + } + else -> { + val localVariable = frame.visibleVariableByName(name) + if (localVariable != null) { + val eval4jValue = frame.getValue(localVariable).asValue() + if (isValueOfCorrectType(eval4jValue, asmType, checkType)) return eval4jValue + } + + val eval4j = JDIEval(frame.virtualMachine()!!, + getClassLoader()!!, + getSuspendContext().getThread()?.getThreadReference()!!, + getSuspendContext().getInvokePolicy()) + + fun JDIEval.getField(owner: Value, name: String, asmType: Type?): Value? { + val fieldDescription = FieldDescription(owner.asmType.getInternalName(), name, asmType?.getDescriptor() ?: "", isStatic = false) + try { + val fieldValue = getField(owner, fieldDescription) + if (isValueOfCorrectType(fieldValue, asmType, checkType)) return fieldValue + return null + } + catch (e: Exception) { + return null + } + } + + fun findCapturedVal(name: String): Value? { + var result: Value? = null + var thisObj: Value? = frame.thisObject().asValue() + + while (result == null && thisObj != null) { + result = eval4j.getField(thisObj!!, name, asmType) + if (result == null) { + thisObj = eval4j.getField(thisObj!!, AsmUtil.CAPTURED_THIS_FIELD, null) + } + } + return result + } + + val capturedValName = getCapturedFieldName(name) + val capturedVal = findCapturedVal(capturedValName) + if (capturedVal != null) return capturedVal + } } + + return if (!failIfNotFound) + null + else + throw EvaluateExceptionUtil.createEvaluateException("Cannot find local variable: name = $name${if (checkType) ", type = " + asmType.toString() else ""}") } - catch(e: Exception) { - if (failIfNotFound) { - throw EvaluateExceptionUtil.createEvaluateException( - "Cannot find local variable: name = ${name}. Note that captured variables are unsupported yet.") - } - else { - return null - } + catch(e: InvalidStackFrameException) { + throw EvaluateExceptionUtil.createEvaluateException("Local variable $name is unavailable in current frame") } } +private fun getCapturedFieldName(name: String) = when (name) { + RECEIVER_NAME -> AsmUtil.CAPTURED_RECEIVER_FIELD + THIS_NAME -> AsmUtil.CAPTURED_THIS_FIELD + AsmUtil.CAPTURED_RECEIVER_FIELD -> name + AsmUtil.CAPTURED_THIS_FIELD -> name + else -> "$$name" +} +private fun isValueOfCorrectType(value: Value, asmType: Type?, shouldCheckType: Boolean) = !shouldCheckType || asmType == null || value.asmType == asmType \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/outs/frameClassObject.out b/idea/testData/debugger/tinyApp/outs/frameClassObject.out index c558c886f4d..11dc39ce6e2 100644 --- a/idea/testData/debugger/tinyApp/outs/frameClassObject.out +++ b/idea/testData/debugger/tinyApp/outs/frameClassObject.out @@ -2,6 +2,7 @@ LineBreakpoint created at frameClassObject.kt:15 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! frameClassObject.FrameClassObjectPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' frameClassObject.kt:14 +Compile bytecode for prop package frameClassObject fun main(args: Array) { @@ -26,6 +27,9 @@ fun foo(f: () -> Unit) { } // PRINT_FRAME + +// EXPRESSION: prop +// RESULT: 1: I frame = invoke():15, A$test$1 {frameClassObject} this = this = {frameClassObject.A$test$1@uniqueID}kotlin.Function0 Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' diff --git a/idea/testData/debugger/tinyApp/outs/frameExtFunExtFun.out b/idea/testData/debugger/tinyApp/outs/frameExtFunExtFun.out index a9410ca32a9..e7769a2da7c 100644 --- a/idea/testData/debugger/tinyApp/outs/frameExtFunExtFun.out +++ b/idea/testData/debugger/tinyApp/outs/frameExtFunExtFun.out @@ -2,6 +2,11 @@ LineBreakpoint created at frameExtFunExtFun.kt:22 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! frameExtFunExtFun.FrameExtFunExtFunPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' frameExtFunExtFun.kt:21 +Compile bytecode for valFoo +Compile bytecode for valTest +Compile bytecode for aProp +Compile bytecode for outerProp +Compile bytecode for bProp package frameExtFunExtFun fun main(args: Array) { @@ -48,6 +53,21 @@ fun lambda(f: () -> Unit) { } // PRINT_FRAME + +// EXPRESSION: valFoo +// RESULT: 1: I + +// EXPRESSION: valTest +// RESULT: 1: I + +// EXPRESSION: aProp +// RESULT: 1: I + +// EXPRESSION: outerProp +// RESULT: 1: I + +// EXPRESSION: bProp +// RESULT: 1: I frame = invoke():22, Outer$foo$LocalClass$test$1 {frameExtFunExtFun} this = this = {frameExtFunExtFun.Outer$foo$LocalClass$test$1@uniqueID}kotlin.Function0 field = this$0: frameExtFunExtFun.Outer$foo$LocalClass = {frameExtFunExtFun.Outer$foo$LocalClass@uniqueID} diff --git a/idea/testData/debugger/tinyApp/outs/frameExtensionFun.out b/idea/testData/debugger/tinyApp/outs/frameExtensionFun.out index 6f4734888ab..e7c86083da6 100644 --- a/idea/testData/debugger/tinyApp/outs/frameExtensionFun.out +++ b/idea/testData/debugger/tinyApp/outs/frameExtensionFun.out @@ -2,6 +2,7 @@ LineBreakpoint created at frameExtensionFun.kt:13 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! frameExtensionFun.FrameExtensionFunPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' frameExtensionFun.kt:12 +Compile bytecode for prop package frameExtensionFun fun main(args: Array) { @@ -18,6 +19,9 @@ fun A.foo() { } // PRINT_FRAME + +// EXPRESSION: prop +// RESULT: 1: I frame = foo():13, FrameExtensionFunPackage-@packagePartHASH {frameExtensionFun} static = static = frameExtensionFun.FrameExtensionFunPackage-@packagePartHASH local = $receiver: frameExtensionFun.A = {frameExtensionFun.A@uniqueID} diff --git a/idea/testData/debugger/tinyApp/outs/frameInnerClass.out b/idea/testData/debugger/tinyApp/outs/frameInnerClass.out index 972c094adfd..d22a92b8bc7 100644 --- a/idea/testData/debugger/tinyApp/outs/frameInnerClass.out +++ b/idea/testData/debugger/tinyApp/outs/frameInnerClass.out @@ -2,6 +2,8 @@ LineBreakpoint created at frameInnerClass.kt:15 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! frameInnerClass.FrameInnerClassPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' frameInnerClass.kt:14 +Compile bytecode for prop1 +Compile bytecode for prop2 package frameInnerClass fun main(args: Array) { @@ -22,6 +24,12 @@ class A { } // PRINT_FRAME + +// EXPRESSION: prop1 +// RESULT: 1: I + +// EXPRESSION: prop2 +// RESULT: 1: I frame = test():15, A$Inner {frameInnerClass} this = this = {frameInnerClass.A$Inner@uniqueID} field = prop2: int = 1 diff --git a/idea/testData/debugger/tinyApp/outs/frameInnerLambda.out b/idea/testData/debugger/tinyApp/outs/frameInnerLambda.out index 9bc5d2e0a1e..174a959a1d7 100644 --- a/idea/testData/debugger/tinyApp/outs/frameInnerLambda.out +++ b/idea/testData/debugger/tinyApp/outs/frameInnerLambda.out @@ -2,6 +2,9 @@ LineBreakpoint created at frameInnerLambda.kt:9 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! frameInnerLambda.FrameInnerLambdaPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' frameInnerLambda.kt:8 +Compile bytecode for val1 +Compile bytecode for val2 +Compile bytecode for val1 + val2 package frameInnerLambda fun main(args: Array) { @@ -20,6 +23,15 @@ fun foo(f: () -> Unit) { } // PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: 1: I + +// EXPRESSION: val2 +// RESULT: 1: I + +// EXPRESSION: val1 + val2 +// RESULT: 2: I frame = invoke():9, FrameInnerLambdaPackage$main$1$1 {frameInnerLambda} this = this = {frameInnerLambda.FrameInnerLambdaPackage$main$1$1@uniqueID}kotlin.Function0 field = this$0: frameInnerLambda.FrameInnerLambdaPackage$main$1 = {frameInnerLambda.FrameInnerLambdaPackage$main$1@uniqueID}kotlin.Function0 diff --git a/idea/testData/debugger/tinyApp/outs/frameLambda.out b/idea/testData/debugger/tinyApp/outs/frameLambda.out index 0f643ec2c50..166449bda2d 100644 --- a/idea/testData/debugger/tinyApp/outs/frameLambda.out +++ b/idea/testData/debugger/tinyApp/outs/frameLambda.out @@ -2,6 +2,7 @@ LineBreakpoint created at frameLambda.kt:7 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! frameLambda.FrameLambdaPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' frameLambda.kt:6 +Compile bytecode for val1 package frameLambda fun main(args: Array) { @@ -17,6 +18,9 @@ fun foo(f: () -> Unit) { } // PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: 1: I frame = invoke():7, FrameLambdaPackage$main$1 {frameLambda} this = this = {frameLambda.FrameLambdaPackage$main$1@uniqueID}kotlin.Function0 field = $val1: int = 1 diff --git a/idea/testData/debugger/tinyApp/outs/frameLambdaNotUsed.out b/idea/testData/debugger/tinyApp/outs/frameLambdaNotUsed.out new file mode 100644 index 00000000000..ea3d5ab1794 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/frameLambdaNotUsed.out @@ -0,0 +1,29 @@ +LineBreakpoint created at frameLambdaNotUsed.kt:7 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! frameLambdaNotUsed.FrameLambdaNotUsedPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +frameLambdaNotUsed.kt:6 +Compile bytecode for val1 +package frameLambdaNotUsed + +fun main(args: Array) { + val val1 = 1 + foo { + //Breakpoint! + val a = 1 + } +} + +fun foo(f: () -> Unit) { + f() +} + +// PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: Cannot find local variable: name = val1 + frame = invoke():7, FrameLambdaNotUsedPackage$main$1 {frameLambdaNotUsed} + this = this = {frameLambdaNotUsed.FrameLambdaNotUsedPackage$main$1@uniqueID}kotlin.Function0 + local = a: int = 0 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/frameObject.out b/idea/testData/debugger/tinyApp/outs/frameObject.out index 6a10bc9adfa..718510979ef 100644 --- a/idea/testData/debugger/tinyApp/outs/frameObject.out +++ b/idea/testData/debugger/tinyApp/outs/frameObject.out @@ -2,6 +2,7 @@ LineBreakpoint created at frameObject.kt:6 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! frameObject.FrameObjectPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' frameObject.kt:5 +Compile bytecode for O.obProp package frameObject fun main(args: Array) { @@ -20,6 +21,9 @@ fun foo(f: () -> Unit) { } // PRINT_FRAME + +// EXPRESSION: O.obProp +// RESULT: 1: I frame = invoke():6, FrameObjectPackage$main$1 {frameObject} this = this = {frameObject.FrameObjectPackage$main$1@uniqueID}kotlin.Function0 Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' diff --git a/idea/testData/debugger/tinyApp/outs/frameSimple.out b/idea/testData/debugger/tinyApp/outs/frameSimple.out index 51e063b7a90..6fcd027b57b 100644 --- a/idea/testData/debugger/tinyApp/outs/frameSimple.out +++ b/idea/testData/debugger/tinyApp/outs/frameSimple.out @@ -1,23 +1,48 @@ -LineBreakpoint created at frameSimple.kt:8 +LineBreakpoint created at frameSimple.kt:9 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! frameSimple.FrameSimplePackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' -frameSimple.kt:7 +frameSimple.kt:8 +Compile bytecode for val1 +Compile bytecode for val2 +Compile bytecode for topVal1 +Compile bytecode for val1 + topVal1 package frameSimple val topVal1 = 1 fun main(args: Array) { val val1 = 1 + val val2 = "str" //Breakpoint! val1 + topVal1 } // PRINT_FRAME - frame = main():8, FrameSimplePackage-@packagePartHASH {frameSimple} + +// EXPRESSION: val1 +// RESULT: 1: I + +// EXPRESSION: val2 +// RESULT: "str": Ljava/lang/String; + +// EXPRESSION: topVal1 +// RESULT: 1: I + +// EXPRESSION: val1 + topVal1 +// RESULT: 2: I + frame = main():9, FrameSimplePackage-@packagePartHASH {frameSimple} static = static = frameSimple.FrameSimplePackage-@packagePartHASH field = topVal1: int = 1 local = args: java.lang.String[] = {java.lang.String[0]@uniqueID} local = val1: int = 1 + local = val2: java.lang.String = {@uniqueID}str + field = value: char[] = {char[3]@uniqueID} + unknown = [0] = 's' 115 + unknown = [1] = 't' 116 + unknown = [2] = 'r' 114 + field = offset: int = 0 + field = count: int = 3 + field = hash: int = 0 Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/frameThis0.out b/idea/testData/debugger/tinyApp/outs/frameThis0.out index a49d6ec3167..e7e427769e2 100644 --- a/idea/testData/debugger/tinyApp/outs/frameThis0.out +++ b/idea/testData/debugger/tinyApp/outs/frameThis0.out @@ -2,6 +2,10 @@ LineBreakpoint created at frameThis0.kt:15 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! frameThis0.FrameThis0Package Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' frameThis0.kt:14 +Compile bytecode for val1 +Compile bytecode for val2 +Compile bytecode for prop1 +Compile bytecode for prop1 + val1 + val2 package frameThis0 fun main(args: Array) { @@ -26,6 +30,18 @@ fun foo(f: () -> Unit) { } // PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: 1: I + +// EXPRESSION: val2 +// RESULT: 1: I + +// EXPRESSION: prop1 +// RESULT: 1: I + +// EXPRESSION: prop1 + val1 + val2 +// RESULT: 3: I frame = invoke():15, A$test$1 {frameThis0} this = this = {frameThis0.A$test$1@uniqueID}kotlin.Function0 field = this$0: frameThis0.A = {frameThis0.A@uniqueID} diff --git a/idea/testData/debugger/tinyApp/outs/frameThis0Ext.out b/idea/testData/debugger/tinyApp/outs/frameThis0Ext.out index 026e982d6d6..0742d4cbd78 100644 --- a/idea/testData/debugger/tinyApp/outs/frameThis0Ext.out +++ b/idea/testData/debugger/tinyApp/outs/frameThis0Ext.out @@ -2,6 +2,11 @@ LineBreakpoint created at frameThis0Ext.kt:14 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! frameThis0Ext.FrameThis0ExtPackage Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' frameThis0Ext.kt:13 +Compile bytecode for val1 +Compile bytecode for prop1 +Compile bytecode for prop2 +Compile bytecode for prop1 + val1 +Compile bytecode for prop2 + val1 package frameThis0Ext fun main(args: Array) { @@ -33,6 +38,21 @@ fun foo(f: () -> Unit) { } // PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: 1: I + +// EXPRESSION: prop1 +// RESULT: 1: I + +// EXPRESSION: prop2 +// RESULT: 1: I + +// EXPRESSION: prop1 + val1 +// RESULT: 2: I + +// EXPRESSION: prop2 + val1 +// RESULT: 2: I frame = invoke():14, A$testExt$1 {frameThis0Ext} this = this = {frameThis0Ext.A$testExt$1@uniqueID}kotlin.Function0 field = this$0: frameThis0Ext.A = {frameThis0Ext.A@uniqueID} diff --git a/idea/testData/debugger/tinyApp/outs/frameThis0This0.out b/idea/testData/debugger/tinyApp/outs/frameThis0This0.out index 553119fc8cf..6418ba9f128 100644 --- a/idea/testData/debugger/tinyApp/outs/frameThis0This0.out +++ b/idea/testData/debugger/tinyApp/outs/frameThis0This0.out @@ -2,6 +2,10 @@ LineBreakpoint created at frameThis0This0.kt:16 !JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! frameThis0This0.FrameThis0This0Package Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' frameThis0This0.kt:15 +Compile bytecode for val1 +Compile bytecode for val2 +Compile bytecode for prop1 +Compile bytecode for prop1 + val1 + val2 package frameThis0This0 fun main(args: Array) { @@ -28,6 +32,18 @@ fun foo(f: () -> Unit) { } // PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: 1: I + +// EXPRESSION: val2 +// RESULT: 1: I + +// EXPRESSION: prop1 +// RESULT: 1: I + +// EXPRESSION: prop1 + val1 + val2 +// RESULT: 3: I frame = invoke():16, A$test$1$1 {frameThis0This0} this = this = {frameThis0This0.A$test$1$1@uniqueID}kotlin.Function0 field = this$0: frameThis0This0.A$test$1 = {frameThis0This0.A$test$1@uniqueID}kotlin.Function0 diff --git a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameClassObject.kt b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameClassObject.kt index 25eb17e50ed..2a351b15070 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameClassObject.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameClassObject.kt @@ -21,4 +21,7 @@ fun foo(f: () -> Unit) { f() } -// PRINT_FRAME \ No newline at end of file +// PRINT_FRAME + +// EXPRESSION: prop +// RESULT: 1: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameExtFunExtFun.kt b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameExtFunExtFun.kt index fd7a810f5ef..3d0f5691cdd 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameExtFunExtFun.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameExtFunExtFun.kt @@ -43,4 +43,19 @@ fun lambda(f: () -> Unit) { f() } -// PRINT_FRAME \ No newline at end of file +// PRINT_FRAME + +// EXPRESSION: valFoo +// RESULT: 1: I + +// EXPRESSION: valTest +// RESULT: 1: I + +// EXPRESSION: aProp +// RESULT: 1: I + +// EXPRESSION: outerProp +// RESULT: 1: I + +// EXPRESSION: bProp +// RESULT: 1: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameExtensionFun.kt b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameExtensionFun.kt index cb7cd55d26d..a4142f70096 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameExtensionFun.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameExtensionFun.kt @@ -13,4 +13,7 @@ fun A.foo() { prop } -// PRINT_FRAME \ No newline at end of file +// PRINT_FRAME + +// EXPRESSION: prop +// RESULT: 1: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameInnerClass.kt b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameInnerClass.kt index 7e3dd2a9673..6aa4e1b3de6 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameInnerClass.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameInnerClass.kt @@ -17,4 +17,10 @@ class A { } } -// PRINT_FRAME \ No newline at end of file +// PRINT_FRAME + +// EXPRESSION: prop1 +// RESULT: 1: I + +// EXPRESSION: prop2 +// RESULT: 1: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameInnerLambda.kt b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameInnerLambda.kt index 388e219a4d5..86c9b13524e 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameInnerLambda.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameInnerLambda.kt @@ -15,4 +15,13 @@ fun foo(f: () -> Unit) { f() } -// PRINT_FRAME \ No newline at end of file +// PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: 1: I + +// EXPRESSION: val2 +// RESULT: 1: I + +// EXPRESSION: val1 + val2 +// RESULT: 2: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameLambda.kt b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameLambda.kt index 9100db6c178..313e3276305 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameLambda.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameLambda.kt @@ -12,4 +12,7 @@ fun foo(f: () -> Unit) { f() } -// PRINT_FRAME \ No newline at end of file +// PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: 1: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameLambdaNotUsed.kt b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameLambdaNotUsed.kt new file mode 100644 index 00000000000..5e328181b99 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameLambdaNotUsed.kt @@ -0,0 +1,18 @@ +package frameLambdaNotUsed + +fun main(args: Array) { + val val1 = 1 + foo { + //Breakpoint! + val a = 1 + } +} + +fun foo(f: () -> Unit) { + f() +} + +// PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: Cannot find local variable: name = val1 \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameObject.kt b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameObject.kt index 9fc93b49755..55c232e6aab 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameObject.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameObject.kt @@ -15,4 +15,7 @@ fun foo(f: () -> Unit) { f() } -// PRINT_FRAME \ No newline at end of file +// PRINT_FRAME + +// EXPRESSION: O.obProp +// RESULT: 1: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameSimple.kt b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameSimple.kt index a694f51f9a4..3607971a065 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameSimple.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameSimple.kt @@ -4,8 +4,21 @@ val topVal1 = 1 fun main(args: Array) { val val1 = 1 + val val2 = "str" //Breakpoint! val1 + topVal1 } -// PRINT_FRAME \ No newline at end of file +// PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: 1: I + +// EXPRESSION: val2 +// RESULT: "str": Ljava/lang/String; + +// EXPRESSION: topVal1 +// RESULT: 1: I + +// EXPRESSION: val1 + topVal1 +// RESULT: 2: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameThis0.kt b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameThis0.kt index cb1ce03517f..73367af12ad 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameThis0.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameThis0.kt @@ -21,4 +21,16 @@ fun foo(f: () -> Unit) { f() } -// PRINT_FRAME \ No newline at end of file +// PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: 1: I + +// EXPRESSION: val2 +// RESULT: 1: I + +// EXPRESSION: prop1 +// RESULT: 1: I + +// EXPRESSION: prop1 + val1 + val2 +// RESULT: 3: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameThis0Ext.kt b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameThis0Ext.kt index d26711e122a..15735ca555a 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameThis0Ext.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameThis0Ext.kt @@ -28,4 +28,19 @@ fun foo(f: () -> Unit) { f() } -// PRINT_FRAME \ No newline at end of file +// PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: 1: I + +// EXPRESSION: prop1 +// RESULT: 1: I + +// EXPRESSION: prop2 +// RESULT: 1: I + +// EXPRESSION: prop1 + val1 +// RESULT: 2: I + +// EXPRESSION: prop2 + val1 +// RESULT: 2: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameThis0This0.kt b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameThis0This0.kt index b585303e0cd..87f7357deb0 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/frame/frameThis0This0.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/frame/frameThis0This0.kt @@ -23,4 +23,16 @@ fun foo(f: () -> Unit) { f() } -// PRINT_FRAME \ No newline at end of file +// PRINT_FRAME + +// EXPRESSION: val1 +// RESULT: 1: I + +// EXPRESSION: val2 +// RESULT: 1: I + +// EXPRESSION: prop1 +// RESULT: 1: I + +// EXPRESSION: prop1 + val1 + val2 +// RESULT: 3: I \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java index abe426ebf41..16d9c9877f0 100644 --- a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -199,6 +199,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/frame/frameLambda.kt"); } + @TestMetadata("frameLambdaNotUsed.kt") + public void testFrameLambdaNotUsed() throws Exception { + doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/frame/frameLambdaNotUsed.kt"); + } + @TestMetadata("frameObject.kt") public void testFrameObject() throws Exception { doSingleBreakpointTest("idea/testData/debugger/tinyApp/src/evaluate/frame/frameObject.kt");