diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java index 53ad8ab2385e..23a6eaea4caa 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java @@ -64,7 +64,10 @@ import com.sun.jdi.request.EventRequest; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class DebuggerSession implements AbstractDebuggerSession { private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.impl.DebuggerSession"); @@ -104,6 +107,8 @@ public class DebuggerSession implements AbstractDebuggerSession { private final Set mySteppingThroughThreads = new HashSet(); protected final Alarm myUpdateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); + private boolean myModifiedClassesScanRequired = false; + public boolean isSteppingThrough(ThreadReferenceProxyImpl threadProxy) { return mySteppingThroughThreads.contains(threadProxy); } @@ -114,6 +119,14 @@ public class DebuggerSession implements AbstractDebuggerSession { return mySearchScope; } + public boolean isModifiedClassesScanRequired() { + return myModifiedClassesScanRequired; + } + + public void setModifiedClassesScanRequired(boolean modifiedClassesScanRequired) { + myModifiedClassesScanRequired = modifiedClassesScanRequired; + } + private class MyDebuggerStateManager extends DebuggerStateManager { private DebuggerContextImpl myDebuggerContext; @@ -192,21 +205,6 @@ public class DebuggerSession implements AbstractDebuggerSession { return myDebugProcess; } - private final Map myDelayedHotswapFiles = new HashMap(); - - public void addHotswapFiles(Map files) { - myDelayedHotswapFiles.putAll(files); - } - - @NotNull - public Map getHotswapFiles() { - return Collections.unmodifiableMap(myDelayedHotswapFiles); - } - - public void clearHotswapFiles() { - myDelayedHotswapFiles.clear(); - } - private static class DebuggerSessionState { final int myState; final String myDescription; diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/HotSwapManager.java b/java/debugger/impl/src/com/intellij/debugger/impl/HotSwapManager.java index 05e9422fa94d..b7cd3f9ef9a1 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/HotSwapManager.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/HotSwapManager.java @@ -35,7 +35,6 @@ import org.jetbrains.annotations.NotNull; import java.io.File; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Map; @@ -155,11 +154,10 @@ public class HotSwapManager extends AbstractProjectComponent { return project.getComponent(HotSwapManager.class); } - private void reloadClasses(DebuggerSession session, HotSwapProgress progress) { + private void reloadClasses(DebuggerSession session, Map classesToReload, HotSwapProgress progress) { final long newSwapTime = System.currentTimeMillis(); - new ReloadClassesWorker(session, progress).reloadClasses(); + new ReloadClassesWorker(session, progress).reloadClasses(classesToReload); setTimeStamp(session, newSwapTime); - session.clearHotswapFiles(); } public static Map> findModifiedClasses(List sessions, Map> generatedPaths) { @@ -225,7 +223,7 @@ public class HotSwapManager extends AbstractProjectComponent { return swapProgress.isCancelled() ? new HashMap>() : modifiedClasses; } - public static void reloadModifiedClasses(final Collection sessions, final HotSwapProgress reloadClassesProgress) { + public static void reloadModifiedClasses(final Map> modifiedClasses, final HotSwapProgress reloadClassesProgress) { final MultiProcessCommand reloadClassesCommand = new MultiProcessCommand(); reloadClassesProgress.setCancelWorker(new Runnable() { @@ -234,11 +232,13 @@ public class HotSwapManager extends AbstractProjectComponent { } }); - for (final DebuggerSession debuggerSession : sessions) { + for (final DebuggerSession debuggerSession : modifiedClasses.keySet()) { reloadClassesCommand.addCommand(debuggerSession.getProcess(), new DebuggerCommandImpl() { protected void action() throws Exception { reloadClassesProgress.setDebuggerSession(debuggerSession); - getInstance(reloadClassesProgress.getProject()).reloadClasses(debuggerSession, reloadClassesProgress); + getInstance(reloadClassesProgress.getProject()).reloadClasses( + debuggerSession, modifiedClasses.get(debuggerSession), reloadClassesProgress + ); } }); } diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java index 88ea2fabb6c0..d8d8dd469c43 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/ReloadClassesWorker.java @@ -90,12 +90,10 @@ class ReloadClassesWorker { } } - public void reloadClasses() { + public void reloadClasses(final Map modifiedClasses) { DebuggerManagerThreadImpl.assertIsManagerThread(); - final Map modifiedClasses = myDebuggerSession.getHotswapFiles(); - - if(modifiedClasses.isEmpty()) { + if(modifiedClasses == null || modifiedClasses.size() == 0) { myProgress.addMessage(myDebuggerSession, MessageCategory.INFORMATION, DebuggerBundle.message("status.hotswap.loaded.classes.up.to.date")); return; } 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 8825676c2cf0..e4c0f5dfc52c 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/HotSwapUIImpl.java @@ -149,47 +149,68 @@ public class HotSwapUIImpl extends HotSwapUI implements ProjectComponent{ final boolean isOutOfProcessMode = CompilerWorkspaceConfiguration.getInstance(myProject).useOutOfProcessBuild(); final boolean shouldPerformScan = !isOutOfProcessMode || generatedPaths == null; - final HotSwapProgressImpl findClassesProgress = shouldPerformScan ? new HotSwapProgressImpl(myProject) : null; - + final HotSwapProgressImpl findClassesProgress; + if (shouldPerformScan) { + findClassesProgress = new HotSwapProgressImpl(myProject); + } + else { + boolean createProgress = false; + for (DebuggerSession session : sessions) { + if (session.isModifiedClassesScanRequired()) { + createProgress = true; + break; + } + } + findClassesProgress = createProgress? new HotSwapProgressImpl(myProject) : null; + } + ApplicationManager.getApplication().executeOnPooledThread(new Runnable() { public void run() { - final Map> newlyModifiedClasses = shouldPerformScan? - scanForModifiedClassesWithProgress(sessions, findClassesProgress, !isOutOfProcessMode) : - HotSwapManager.findModifiedClasses(sessions, generatedPaths); - - for (Map.Entry> entry : newlyModifiedClasses.entrySet()) { - final DebuggerSession session = entry.getKey(); - if (shouldPerformScan) { - session.clearHotswapFiles(); - } - session.addHotswapFiles(entry.getValue()); + final Map> modifiedClasses; + if (shouldPerformScan) { + modifiedClasses = scanForModifiedClassesWithProgress(sessions, findClassesProgress, !isOutOfProcessMode); } - - boolean hasFilesToReload = false; - for (DebuggerSession session : sessions) { - if (!session.getHotswapFiles().isEmpty()) { - hasFilesToReload = true; - break; + else { + final List toScan = new ArrayList(); + final List toUseGenerated = new ArrayList(); + for (DebuggerSession session : sessions) { + (session.isModifiedClassesScanRequired()? toScan : toUseGenerated).add(session); + session.setModifiedClassesScanRequired(false); + } + modifiedClasses = new HashMap>(); + if (!toUseGenerated.isEmpty()) { + modifiedClasses.putAll(HotSwapManager.findModifiedClasses(toUseGenerated, generatedPaths)); + } + if (!toScan.isEmpty()) { + modifiedClasses.putAll(scanForModifiedClassesWithProgress(toScan, findClassesProgress, !isOutOfProcessMode)); } } - if (!hasFilesToReload) { + + final Application application = ApplicationManager.getApplication(); + if (modifiedClasses.isEmpty()) { final String message = DebuggerBundle.message("status.hotswap.uptodate"); HotSwapProgressImpl.NOTIFICATION_GROUP.createNotification(message, NotificationType.INFORMATION).notify(myProject); return; } - final Set sessionsToReload = new HashSet(sessions); - - final Application application = ApplicationManager.getApplication(); application.invokeLater(new Runnable() { public void run() { if (shouldAskBeforeHotswap && !DebuggerSettings.RUN_HOTSWAP_ALWAYS.equals(runHotswap)) { final RunHotswapDialog dialog = new RunHotswapDialog(myProject, sessions, shouldDisplayHangWarning); dialog.show(); if (!dialog.isOK()) { + for (DebuggerSession session : modifiedClasses.keySet()) { + session.setModifiedClassesScanRequired(true); + } return; } - sessionsToReload.retainAll(dialog.getSessionsToReload()); + final Set toReload = new HashSet(dialog.getSessionsToReload()); + for (DebuggerSession session : modifiedClasses.keySet()) { + if (!toReload.contains(session)) { + session.setModifiedClassesScanRequired(true); + } + } + modifiedClasses.keySet().retainAll(toReload); } else { if (shouldDisplayHangWarning) { @@ -208,16 +229,19 @@ public class HotSwapUIImpl extends HotSwapUI implements ProjectComponent{ } ); if (answer == DialogWrapper.CANCEL_EXIT_CODE) { + for (DebuggerSession session : modifiedClasses.keySet()) { + session.setModifiedClassesScanRequired(true); + } return; } } } - if (!sessionsToReload.isEmpty()) { + if (!modifiedClasses.isEmpty()) { final HotSwapProgressImpl progress = new HotSwapProgressImpl(myProject); application.executeOnPooledThread(new Runnable() { public void run() { - reloadModifiedClasses(sessionsToReload, progress); + reloadModifiedClasses(modifiedClasses, progress); } }); } @@ -242,10 +266,10 @@ public class HotSwapUIImpl extends HotSwapUI implements ProjectComponent{ return result.get(); } - private static void reloadModifiedClasses(final Collection sessions, final HotSwapProgressImpl progress) { + private static void reloadModifiedClasses(final Map> modifiedClasses, final HotSwapProgressImpl progress) { ProgressManager.getInstance().runProcess(new Runnable() { public void run() { - HotSwapManager.reloadModifiedClasses(sessions, progress); + HotSwapManager.reloadModifiedClasses(modifiedClasses, progress); progress.finished(); } }, progress.getProgressIndicator());