Debugger: Support synchronized blocks and functions in evaluator (KT-11888)
This commit is contained in:
+7
@@ -20,6 +20,7 @@ import com.sun.jdi.ArrayReference
|
||||
import com.sun.jdi.ArrayType
|
||||
import com.sun.jdi.ClassLoaderReference
|
||||
import com.sun.jdi.Value
|
||||
import jdk.internal.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
@@ -63,6 +64,7 @@ interface ClassLoadingAdapter {
|
||||
|
||||
private fun analyzeClass(classToLoad: ClassToLoad, info: ClassInfoForEvaluator): ClassInfoForEvaluator {
|
||||
val classNode = ClassNode().apply { ClassReader(classToLoad.bytes).accept(this, 0) }
|
||||
|
||||
val methodToRun = classNode.methods.single { it.name == GENERATED_FUNCTION_NAME }
|
||||
|
||||
val visitedLabels = hashSetOf<Label>()
|
||||
@@ -78,6 +80,11 @@ interface ClassLoadingAdapter {
|
||||
is TableSwitchInsnNode, is LookupSwitchInsnNode -> {
|
||||
return info.copy(containsCodeUnsupportedInEval4J = true)
|
||||
}
|
||||
is InsnNode -> {
|
||||
if (insn.opcode == Opcodes.MONITORENTER || insn.opcode == Opcodes.MONITOREXIT) {
|
||||
return info.copy(containsCodeUnsupportedInEval4J = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val nextInsn = insn.next ?: return info
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package synchronizedBlock
|
||||
|
||||
fun main() {
|
||||
//Breakpoint!
|
||||
val a = 5
|
||||
}
|
||||
|
||||
// EXPRESSION: synchronized(Any()) { "foo" }
|
||||
// RESULT: "foo": Ljava/lang/String;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
class Foo {
|
||||
@Synchronized
|
||||
fun foo(): Int {
|
||||
return 5
|
||||
}
|
||||
}
|
||||
|
||||
Foo().foo()
|
||||
|
||||
// RESULT: 5: I
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
LineBreakpoint created at synchronizedBlock.kt:5
|
||||
Run Java
|
||||
Connected to the target VM
|
||||
synchronizedBlock.kt:5
|
||||
Compile bytecode for synchronized(Any()) { "foo" }
|
||||
Compile bytecode for class Foo {
|
||||
@Synchronized
|
||||
fun foo(): Int {
|
||||
return 5
|
||||
}
|
||||
}
|
||||
|
||||
Foo().foo()
|
||||
|
||||
// RESULT: 5: I
|
||||
Disconnected from the target VM
|
||||
|
||||
Process finished with exit code 0
|
||||
Generated
+5
@@ -391,6 +391,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
|
||||
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/stdlib.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("synchronizedBlock.kt")
|
||||
public void testSynchronizedBlock() throws Exception {
|
||||
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/synchronizedBlock.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeParameterRef.kt")
|
||||
public void testTypeParameterRef() throws Exception {
|
||||
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/typeParameterRef.kt");
|
||||
|
||||
Reference in New Issue
Block a user