From e1e845cef165e0b3133b4c6f14b61bc7db8540f6 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Thu, 29 Oct 2015 15:50:01 +0300 Subject: [PATCH] Fix conditional breakpoints --- .../idea/debugger/JetPositionManager.kt | 2 +- .../outs/simpleConditionalBreakpoint.out | 7 +++ .../isInsideInlineLambda.kt | 10 ++--- .../multipleBreakpointsAtLine.kt | 14 +++--- .../ceAnonymousObjectCapturedInClosure.kt | 2 +- .../lambdas/twoLambdasOnOneLineFirst.kt | 2 +- .../src/stepping/custom/severalFunLiterals.kt | 2 +- .../custom/severalFunLiteralsInClass.kt | 2 +- .../custom/simpleConditionalBreakpoint.kt | 8 ++++ .../idea/debugger/KotlinDebuggerTestBase.kt | 43 +++++++++++++------ .../debugger/KotlinSteppingTestGenerated.java | 6 +++ 11 files changed, 69 insertions(+), 29 deletions(-) create mode 100644 idea/testData/debugger/tinyApp/outs/simpleConditionalBreakpoint.out create mode 100644 idea/testData/debugger/tinyApp/src/stepping/custom/simpleConditionalBreakpoint.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/debugger/JetPositionManager.kt b/idea/src/org/jetbrains/kotlin/idea/debugger/JetPositionManager.kt index 93eefc61a4e..7ac123766f0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/debugger/JetPositionManager.kt +++ b/idea/src/org/jetbrains/kotlin/idea/debugger/JetPositionManager.kt @@ -76,7 +76,7 @@ public class JetPositionManager(private val myDebugProcess: DebugProcess) : Mult private val myTypeMappers = WeakHashMap>() override fun evaluateCondition(context: EvaluationContext, frame: StackFrameProxyImpl, location: Location, expression: String): ThreeState? { - return null + return ThreeState.UNSURE } override fun createStackFrame(frame: StackFrameProxyImpl, debugProcess: DebugProcessImpl, location: Location): XStackFrame? { diff --git a/idea/testData/debugger/tinyApp/outs/simpleConditionalBreakpoint.out b/idea/testData/debugger/tinyApp/outs/simpleConditionalBreakpoint.out new file mode 100644 index 00000000000..c0872dcc4c6 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/simpleConditionalBreakpoint.out @@ -0,0 +1,7 @@ +LineBreakpoint created at simpleConditionalBreakpoint.kt:5 condition = 1 == 1 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! simpleConditionalBreakpoint.SimpleConditionalBreakpointKt +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +simpleConditionalBreakpoint.kt:5 +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/src/evaluate/multipleBreakpoints/isInsideInlineLambda.kt b/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/isInsideInlineLambda.kt index f415ad5c0b4..4f41bd0de0d 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/isInsideInlineLambda.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/isInsideInlineLambda.kt @@ -5,7 +5,7 @@ fun main(args: Array) { // EXPRESSION: it + 1 // RESULT: 2: I - //Breakpoint! (0) + //Breakpoint! (lambdaOrdinal = 0) a.foo(1) { 1 } @@ -13,7 +13,7 @@ fun main(args: Array) { a.foo(1) { // EXPRESSION: it + 2 // RESULT: 3: I - //Breakpoint! (0) + //Breakpoint! (lambdaOrdinal = 0) a.foo(1) { 1 } 1 } @@ -21,7 +21,7 @@ fun main(args: Array) { // inside variable declaration // EXPRESSION: it + 3 // RESULT: 4: I - //Breakpoint! (0) + //Breakpoint! (lambdaOrdinal = 0) val x = a.foo(1) { 1 } // inside object declaration @@ -29,7 +29,7 @@ fun main(args: Array) { fun foo() { // EXPRESSION: it + 4 // RESULT: 5: I - //Breakpoint! (0) + //Breakpoint! (lambdaOrdinal = 0) a.foo(1) { 1 } } } @@ -39,7 +39,7 @@ fun main(args: Array) { fun local() { // EXPRESSION: it + 5 // RESULT: 6: I - //Breakpoint! (0) + //Breakpoint! (lambdaOrdinal = 0) a.foo(1) { 1 } } local() diff --git a/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/multipleBreakpointsAtLine.kt b/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/multipleBreakpointsAtLine.kt index ff77077f7fa..fe1e2ba15e3 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/multipleBreakpointsAtLine.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/multipleBreakpoints/multipleBreakpointsAtLine.kt @@ -5,17 +5,17 @@ fun main(args: Array) { // EXPRESSION: it + 1 // RESULT: Unresolved reference: it - //Breakpoint! (-1) + //Breakpoint! (lambdaOrdinal = -1) a.foo(1) { 1 }.foo(2) { 1 } // EXPRESSION: it + 2 // RESULT: 3: I - //Breakpoint! (0) + //Breakpoint! (lambdaOrdinal = 0) a.foo(1) { 1 }.foo(2) { 1 } // EXPRESSION: it + 3 // RESULT: 5: I - //Breakpoint! (1) + //Breakpoint! (lambdaOrdinal = 1) a.foo(1) { 1 }.foo(2) { 1 } // EXPRESSION: it + 4 @@ -34,17 +34,17 @@ fun main(args: Array) { // EXPRESSION: it + 8 // RESULT: Unresolved reference: it - //Breakpoint! (-1) + //Breakpoint! (lambdaOrdinal = -1) a.bar(1) { 1 }.bar(2) { 1 } // EXPRESSION: it + 9 // RESULT: 10: I - //Breakpoint! (0) + //Breakpoint! (lambdaOrdinal = 0) a.bar(1) { 1 }.bar(2) { 1 } // EXPRESSION: it + 10 // RESULT: 12: I - //Breakpoint! (1) + //Breakpoint! (lambdaOrdinal = 1) a.bar(1) { 1 }.bar(2) { 1 } // EXPRESSION: it + 11 @@ -63,7 +63,7 @@ fun main(args: Array) { // EXPRESSION: it + 15 // RESULT: 17: I - //Breakpoint! (1) + //Breakpoint! (lambdaOrdinal = 1) a.bar(1) { 1 }.bar(2) { 1 + 1 1 + 1 } diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceAnonymousObjectCapturedInClosure.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceAnonymousObjectCapturedInClosure.kt index f0b20979ae6..8019337d972 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceAnonymousObjectCapturedInClosure.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/compilingEvaluator/ceAnonymousObjectCapturedInClosure.kt @@ -3,7 +3,7 @@ package ceAnonymousObjectCapturedInClosure fun main(args: Array) { val localObject = object { fun test() = 1 } var localObjectVar = object { fun test() = 1 } - //Breakpoint! (-1) + //Breakpoint! (lambdaOrdinal = -1) lambda { localObjectVar.test() } } diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/lambdas/twoLambdasOnOneLineFirst.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/lambdas/twoLambdasOnOneLineFirst.kt index a7ce4515cb3..bd9988f6b1a 100644 --- a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/lambdas/twoLambdasOnOneLineFirst.kt +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/lambdas/twoLambdasOnOneLineFirst.kt @@ -5,7 +5,7 @@ fun main(args: Array) { // EXPRESSION: it // RESULT: 1: I // STEP_INTO: 2 - //Breakpoint! (-1) + //Breakpoint! (lambdaOrdinal = -1) a.foo { a }.foo { a } } diff --git a/idea/testData/debugger/tinyApp/src/stepping/custom/severalFunLiterals.kt b/idea/testData/debugger/tinyApp/src/stepping/custom/severalFunLiterals.kt index 9cef982aaab..0866f6c6981 100644 --- a/idea/testData/debugger/tinyApp/src/stepping/custom/severalFunLiterals.kt +++ b/idea/testData/debugger/tinyApp/src/stepping/custom/severalFunLiterals.kt @@ -2,7 +2,7 @@ package severalFunLiterals fun main(args: Array) { val myClass = MyClass() - //Breakpoint! (-1) + //Breakpoint! (lambdaOrdinal = -1) myClass.f1 { test() }.f2 { test() } diff --git a/idea/testData/debugger/tinyApp/src/stepping/custom/severalFunLiteralsInClass.kt b/idea/testData/debugger/tinyApp/src/stepping/custom/severalFunLiteralsInClass.kt index 912b6638d78..55c8a2f971c 100644 --- a/idea/testData/debugger/tinyApp/src/stepping/custom/severalFunLiteralsInClass.kt +++ b/idea/testData/debugger/tinyApp/src/stepping/custom/severalFunLiteralsInClass.kt @@ -16,7 +16,7 @@ class MyClass { } fun inClass() { - //Breakpoint! (-1) + //Breakpoint! (lambdaOrdinal = -1) f1 { test() }.f2 { test() } diff --git a/idea/testData/debugger/tinyApp/src/stepping/custom/simpleConditionalBreakpoint.kt b/idea/testData/debugger/tinyApp/src/stepping/custom/simpleConditionalBreakpoint.kt new file mode 100644 index 00000000000..272df353a05 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/stepping/custom/simpleConditionalBreakpoint.kt @@ -0,0 +1,8 @@ +package simpleConditionalBreakpoint + +fun main(args: Array) { + //Breakpoint! (condition = 1 == 1) + args.size() +} + +// RESUME: 1 \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestBase.kt b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestBase.kt index 2baec078f59..bc6b547229e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestBase.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinDebuggerTestBase.kt @@ -21,7 +21,9 @@ import com.intellij.debugger.SourcePosition import com.intellij.debugger.actions.MethodSmartStepTarget import com.intellij.debugger.actions.SmartStepTarget import com.intellij.debugger.engine.* +import com.intellij.debugger.engine.evaluation.CodeFragmentKind import com.intellij.debugger.engine.evaluation.EvaluationContextImpl +import com.intellij.debugger.engine.evaluation.TextWithImportsImpl import com.intellij.debugger.impl.DebuggerContextImpl import com.intellij.debugger.impl.PositionUtil import com.intellij.debugger.settings.DebuggerSettings @@ -300,8 +302,9 @@ abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() { } } else if (comment.startsWith("//Breakpoint!")) { - val ordinal = if (comment.contains(" (")) comment.substringAfter("//Breakpoint! (").substringBefore(")").toInt() else null - createLineBreakpoint(breakpointManager, file, lineIndex, ordinal) + val ordinal = getPropertyFromComment(comment, "lambdaOrdinal")?.toInt() ?: null + val condition = getPropertyFromComment(comment, "condition") + createLineBreakpoint(breakpointManager, file, lineIndex, ordinal, condition) } else { throw AssertionError("Cannot create breakpoint at line ${lineIndex + 1}") @@ -317,11 +320,25 @@ abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() { } } + private fun getPropertyFromComment(comment: String, propertyName: String): String? { + if (comment.contains("$propertyName = ")) { + val result = comment.substringAfter("$propertyName = ") + if (result.contains(", ")) { + return result.substringBefore(", ") + } + if (result.contains(")")) { + return result.substringBefore(")") + } + } + return null + } + private fun createLineBreakpoint( breakpointManager: XBreakpointManager, file: PsiFile, lineIndex: Int, - lambdaOrdinal: Int? + lambdaOrdinal: Int?, + condition: String? ) { val kotlinLineBreakpointType = findBreakpointType(KotlinLineBreakpointType::class.java) val javaBreakpoint = createBreakpointOfType( @@ -330,17 +347,19 @@ abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() { lineIndex, file.virtualFile) if (javaBreakpoint is LineBreakpoint<*>) { + val properties = javaBreakpoint.xBreakpoint.properties as? JavaLineBreakpointProperties ?: return + var suffix = "" if (lambdaOrdinal != null) { - val properties = javaBreakpoint.xBreakpoint.properties as? JavaLineBreakpointProperties ?: return properties.lambdaOrdinal = lambdaOrdinal + suffix += " lambdaOrdinal = $lambdaOrdinal" + } + if (condition != null) { + javaBreakpoint.setCondition(TextWithImportsImpl(CodeFragmentKind.EXPRESSION, condition)) + suffix += " condition = $condition" + } - BreakpointManager.addBreakpoint(javaBreakpoint) - println("LineBreakpoint created at ${file.virtualFile.name}:${lineIndex + 1} lambdaOrdinal = $lambdaOrdinal", ProcessOutputTypes.SYSTEM) - } - else { - BreakpointManager.addBreakpoint(javaBreakpoint) - println("LineBreakpoint created at ${file.virtualFile.name}:${lineIndex + 1}", ProcessOutputTypes.SYSTEM) - } + BreakpointManager.addBreakpoint(javaBreakpoint) + println("LineBreakpoint created at ${file.virtualFile.name}:${lineIndex + 1}$suffix", ProcessOutputTypes.SYSTEM) } } @@ -403,7 +422,7 @@ abstract class KotlinDebuggerTestBase : KotlinDebuggerTestCase() { val index = psiSourceFile.getText()!!.indexOf(lineMarker) val lineNumber = document.getLineNumber(index) + 1 // lineMarker is for previous line - createLineBreakpoint(breakpointManager, psiSourceFile, lineNumber, ordinal) + createLineBreakpoint(breakpointManager, psiSourceFile, lineNumber, ordinal, null) } DebuggerInvocationUtil.invokeAndWait(project, runnable, ModalityState.defaultModalityState()) diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java index 5235df450f6..9c81b3cb8c8 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java @@ -541,6 +541,12 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest { doCustomTest(fileName); } + @TestMetadata("simpleConditionalBreakpoint.kt") + public void testSimpleConditionalBreakpoint() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/simpleConditionalBreakpoint.kt"); + doCustomTest(fileName); + } + @TestMetadata("smartStepIntoInlinedFunLiteral.kt") public void testSmartStepIntoInlinedFunLiteral() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/custom/smartStepIntoInlinedFunLiteral.kt");