[debugger] IJPL-158332 Simplify java debugger notifications on hotswap failure

* do not include session name
* use balloon notification

GitOrigin-RevId: f9492529682e0a78b621a4184045ab8a3312666c
This commit is contained in:
Maksim Zuev
2024-07-30 17:13:52 +00:00
committed by intellij-monorepo-bot
parent 7c94317606
commit f227a20bb8
6 changed files with 41 additions and 25 deletions
@@ -45,10 +45,6 @@ class ReloadClassesWorker {
}
private void processException(@NotNull Throwable e) {
if (e.getMessage() != null) {
myProgress.addMessage(myDebuggerSession, MessageCategory.ERROR, e.getMessage());
}
if (e instanceof ProcessCanceledException) {
myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION, JavaDebuggerBundle.message("error.operation.canceled"));
return;
@@ -56,7 +52,7 @@ class ReloadClassesWorker {
String message =
e instanceof UnsupportedOperationException
? JavaDebuggerBundle.message("error.operation.not.supported.by.vm")
? JavaDebuggerBundle.message("error.operation.not.supported.by.vm", e.getLocalizedMessage())
: e instanceof NoClassDefFoundError
? JavaDebuggerBundle.message("error.class.def.not.found", e.getLocalizedMessage())
: e instanceof VerifyError
@@ -7,10 +7,7 @@ import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.debugger.impl.HotSwapProgress;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.ExecutionUtil;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationAction;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationType;
import com.intellij.notification.*;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator;
@@ -19,7 +16,7 @@ import com.intellij.openapi.progress.util.ProgressWindow;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.reference.SoftReference;
import com.intellij.util.SmartList;
@@ -31,19 +28,24 @@ import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntIterator;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Unmodifiable;
import java.awt.*;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public final class HotSwapProgressImpl extends HotSwapProgress {
static final NotificationGroup NOTIFICATION_GROUP = NotificationGroup.toolWindowGroup("HotSwap", ToolWindowId.DEBUG);
static final NotificationGroup NOTIFICATION_GROUP = Registry.is("debugger.hotswap.floating.toolbar")
? NotificationGroupManager.getInstance().getNotificationGroup("HotSwap Messages")
: NotificationGroup.toolWindowGroup("HotSwap", ToolWindowId.DEBUG);
private final Int2ObjectMap<List<String>> myMessages = new Int2ObjectOpenHashMap<>();
private final Int2ObjectMap<Map<DebuggerSession, List<String>>> myMessages = new Int2ObjectOpenHashMap<>();
private final ProgressWindow myProgressWindow;
private @NlsContexts.ProgressTitle String myTitle = JavaDebuggerBundle.message("progress.hot.swap.title");
private final MergingUpdateQueue myUpdateQueue;
@@ -81,8 +83,11 @@ public final class HotSwapProgressImpl extends HotSwapProgress {
listener.onFinish();
}
List<String> errors = getMessages(MessageCategory.ERROR);
List<String> warnings = getMessages(MessageCategory.WARNING);
var debuggerSessions = myMessages.values().stream().flatMap(e -> e.keySet().stream()).collect(Collectors.toUnmodifiableSet());
boolean addSessionName = debuggerSessions.size() > 1;
List<String> errors = getMessages(MessageCategory.ERROR, addSessionName);
List<String> warnings = getMessages(MessageCategory.WARNING, addSessionName);
if (!errors.isEmpty()) {
notifyUser(JavaDebuggerBundle.message("status.hot.swap.completed.with.errors"), buildMessage(errors), true, NotificationType.ERROR);
@@ -93,8 +98,8 @@ public final class HotSwapProgressImpl extends HotSwapProgress {
}
else if (!myMessages.isEmpty()) {
List<String> messages = new ArrayList<>();
for (IntIterator iterator = myMessages.keySet().iterator(); iterator.hasNext(); ) {
messages.addAll(getMessages(iterator.nextInt()));
for (int key : myMessages.keySet()) {
messages.addAll(getMessages(key, addSessionName));
}
notifyUser("", buildMessage(messages), false, NotificationType.INFORMATION);
}
@@ -118,22 +123,35 @@ public final class HotSwapProgressImpl extends HotSwapProgress {
mySessionRef = new WeakReference<>(session.getXDebugSession());
}
List<String> getMessages(int category) {
return ContainerUtil.notNullize(myMessages.get(category));
private @NotNull @Unmodifiable List<String> getMessages(int category, boolean addSessionName) {
var sessionMessages = ContainerUtil.notNullize(myMessages.get(category));
return sessionMessages.entrySet().stream().flatMap(entry -> {
var stream = entry.getValue().stream();
return addSessionName ? stream.map(message -> entry.getKey().getSessionName() + ": " + message) : stream;
}).toList();
}
boolean hasErrors() {
return !getMessages(MessageCategory.ERROR, false).isEmpty();
}
private static @NlsSafe String buildMessage(List<String> messages) {
return StreamEx.of(messages).map(m -> StringUtil.trimEnd(m, ';')).joining("\n");
return StreamEx.of(messages).joining("\n");
}
@Override
public void addMessage(DebuggerSession session, final int type, final String text) {
List<String> messages = myMessages.get(type);
Map<DebuggerSession, List<String>> messages = myMessages.get(type);
if (messages == null) {
messages = new SmartList<>();
messages = new HashMap<>();
myMessages.put(type, messages);
}
messages.add(session.getSessionName() + ": " + text + ";");
List<String> sessionMessages = messages.get(session);
if (sessionMessages == null) {
sessionMessages = new SmartList<>();
messages.put(session, sessionMessages);
}
sessionMessages.add(text);
}
@Override
@@ -203,7 +203,7 @@ public final class HotSwapUIImpl extends HotSwapUI {
@Override
public void onFinish() {
if (progress.getMessages(MessageCategory.ERROR).isEmpty()) {
if (!progress.hasErrors()) {
statusListener.onSuccess(sessions);
}
else {
@@ -168,7 +168,7 @@ progress.hotswap.scanning.path=Scanning: {0}
progress.hotswap.scanning.classes=Scanning for classes to reload...
progress.hotswap.reloading=Reloading classes...
error.operation.canceled=Operation canceled
error.operation.not.supported.by.vm=Operation not supported by VM
error.operation.not.supported.by.vm=Operation not supported by VM : {0}
error.class.def.not.found=Class definition not found : {0}
error.verification.error=Verification error : {0}
error.unsupported.class.version=Unsupported class version : {0}
@@ -334,4 +334,5 @@ xdebugger.visualized.text.name.jwt=JWT
xdebugger.visualized.text.name.url=URL (decoded)
xdebugger.hotswap.code.changed=Code changed:
notification.group.debugger.hotswap.messages=Hotswap failed
xdebugger.hotswap.status.success=Code has been reloaded
@@ -109,6 +109,7 @@
<titleInfoProvider implementation="com.intellij.xdebugger.impl.ui.DebuggerTitleInfoProvider"/>
<notificationGroup id="Debugger messages" displayType="TOOL_WINDOW" toolWindowId="Debug" isLogByDefault="false" bundle="messages.XDebuggerBundle" key="notification.group.debugger.messages"/>
<notificationGroup id="HotSwap Messages" displayType="BALLOON" bundle="messages.XDebuggerBundle" key="notification.group.debugger.hotswap.messages"/>
<notificationGroup id="Breakpoint hit" displayType="NONE" toolWindowId="Debug" isLogByDefault="false" bundle="messages.XDebuggerBundle" key="notification.group.breakpoint.hit"/>
<notificationGroup id="Attach to Process action" displayType="BALLOON" bundle="messages.XDebuggerBundle" key="notification.group.attach.to.process"/>