Evaluate expression: support EE for shared vars
This commit is contained in:
@@ -933,7 +933,8 @@ public abstract class StackValue {
|
||||
}
|
||||
}
|
||||
|
||||
public static Type sharedTypeForType(Type type) {
|
||||
@NotNull
|
||||
public static Type sharedTypeForType(@NotNull Type type) {
|
||||
switch (type.getSort()) {
|
||||
case Type.OBJECT:
|
||||
case Type.ARRAY:
|
||||
|
||||
@@ -70,6 +70,7 @@ import org.jetbrains.jet.plugin.caches.resolve.JavaResolveExtension
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaClassImpl
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils
|
||||
import org.jetbrains.jet.codegen.StackValue
|
||||
|
||||
private val RECEIVER_NAME = "\$receiver"
|
||||
private val THIS_NAME = "this"
|
||||
@@ -339,18 +340,12 @@ fun EvaluationContextImpl.findLocalVariable(name: String, asmType: Type?, checkT
|
||||
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? {
|
||||
fun JDIEval.getField(owner: Value, name: String, asmType: Type?, checkType: Boolean): Value? {
|
||||
val fieldDescription = FieldDescription(owner.asmType.getInternalName(), name, asmType?.getDescriptor() ?: "", isStatic = false)
|
||||
try {
|
||||
val fieldValue = getField(owner, fieldDescription)
|
||||
@@ -362,14 +357,39 @@ fun EvaluationContextImpl.findLocalVariable(name: String, asmType: Type?, checkT
|
||||
}
|
||||
}
|
||||
|
||||
fun Value.isSharedVar(expectedType: Type?): Boolean {
|
||||
return expectedType != null && this.asmType == StackValue.sharedTypeForType(expectedType)
|
||||
}
|
||||
|
||||
fun JDIEval.getValueForSharedVar(value: Value, expectedType: Type?, checkType: Boolean): Value? {
|
||||
val sharedVarValue = this.getField(value, "element", expectedType, checkType)
|
||||
if (sharedVarValue != null && isValueOfCorrectType(sharedVarValue, expectedType, checkType)) {
|
||||
return sharedVarValue
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
val localVariable = frame.visibleVariableByName(name)
|
||||
if (localVariable != null) {
|
||||
val eval4jValue = frame.getValue(localVariable).asValue()
|
||||
if (eval4jValue.isSharedVar(asmType)) {
|
||||
val sharedVarValue = eval4j.getValueForSharedVar(eval4jValue, asmType, checkType)
|
||||
if (sharedVarValue != null) {
|
||||
return sharedVarValue
|
||||
}
|
||||
}
|
||||
|
||||
if (isValueOfCorrectType(eval4jValue, asmType, checkType)) return eval4jValue
|
||||
}
|
||||
|
||||
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)
|
||||
result = eval4j.getField(thisObj!!, name, asmType, checkType)
|
||||
if (result == null) {
|
||||
thisObj = eval4j.getField(thisObj!!, AsmUtil.CAPTURED_THIS_FIELD, null)
|
||||
thisObj = eval4j.getField(thisObj!!, AsmUtil.CAPTURED_THIS_FIELD, null, false)
|
||||
}
|
||||
}
|
||||
return result
|
||||
@@ -377,7 +397,15 @@ fun EvaluationContextImpl.findLocalVariable(name: String, asmType: Type?, checkT
|
||||
|
||||
val capturedValName = getCapturedFieldName(name)
|
||||
val capturedVal = findCapturedVal(capturedValName)
|
||||
if (capturedVal != null) return capturedVal
|
||||
if (capturedVal != null) {
|
||||
if (capturedVal.isSharedVar(asmType)) {
|
||||
val sharedVarValue = eval4j.getValueForSharedVar(capturedVal, asmType, checkType)
|
||||
if (sharedVarValue != null) {
|
||||
return sharedVarValue
|
||||
}
|
||||
}
|
||||
return capturedVal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ LineBreakpoint created at frameSharedVar.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!;!CUSTOM_LIBRARY!;!RT_JAR! frameSharedVar.FrameSharedVarPackage
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
frameSharedVar.kt:6
|
||||
Compile bytecode for var1
|
||||
package frameSharedVar
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
@@ -17,6 +18,9 @@ fun foo(f: () -> Unit) {
|
||||
}
|
||||
|
||||
// PRINT_FRAME
|
||||
|
||||
// EXPRESSION: var1
|
||||
// RESULT: 1: I
|
||||
frame = invoke():7, FrameSharedVarPackage$@packagePartHASH$main$1 {frameSharedVar}
|
||||
this = this = {frameSharedVar.FrameSharedVarPackage$@packagePartHASH$main$1@uniqueID}kotlin.Function0<kotlin.Unit>
|
||||
field = $var1: kotlin.jvm.internal.Ref$IntRef = {kotlin.jvm.internal.Ref$IntRef@uniqueID}1
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
LineBreakpoint created at frameSharedVarLocalVar.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!;!CUSTOM_LIBRARY!;!RT_JAR! frameSharedVarLocalVar.FrameSharedVarLocalVarPackage
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
frameSharedVarLocalVar.kt:6
|
||||
Compile bytecode for var1
|
||||
package frameSharedVarLocalVar
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
var var1 = 1
|
||||
foo {
|
||||
//Breakpoint!
|
||||
var1 = 2
|
||||
}
|
||||
}
|
||||
|
||||
inline fun foo(f: () -> Unit) {
|
||||
f()
|
||||
}
|
||||
|
||||
// PRINT_FRAME
|
||||
|
||||
// EXPRESSION: var1
|
||||
// RESULT: 1: I
|
||||
frame = main():7, FrameSharedVarLocalVarPackage-@packagePartHASH {frameSharedVarLocalVar}
|
||||
static = static = frameSharedVarLocalVar.FrameSharedVarLocalVarPackage-@packagePartHASH
|
||||
local = args: java.lang.String[] = {java.lang.String[0]@uniqueID}
|
||||
local = var1: kotlin.jvm.internal.Ref$IntRef = {kotlin.jvm.internal.Ref$IntRef@uniqueID}1
|
||||
field = element: int = 1
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
+4
-1
@@ -12,4 +12,7 @@ fun foo(f: () -> Unit) {
|
||||
f()
|
||||
}
|
||||
|
||||
// PRINT_FRAME
|
||||
// PRINT_FRAME
|
||||
|
||||
// EXPRESSION: var1
|
||||
// RESULT: 1: I
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package frameSharedVarLocalVar
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
var var1 = 1
|
||||
foo {
|
||||
//Breakpoint!
|
||||
var1 = 2
|
||||
}
|
||||
}
|
||||
|
||||
inline fun foo(f: () -> Unit) {
|
||||
f()
|
||||
}
|
||||
|
||||
// PRINT_FRAME
|
||||
|
||||
// EXPRESSION: var1
|
||||
// RESULT: 1: I
|
||||
+6
@@ -266,6 +266,12 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
|
||||
doSingleBreakpointTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("frameSharedVarLocalVar.kt")
|
||||
public void testFrameSharedVarLocalVar() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/frameSharedVarLocalVar.kt");
|
||||
doSingleBreakpointTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("frameSimple.kt")
|
||||
public void testFrameSimple() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/frameSimple.kt");
|
||||
|
||||
Reference in New Issue
Block a user