diff --git a/java/testFramework/src/com/intellij/debugger/DebuggerBreakpointTestUtils.kt b/java/testFramework/src/com/intellij/debugger/DebuggerBreakpointTestUtils.kt index 7426a3c589b9..b87c80c981da 100644 --- a/java/testFramework/src/com/intellij/debugger/DebuggerBreakpointTestUtils.kt +++ b/java/testFramework/src/com/intellij/debugger/DebuggerBreakpointTestUtils.kt @@ -3,8 +3,12 @@ package com.intellij.debugger import com.intellij.execution.process.ProcessEvent import com.intellij.execution.process.ProcessListener +import com.intellij.openapi.util.KeyWithDefaultValue import com.intellij.util.ConcurrencyUtil +@JvmField +val USE_XSESSION_PAUSE_LISTENER_KEY: KeyWithDefaultValue = KeyWithDefaultValue.create("USE_XSESSION_PAUSE_LISTENER_KEY", false) + /** * It allows to avoid the hell with listeners by pretty linear program. * It allows to write: diff --git a/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java b/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java index d9951813a73f..2b1d7a1fb35e 100644 --- a/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java +++ b/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java @@ -7,6 +7,7 @@ import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.TextWithImportsImpl; import com.intellij.debugger.engine.events.DebuggerCommandImpl; import com.intellij.debugger.engine.events.SuspendContextCommandImpl; +import com.intellij.debugger.impl.DebuggerSession; import com.intellij.debugger.impl.PositionUtil; import com.intellij.debugger.impl.PrioritizedTask; import com.intellij.debugger.jdi.StackFrameProxyImpl; @@ -31,6 +32,11 @@ import com.intellij.util.TimeoutUtil; import com.intellij.util.lang.CompoundRuntimeException; import com.intellij.util.ui.EdtInvocationManager; import com.intellij.util.ui.UIUtil; +import com.intellij.xdebugger.XDebugSession; +import com.intellij.xdebugger.XDebugSessionListener; +import com.intellij.xdebugger.frame.XSuspendContext; +import com.intellij.xdebugger.impl.XSteppingSuspendContext; +import com.intellij.xdebugger.impl.frame.XDebugSessionProxyKeeperKt; import com.sun.jdi.Method; import com.sun.jdi.request.StepRequest; import org.jetbrains.annotations.NotNull; @@ -43,6 +49,8 @@ import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.concurrent.TimeUnit; +import static com.intellij.debugger.DebuggerBreakpointTestUtilsKt.USE_XSESSION_PAUSE_LISTENER_KEY; + /** * Runs the IDE with the debugger. *

@@ -151,11 +159,35 @@ public abstract class ExecutionWithDebuggerToolsTestCase extends ExecutionTestCa assertNotNull("Debug process was not started", debugProcess); myBreakpointProvider = new BreakpointProvider(myDebugProcess); - debugProcess.addDebugProcessListener(myBreakpointProvider, getTestRootDisposable()); + + if (USE_XSESSION_PAUSE_LISTENER_KEY.get(myDebugProcess.getProject(), false)) { + useXSessionPauseListener(debugProcess); + } else { + debugProcess.addDebugProcessListener(myBreakpointProvider, getTestRootDisposable()); + } } return myBreakpointProvider; } + private void useXSessionPauseListener(DebugProcessImpl debugProcess) { + DebuggerSession jvmSession = debugProcess.getSession(); + JavaDebugProcess process = debugProcess.getXdebugProcess(); + assert (process != null); + XDebugSession xSession = process.getSession(); + XDebugSessionProxyKeeperKt.asProxy(xSession).addSessionListener(new XDebugSessionListener() { + @Override + public void sessionPaused() { + SuspendContextImpl suspendContext = jvmSession.getContextManager().getContext().getSuspendContext(); + if (suspendContext == null) { + XSuspendContext xSessionSuspendContext = xSession.getSuspendContext(); + assert xSessionSuspendContext instanceof XSteppingSuspendContext : "Suspension context is null and XSuspendContext is " + xSessionSuspendContext; + } else { + myBreakpointProvider.pausedWrapper(suspendContext); + } + } + }, xSession.getProject()); + } + /** * Queues an action to be run a single time. *

@@ -573,6 +605,10 @@ public abstract class ExecutionWithDebuggerToolsTestCase extends ExecutionTestCa @Override public void paused(SuspendContextImpl suspendContext) { // Need to add SuspendContextCommandImpl because the stepping pause is not now in SuspendContextCommandImpl + pausedWrapper(suspendContext); + } + + void pausedWrapper(SuspendContextImpl suspendContext) { if (DebugProcessImpl.isInSuspendCommand(suspendContext)) { pausedImpl(suspendContext); } diff --git a/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinDescriptorTestCase.kt b/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinDescriptorTestCase.kt index 70dfb52086f7..6439946a2248 100644 --- a/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinDescriptorTestCase.kt +++ b/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinDescriptorTestCase.kt @@ -40,9 +40,9 @@ import com.intellij.util.containers.addIfNotNull import com.intellij.xdebugger.XDebugSession import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil +import org.jetbrains.kotlin.idea.artifacts.TestKotlinArtifacts import org.jetbrains.kotlin.idea.base.codeInsight.KotlinMainFunctionDetector import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode -import org.jetbrains.kotlin.idea.artifacts.TestKotlinArtifacts import org.jetbrains.kotlin.idea.base.psi.classIdIfNonLocal import org.jetbrains.kotlin.idea.base.test.IgnoreTests import org.jetbrains.kotlin.idea.base.test.InTextDirectivesUtils @@ -633,6 +633,7 @@ abstract class KotlinDescriptorTestCase : DescriptorTestCase(), if (file != null) { val breakpointCreator = this.breakpointCreator ?: error(BreakpointCreator::class.java.simpleName + " should be set") breakpointCreator.createBreakpoints(file) + myWasUsedOnlyDefaultSuspendPolicy = breakpointCreator.wasUsedOnlyDefaultSuspendPolicy } } diff --git a/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/preference/DebuggerPreferenceKey.kt b/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/preference/DebuggerPreferenceKey.kt index 8c33dac62568..ac62e391713e 100644 --- a/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/preference/DebuggerPreferenceKey.kt +++ b/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/preference/DebuggerPreferenceKey.kt @@ -49,6 +49,8 @@ internal object DebuggerPreferenceKeys { val JVM_DEFAULT_MODE by debuggerPreferenceKey("") + val USE_XSESSION_PAUSE_LISTENER by debuggerPreferenceKey(false) + val values: List> by lazy { DebuggerPreferenceKeys::class.declaredMemberProperties .filter { (it.returnType.javaType as? ParameterizedType)?.rawType == DebuggerPreferenceKey::class.java } diff --git a/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/preference/SettingsMutators.kt b/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/preference/SettingsMutators.kt index 7650048f685f..354f072095bf 100644 --- a/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/preference/SettingsMutators.kt +++ b/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/preference/SettingsMutators.kt @@ -2,13 +2,14 @@ package org.jetbrains.kotlin.idea.debugger.test.preference +import com.intellij.debugger.USE_XSESSION_PAUSE_LISTENER_KEY import com.intellij.debugger.settings.DebuggerSettings import com.intellij.openapi.application.runWriteAction import com.intellij.openapi.project.Project import com.intellij.xdebugger.impl.settings.XDebuggerSettingManagerImpl import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JvmCompilerArgumentsHolder -import org.jetbrains.kotlin.idea.debugger.core.DebuggerUtils import org.jetbrains.kotlin.idea.debugger.KotlinDebuggerSettings +import org.jetbrains.kotlin.idea.debugger.core.DebuggerUtils import org.jetbrains.kotlin.idea.debugger.core.ToggleKotlinVariablesState import org.jetbrains.kotlin.idea.debugger.evaluate.compilation.ReflectionCallClassPatcher import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferenceKeys.DISABLE_KOTLIN_INTERNAL_CLASSES @@ -33,6 +34,7 @@ internal val SettingsMutators: List> = listOf( ForceRankingSettingsMutator, ReflectionPatchingMutator, ShowLibraryStackFramesMutator, + UseXSessionPauseListenerMutator, ) private class DebuggerSettingsMutator( @@ -104,3 +106,11 @@ private object ShowLibraryStackFramesMutator : SettingsMutator(Debugger return oldValue } } + +private object UseXSessionPauseListenerMutator : SettingsMutator(DebuggerPreferenceKeys.USE_XSESSION_PAUSE_LISTENER) { + override fun setValue(value: Boolean, project: Project): Boolean { + val oldValue = USE_XSESSION_PAUSE_LISTENER_KEY.get(project, false)!! + USE_XSESSION_PAUSE_LISTENER_KEY.set(project, value) + return oldValue + } +} diff --git a/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/util/BreakpointCreator.kt b/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/util/BreakpointCreator.kt index 9efbd855b804..df47ab7945f5 100644 --- a/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/util/BreakpointCreator.kt +++ b/plugins/kotlin/jvm-debugger/test/test/org/jetbrains/kotlin/idea/debugger/test/util/BreakpointCreator.kt @@ -4,6 +4,7 @@ package org.jetbrains.kotlin.idea.debugger.test.util import com.intellij.debugger.engine.evaluation.CodeFragmentKind import com.intellij.debugger.engine.evaluation.TextWithImportsImpl +import com.intellij.debugger.settings.DebuggerSettings import com.intellij.debugger.ui.breakpoints.Breakpoint import com.intellij.debugger.ui.breakpoints.BreakpointManager import com.intellij.debugger.ui.breakpoints.JavaLineBreakpointType @@ -40,6 +41,8 @@ internal class BreakpointCreator( private val logger: (String) -> Unit, private val preferences: DebuggerPreferences ) { + var wasUsedOnlyDefaultSuspendPolicy = true + fun createBreakpoints(file: PsiFile) { val document = runReadAction { PsiDocumentManager.getInstance(project).getDocument(file) } ?: return val breakpointManager = XDebuggerManager.getInstance(project).breakpointManager @@ -85,7 +88,8 @@ internal class BreakpointCreator( val lambdaOrdinal = getPropertyFromComment(comment, "lambdaOrdinal")?.toInt() val conditionalReturn = getPropertyFromComment(comment, "conditionalReturn").toBoolean() val condition = getPropertyFromComment(comment, "condition") - createLineBreakpoint(breakpointManager, file, lineIndex, lambdaOrdinal, conditionalReturn, condition) + val suspendPolicy = getPropertyFromComment(comment, "suspendPolicy") + createLineBreakpoint(breakpointManager, file, lineIndex, lambdaOrdinal, conditionalReturn, condition, suspendPolicy) } comment.startsWith("//FunctionBreakpoint!") -> { createFunctionBreakpoint(breakpointManager, file, lineIndex, false) @@ -109,7 +113,7 @@ internal class BreakpointCreator( when (kind) { "line" -> createBreakpoint(fileName, lineMarker) { psiFile, lineNumber -> - createLineBreakpoint(breakpointManager, psiFile, lineNumber + 1, ordinal, false, null) + createLineBreakpoint(breakpointManager, psiFile, lineNumber + 1, ordinal, false, null, null) } "fun" -> createBreakpoint(fileName, lineMarker) { psiFile, lineNumber -> createFunctionBreakpoint(breakpointManager, psiFile, lineNumber, true) @@ -173,7 +177,8 @@ internal class BreakpointCreator( lineIndex: Int, lambdaOrdinal: Int?, conditionalReturn: Boolean, - condition: String? + condition: String?, + suspendPolicy: String? ) { val kotlinLineBreakpointType = findBreakpointType(KotlinLineBreakpointType::class.java) val updatedLambdaOrdinal = lambdaOrdinal?.let { if (it != JavaLineBreakpointProperties.NO_LAMBDA) it - 1 else it } @@ -205,6 +210,15 @@ internal class BreakpointCreator( suffix += " condition = $condition" } + if (suspendPolicy != null) { + wasUsedOnlyDefaultSuspendPolicy = false + val okVariants = listOf(DebuggerSettings.SUSPEND_ALL, DebuggerSettings.SUSPEND_THREAD) + if (!okVariants.contains(suspendPolicy)) { + error("Unknown suspend policy: $suspendPolicy") + } + javaBreakpoint.suspendPolicy = suspendPolicy + } + BreakpointManager.addBreakpoint(javaBreakpoint) logger("LineBreakpoint created at ${file.virtualFile.name}:${lineIndex + 1}$suffix") }