Evaluate: Fix for evaluating local variables captured by an inline function (KT-17514)

This commit is contained in:
Yan Zhulanow
2017-10-02 15:28:19 +03:00
parent fed5bddde2
commit 43a1162b25
5 changed files with 56 additions and 12 deletions
@@ -69,7 +69,7 @@ internal const val THIS = "this"
internal const val THIS_0 = "this$0"
internal const val FIRST_FUN_LABEL = "$$$$\$ROOT$$$$$"
internal const val SPECIAL_TRANSFORMATION_NAME = "\$special"
internal const val INLINE_TRANSFORMATION_SUFFIX = "\$inlined"
const val INLINE_TRANSFORMATION_SUFFIX = "\$inlined"
internal const val INLINE_CALL_TRANSFORMATION_SUFFIX = "$" + INLINE_TRANSFORMATION_SUFFIX
internal const val INLINE_FUN_THIS_0_SUFFIX = "\$inline_fun"
internal const val DEFAULT_LAMBDA_FAKE_CALL = "$$\$DEFAULT_LAMBDA_FAKE_CALL$$$"
@@ -18,6 +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.sun.jdi.ClassType
import com.sun.jdi.InvalidStackFrameException
import com.sun.jdi.ObjectReference
@@ -27,6 +28,7 @@ import org.jetbrains.eval4j.jdi.asValue
import org.jetbrains.eval4j.obj
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.isInsideInlineFunctionBody
import org.jetbrains.kotlin.idea.debugger.numberOfInlinedFunctions
@@ -78,11 +80,10 @@ class FrameVisitor(context: EvaluationContextImpl) {
return localVariable
}
val capturedValName = getCapturedFieldName(name)
val capturedVal = findCapturedLocalVariable(capturedValName, asmType, checkType)
if (capturedVal != null) {
return capturedVal
}
getCapturedFieldNames(name).asSequence()
.mapNotNull { findCapturedLocalVariable(it, asmType, checkType) }
.firstOrNull()
?.let { return it }
}
}
@@ -221,12 +222,15 @@ class FrameVisitor(context: EvaluationContextImpl) {
return null
}
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 getCapturedFieldNames(name: String): List<String> = when (name) {
RECEIVER_NAME -> listOf(AsmUtil.CAPTURED_RECEIVER_FIELD)
THIS_NAME -> listOf(AsmUtil.CAPTURED_THIS_FIELD)
AsmUtil.CAPTURED_RECEIVER_FIELD -> listOf(name)
AsmUtil.CAPTURED_THIS_FIELD -> listOf(name)
else -> {
val simpleName = "$$name"
listOf(simpleName, simpleName + INLINE_TRANSFORMATION_SUFFIX)
}
}
private fun com.sun.jdi.Type?.isSubclass(superClassName: String): Boolean {
@@ -0,0 +1,23 @@
package kt17514
fun <T> checkSucceeds(callable: () -> T) = callable()
fun main(args: Array<String>) {
val isPresent = true
val isPresent2 = true
val expectedLibs = listOf("aa", "bb", "cc")
expectedLibs
.forEach {
checkSucceeds {
val isPresent2 = false
//Breakpoint!
val v = isPresent
}
}
}
// EXPRESSION: isPresent
// RESULT: 1: Z
// EXPRESSION: isPresent2
// RESULT: 0: Z
@@ -0,0 +1,11 @@
LineBreakpoint created at kt17514.kt:14
Run Java
Connected to the target VM
kt17514.kt:14
Compile bytecode for isPresent
Compile bytecode for isPresent2
kt17514.kt:14
resuming kt17514.kt:14
Disconnected from the target VM
Process finished with exit code 0
@@ -236,6 +236,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
doSingleBreakpointTest(fileName);
}
@TestMetadata("kt17514.kt")
public void testKt17514() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt17514.kt");
doSingleBreakpointTest(fileName);
}
@TestMetadata("kt5554OnlyIntsShouldBeCoerced.kt")
public void testKt5554OnlyIntsShouldBeCoerced() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/kt5554OnlyIntsShouldBeCoerced.kt");