diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java index 7bb98d77793a..93c63f1760da 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java @@ -100,6 +100,10 @@ public abstract class Breakpoint
implements return myProject; } + private @NotNull BreakpointManager getBreakpointManager() { + return DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager(); + } + protected @NotNull P getProperties() { return myXBreakpoint.getProperties(); } @@ -395,7 +399,9 @@ public abstract class Breakpoint
implements buf.append("\n"); } if (!buf.isEmpty()) { - debugProcess.printToConsole(buf.toString()); + var msg = buf.toString(); + getBreakpointManager().multicastLogMessage(this, msg, debugProcess); + debugProcess.printToConsole(msg); } } if (isRemoveAfterHit()) { @@ -623,7 +629,7 @@ public abstract class Breakpoint
implements
}
private void removeBreakpoint() {
- AppUIUtil.invokeOnEdt(() -> DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().removeBreakpoint(Breakpoint.this));
+ AppUIUtil.invokeOnEdt(() -> getBreakpointManager().removeBreakpoint(Breakpoint.this));
debugProcess.removeDebugProcessListener(this);
}
});
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointLogMessageListener.kt b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointLogMessageListener.kt
new file mode 100644
index 000000000000..80625a850a74
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointLogMessageListener.kt
@@ -0,0 +1,14 @@
+// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
+package com.intellij.debugger.ui.breakpoints
+
+import com.intellij.debugger.engine.DebugProcessImpl
+import org.jetbrains.annotations.ApiStatus
+import java.util.EventListener
+
+/**
+ * Listener for breakpoint messages: evaluate and log, stack trace, "breakpoint hit", etc.
+ */
+@ApiStatus.Internal
+fun interface BreakpointLogMessageListener : EventListener {
+ fun onLogMessage(breakpoint: Breakpoint<*>, message: String, debugProcess: DebugProcessImpl)
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java
index 1c136686b1c3..185fa31b8d99 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/BreakpointManager.java
@@ -14,6 +14,7 @@ import com.intellij.debugger.engine.LightOrRealThreadInfo;
import com.intellij.debugger.engine.RealThreadInfo;
import com.intellij.debugger.engine.requests.RequestManagerImpl;
import com.intellij.debugger.impl.*;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.WriteAction;
@@ -33,6 +34,8 @@ import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.PsiField;
+import com.intellij.util.CoroutineScopeKt;
+import com.intellij.util.EventDispatcher;
import com.intellij.util.concurrency.AppExecutorUtil;
import com.intellij.util.concurrency.ThreadingAssertions;
import com.intellij.util.containers.ContainerUtil;
@@ -55,6 +58,7 @@ import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.request.EventRequest;
import com.sun.jdi.request.EventRequestManager;
import com.sun.jdi.request.InvalidRequestStateException;
+import kotlinx.coroutines.CoroutineScope;
import one.util.streamex.StreamEx;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
@@ -86,6 +90,8 @@ public class BreakpointManager {
private final Project myProject;
private final Map