mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[debugger] Add possibility to use suspend-thread mode in Kotlin stepping tests
IDEA-381878 IDEA-365578 GitOrigin-RevId: 84125a840c6d105a087eb34131f3d7da899d6438
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b4e940ebe4
commit
23fe1a8e21
@@ -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<Boolean?> = KeyWithDefaultValue.create("USE_XSESSION_PAUSE_LISTENER_KEY", false)
|
||||
|
||||
/**
|
||||
* It allows to avoid the hell with listeners by pretty linear program.
|
||||
* It allows to write:
|
||||
|
||||
+37
-1
@@ -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.
|
||||
* <p>
|
||||
@@ -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.
|
||||
* <p>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+2
-1
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -49,6 +49,8 @@ internal object DebuggerPreferenceKeys {
|
||||
|
||||
val JVM_DEFAULT_MODE by debuggerPreferenceKey("")
|
||||
|
||||
val USE_XSESSION_PAUSE_LISTENER by debuggerPreferenceKey(false)
|
||||
|
||||
val values: List<DebuggerPreferenceKey<*>> by lazy {
|
||||
DebuggerPreferenceKeys::class.declaredMemberProperties
|
||||
.filter { (it.returnType.javaType as? ParameterizedType)?.rawType == DebuggerPreferenceKey::class.java }
|
||||
|
||||
+11
-1
@@ -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<SettingsMutator<*>> = listOf(
|
||||
ForceRankingSettingsMutator,
|
||||
ReflectionPatchingMutator,
|
||||
ShowLibraryStackFramesMutator,
|
||||
UseXSessionPauseListenerMutator,
|
||||
)
|
||||
|
||||
private class DebuggerSettingsMutator<T : Any>(
|
||||
@@ -104,3 +106,11 @@ private object ShowLibraryStackFramesMutator : SettingsMutator<Boolean>(Debugger
|
||||
return oldValue
|
||||
}
|
||||
}
|
||||
|
||||
private object UseXSessionPauseListenerMutator : SettingsMutator<Boolean>(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
|
||||
}
|
||||
}
|
||||
|
||||
+17
-3
@@ -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")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user