Evaluate expression: support captured vals

This commit is contained in:
Natalia Ukhorskaya
2014-07-01 17:38:15 +04:00
parent 6440884a40
commit 73e0ae1d1c
27 changed files with 383 additions and 46 deletions
@@ -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()
@@ -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<Value>
): 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<out String>?): 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<String>): List<Value> {
val frames = getFrameProxy()?.getStackFrame()
if (frames != null) {
return parameterNames.map { frames.findLocalVariable(it)!! }
}
return Collections.emptyList()
private fun EvaluationContextImpl.getArgumentsForEval4j(parameterNames: List<String>, parameterTypes: Array<Type>): List<Value> {
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
@@ -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<String>) {
@@ -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<kotlin.Unit>
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
@@ -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<String>) {
@@ -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<kotlin.Unit>
field = this$0: frameExtFunExtFun.Outer$foo$LocalClass = {frameExtFunExtFun.Outer$foo$LocalClass@uniqueID}
@@ -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<String>) {
@@ -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}
@@ -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<String>) {
@@ -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
@@ -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<String>) {
@@ -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<kotlin.Unit>
field = this$0: frameInnerLambda.FrameInnerLambdaPackage$main$1 = {frameInnerLambda.FrameInnerLambdaPackage$main$1@uniqueID}kotlin.Function0<kotlin.Unit>
@@ -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<String>) {
@@ -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<kotlin.Unit>
field = $val1: int = 1
@@ -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<String>) {
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<kotlin.Unit>
local = a: int = 0
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
Process finished with exit code 0
@@ -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<String>) {
@@ -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<kotlin.Unit>
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
@@ -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<String>) {
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
@@ -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<String>) {
@@ -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<kotlin.Unit>
field = this$0: frameThis0.A = {frameThis0.A@uniqueID}
@@ -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<String>) {
@@ -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<kotlin.Unit>
field = this$0: frameThis0Ext.A = {frameThis0Ext.A@uniqueID}
@@ -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<String>) {
@@ -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<kotlin.Unit>
field = this$0: frameThis0This0.A$test$1 = {frameThis0This0.A$test$1@uniqueID}kotlin.Function0<kotlin.Unit>
@@ -21,4 +21,7 @@ fun foo(f: () -> Unit) {
f()
}
// PRINT_FRAME
// PRINT_FRAME
// EXPRESSION: prop
// RESULT: 1: I
@@ -43,4 +43,19 @@ fun lambda(f: () -> Unit) {
f()
}
// PRINT_FRAME
// 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
@@ -13,4 +13,7 @@ fun A.foo() {
prop
}
// PRINT_FRAME
// PRINT_FRAME
// EXPRESSION: prop
// RESULT: 1: I
@@ -17,4 +17,10 @@ class A {
}
}
// PRINT_FRAME
// PRINT_FRAME
// EXPRESSION: prop1
// RESULT: 1: I
// EXPRESSION: prop2
// RESULT: 1: I
@@ -15,4 +15,13 @@ fun foo(f: () -> Unit) {
f()
}
// PRINT_FRAME
// PRINT_FRAME
// EXPRESSION: val1
// RESULT: 1: I
// EXPRESSION: val2
// RESULT: 1: I
// EXPRESSION: val1 + val2
// RESULT: 2: I
@@ -12,4 +12,7 @@ fun foo(f: () -> Unit) {
f()
}
// PRINT_FRAME
// PRINT_FRAME
// EXPRESSION: val1
// RESULT: 1: I
@@ -0,0 +1,18 @@
package frameLambdaNotUsed
fun main(args: Array<String>) {
val val1 = 1
foo {
//Breakpoint!
val a = 1
}
}
fun foo(f: () -> Unit) {
f()
}
// PRINT_FRAME
// EXPRESSION: val1
// RESULT: Cannot find local variable: name = val1
@@ -15,4 +15,7 @@ fun foo(f: () -> Unit) {
f()
}
// PRINT_FRAME
// PRINT_FRAME
// EXPRESSION: O.obProp
// RESULT: 1: I
@@ -4,8 +4,21 @@ val topVal1 = 1
fun main(args: Array<String>) {
val val1 = 1
val val2 = "str"
//Breakpoint!
val1 + topVal1
}
// PRINT_FRAME
// 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
@@ -21,4 +21,16 @@ fun foo(f: () -> Unit) {
f()
}
// PRINT_FRAME
// PRINT_FRAME
// EXPRESSION: val1
// RESULT: 1: I
// EXPRESSION: val2
// RESULT: 1: I
// EXPRESSION: prop1
// RESULT: 1: I
// EXPRESSION: prop1 + val1 + val2
// RESULT: 3: I
@@ -28,4 +28,19 @@ fun foo(f: () -> Unit) {
f()
}
// PRINT_FRAME
// 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
@@ -23,4 +23,16 @@ fun foo(f: () -> Unit) {
f()
}
// PRINT_FRAME
// PRINT_FRAME
// EXPRESSION: val1
// RESULT: 1: I
// EXPRESSION: val2
// RESULT: 1: I
// EXPRESSION: prop1
// RESULT: 1: I
// EXPRESSION: prop1 + val1 + val2
// RESULT: 3: I
@@ -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");