void (@NotNull List<DebuggerSession> sessions, @Nullable Map<String, Collection<String>> generatedPaths, @Nullable NotNullLazyValue<List<String>> outputPaths, @Nullable HotSwapStatusListener callback) { boolean shouldAskBeforeHotswap = myAskBeforeHotswap; myAskBeforeHotswap = true; DebuggerSettings settings = DebuggerSettings.getInstance(); String runHotswap = settings.RUN_HOTSWAP_AFTER_COMPILE; boolean shouldDisplayHangWarning = shouldDisplayHangWarning(settings, sessions); HotSwapStatusListener statusListener = makeNullSafe(callback); if (shouldAskBeforeHotswap && DebuggerSettings.RUN_HOTSWAP_NEVER.equals(runHotswap)) { statusListener.onCancel(sessions); return; } List<DebuggerSession> toScan = new ArrayList<>(sessions); // by default scan all sessions List<DebuggerSession> toUseGenerated = new ArrayList<>(); if (generatedPaths != null) { toScan.clear(); for (DebuggerSession session : sessions) { if (session.isModifiedClassesScanRequired()) { toScan.add(session); } else { toUseGenerated.add(session); } session.setModifiedClassesScanRequired(false); } } HotSwapProgressImpl findClassesProgress = !toScan.isEmpty() ? createHotSwapProgress(statusListener, sessions) : null; HotSwapProgressImpl outputPathsProgress = !toUseGenerated.isEmpty() && outputPaths != null ? createHotSwapProgress(statusListener, sessions) : null; ApplicationManager.getApplication().executeOnPooledThread(() -> { Map<DebuggerSession, Map<String, HotSwapFile>> modifiedClasses = new HashMap<>(); if (!toUseGenerated.isEmpty()) { modifiedClasses.putAll(HotSwapManager.findModifiedClasses(toUseGenerated, generatedPaths)); if (outputPathsProgress != null) { scanForModifiedClassesWithProgress(toUseGenerated, outputPaths, outputPathsProgress) .forEach( (session, map) -> modifiedClasses.merge(session, map, (map1, map2) -> { map1.putAll(map2); return map1; }) ); } } if (findClassesProgress != null) { modifiedClasses.putAll(scanForModifiedClassesWithProgress(toScan, null, findClassesProgress)); } if (modifiedClasses.isEmpty()) { String message = JavaDebuggerBundle.message("status.hotswap.uptodate"); HotSwapProgressImpl.NOTIFICATION_GROUP.createNotification(message, NotificationType.INFORMATION).notify(myProject); statusListener.onSuccess(sessions); return; } ApplicationManager.getApplication().invokeLater(() -> { if (shouldAskBeforeHotswap && !DebuggerSettings.RUN_HOTSWAP_ALWAYS.equals(runHotswap)) { RunHotswapDialog dialog = new RunHotswapDialog(myProject, sessions, shouldDisplayHangWarning); if (!dialog.showAndGet()) { for (DebuggerSession session : modifiedClasses.keySet()) { session.setModifiedClassesScanRequired(true); } statusListener.onCancel(sessions); return; } Set<DebuggerSession> toReload = new HashSet<>(dialog.getSessionsToReload()); for (DebuggerSession session : modifiedClasses.keySet()) { if (!toReload.contains(session)) { session.setModifiedClassesScanRequired(true); } } modifiedClasses.keySet().retainAll(toReload); } else if (shouldDisplayHangWarning && !confirmPossibleHang(settings)) { for (DebuggerSession session : modifiedClasses.keySet()) { session.setModifiedClassesScanRequired(true); } statusListener.onCancel(sessions); return; } if (modifiedClasses.isEmpty()) { return; // Without calling onCancel. } HotSwapProgressImpl progress = new HotSwapProgressImpl(myProject); if (modifiedClasses.keySet().size() == 1) { progress.setSessionForActions(ContainerUtil.getFirstItem(modifiedClasses.keySet())); } progress.addProgressListener(delegatingTo(statusListener, sessions, progress)); ApplicationManager.getApplication().executeOnPooledThread( () -> reloadModifiedClasses(modifiedClasses, progress) ); }, ModalityState.nonModal()); }); }