diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapProgressImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapProgressImpl.java
index c9715ea5d91e..0bd755f05c5d 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapProgressImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapProgressImpl.java
@@ -26,6 +26,7 @@ import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
+import com.intellij.xdebugger.impl.hotswap.HotSwapStatusNotificationManager;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import one.util.streamex.StreamEx;
@@ -110,6 +111,7 @@ public final class HotSwapProgressImpl extends HotSwapProgress {
boolean withRestart,
NotificationType type) {
Notification notification = NOTIFICATION_GROUP.createNotification(title, message, type);
+ HotSwapStatusNotificationManager.getInstance(getProject()).trackNotification(notification);
if (SoftReference.dereference(mySessionRef) != null) {
if (withRestart) {
notification.addAction(new RestartHotSwapNotificationAction(mySessionRef));
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java
index 9b69c35c1936..68683b979cfb 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java
@@ -9,6 +9,7 @@ import com.intellij.debugger.impl.HotSwapFile;
import com.intellij.debugger.impl.HotSwapManager;
import com.intellij.debugger.impl.hotswap.HotSwapDebugSessionManager;
import com.intellij.debugger.settings.DebuggerSettings;
+import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
@@ -30,6 +31,7 @@ import com.intellij.ui.UIBundle;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FileCollectionFactory;
import com.intellij.util.messages.MessageBusConnection;
+import com.intellij.xdebugger.impl.hotswap.HotSwapStatusNotificationManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.util.JpsPathUtil;
@@ -144,7 +146,9 @@ public final class HotSwapUIImpl extends HotSwapUI {
if (modifiedClasses.isEmpty()) {
String message = JavaDebuggerBundle.message("status.hotswap.uptodate");
- HotSwapProgressImpl.NOTIFICATION_GROUP.createNotification(message, NotificationType.INFORMATION).notify(myProject);
+ Notification notification = HotSwapProgressImpl.NOTIFICATION_GROUP.createNotification(message, NotificationType.INFORMATION);
+ HotSwapStatusNotificationManager.getInstance(myProject).trackNotification(notification);
+ notification.notify(myProject);
statusListener.onNothingToReload(sessions);
return;
}
diff --git a/platform/xdebugger-impl/resources/META-INF/xdebugger.xml b/platform/xdebugger-impl/resources/META-INF/xdebugger.xml
index 9fc705079370..7a228bffaa0f 100644
--- a/platform/xdebugger-impl/resources/META-INF/xdebugger.xml
+++ b/platform/xdebugger-impl/resources/META-INF/xdebugger.xml
@@ -109,7 +109,7 @@
-
+
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/hotswap/HotSwapSessionManager.kt b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/hotswap/HotSwapSessionManager.kt
index eea323cd59a8..7817488d540d 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/hotswap/HotSwapSessionManager.kt
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/hotswap/HotSwapSessionManager.kt
@@ -38,6 +38,7 @@ class HotSwapSessionManager(private val project: Project, private val parentScop
}
companion object {
+ @JvmStatic
fun getInstance(project: Project): HotSwapSessionManager = project.service()
}
}
@@ -74,6 +75,7 @@ class HotSwapSession(val project: Project, internal val provider: HotSwapProv
}
override fun dispose() {
+ HotSwapStatusNotificationManager.getInstance(project).clearNotifications()
currentStatus = HotSwapVisibleStatus.SESSION_COMPLETED
coroutineScope.cancel()
}
@@ -88,6 +90,7 @@ class HotSwapSession(val project: Project, internal val provider: HotSwapProv
fun getChanges() = changesCollector.getChanges()
fun startHotSwapListening(): HotSwapResultListener {
+ HotSwapStatusNotificationManager.getInstance(project).clearNotifications()
currentStatus = HotSwapVisibleStatus.IN_PROGRESS
return object : HotSwapResultListener {
override fun onSuccessfulReload() {
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/hotswap/HotSwapStatusNotificationManager.kt b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/hotswap/HotSwapStatusNotificationManager.kt
index 331bd79f8586..09fc3cb5c9b6 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/hotswap/HotSwapStatusNotificationManager.kt
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/hotswap/HotSwapStatusNotificationManager.kt
@@ -3,6 +3,7 @@ package com.intellij.xdebugger.impl.hotswap
import com.intellij.execution.multilaunch.design.components.RoundedCornerBorder
import com.intellij.icons.AllIcons
+import com.intellij.notification.Notification
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.EDT
import com.intellij.openapi.components.Service
@@ -23,6 +24,7 @@ import kotlinx.coroutines.launch
import org.jetbrains.annotations.ApiStatus
import java.awt.BorderLayout
import java.awt.Point
+import java.util.*
import javax.swing.JPanel
import javax.swing.SwingConstants
import kotlin.time.Duration.Companion.seconds
@@ -31,9 +33,22 @@ import kotlin.time.Duration.Companion.seconds
@Service(Service.Level.PROJECT)
class HotSwapStatusNotificationManager(private val project: Project) : Disposable.Default {
companion object {
+ @JvmStatic
fun getInstance(project: Project): HotSwapStatusNotificationManager = project.service()
}
+ private val notifications = Collections.synchronizedSet(hashSetOf())
+
+ fun trackNotification(notification: Notification) {
+ notification.whenExpired { notifications.remove(notification) }
+ notifications.add(notification)
+ }
+
+ internal fun clearNotifications() {
+ notifications.forEach { it.expire() }
+ notifications.clear()
+ }
+
fun showSuccessNotification(scope: CoroutineScope, disposable: Disposable? = null) {
scope.launch(Dispatchers.EDT) {
val frame = WindowManager.getInstance().getFrame(project) ?: return@launch