don't leak progress dialog UI if PCE happens during its parent window calculation

take care to fully initialize ProgressDialog and register it in disposer after PCE
do other side-effectful stuff also after possible PCE

fixes memory leak after action update being interrupted by timeout:
	at com.intellij.openapi.util.Disposer.register(Disposer.java:93)
	at com.intellij.util.Alarm.<init>(Alarm.java:136)
	at com.intellij.util.Alarm.<init>(Alarm.java:105)
	at com.intellij.openapi.progress.util.ProgressDialog.<init>(ProgressDialog.java:40)
	at com.intellij.openapi.progress.util.ProgressWindow.<init>(ProgressWindow.java:102)
	at com.intellij.openapi.progress.util.ProgressWindow.<init>(ProgressWindow.java:84)
	at com.intellij.openapi.progress.impl.BackgroundableProcessIndicator.<init>(BackgroundableProcessIndicator.java:57)
	at com.intellij.openapi.progress.impl.BackgroundableProcessIndicator.<init>(BackgroundableProcessIndicator.java:42)
	at com.intellij.openapi.progress.impl.ProgressManagerImpl.runProcessWithProgressAsynchronously(ProgressManagerImpl.java:131)
	at com.intellij.openapi.progress.impl.CoreProgressManager.runAsynchronously(CoreProgressManager.java:328)
	at com.intellij.openapi.progress.impl.CoreProgressManager.run(CoreProgressManager.java:312)
	at com.intellij.openapi.progress.Task.queue(Task.java:115)
	at com.intellij.lang.ant.config.impl.AntConfigurationImpl.queueLater(AntConfigurationImpl.java:736)
This commit is contained in:
peter
2018-11-21 15:34:12 +01:00
parent 27903701d3
commit 8bd0ab03e5
2 changed files with 21 additions and 29 deletions
@@ -13,7 +13,6 @@ import com.intellij.openapi.ui.impl.GlassPaneDialogWrapperPeer;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.ex.WindowManagerEx;
import com.intellij.ui.PopupBorder;
import com.intellij.ui.TitlePanel;
import com.intellij.ui.WindowMoveListener;
@@ -85,22 +84,9 @@ class ProgressDialog implements Disposable {
private final SingleAlarm myDisableCancelAlarm = new SingleAlarm(this::setCancelButtonDisabledInEDT, 500, ModalityState.any(),this);
private final SingleAlarm myEnableCancelAlarm = new SingleAlarm(this::setCancelButtonEnabledInEDT, 500, ModalityState.any(),this);
ProgressDialog(@NotNull ProgressWindow progressWindow,
boolean shouldShowBackground,
@Nullable Component parent,
@Nullable Project project,
String cancelText) {
ProgressDialog(@NotNull ProgressWindow progressWindow, boolean shouldShowBackground, String cancelText, @Nullable Window parentWindow) {
myProgressWindow = progressWindow;
if (parent != null) {
myParentWindow = UIUtil.getWindow(parent);
}
else {
Window parentWindow = WindowManager.getInstance().suggestParentWindow(project);
if (parentWindow == null) {
parentWindow = WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow();
}
myParentWindow = parentWindow;
}
myParentWindow = parentWindow;
initDialog(shouldShowBackground, cancelText);
}
@@ -30,7 +30,9 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.ex.ProgressIndicatorEx;
import com.intellij.openapi.wm.ex.WindowManagerEx;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.messages.Topic;
import com.intellij.util.ui.UIUtil;
@@ -92,23 +94,27 @@ public class ProgressWindow extends ProgressIndicatorBase implements BlockingPro
myProject = project;
myShouldShowCancel = shouldShowCancel;
myCancelText = cancelText;
setModalityProgress(shouldShowBackground ? null : this);
Component parent = parentComponent;
if (parent == null && project == null && !ApplicationManager.getApplication().isHeadlessEnvironment()) {
parent = JOptionPane.getRootFrame();
}
myDialog = new ProgressDialog(this, shouldShowBackground, parent, myProject, myCancelText);
Disposer.register(this, myDialog);
addStateDelegate(new MyDelegate());
ApplicationManager.getApplication().getMessageBus().syncPublisher(TOPIC).progressWindowCreated(this);
if (myProject != null) {
Disposer.register(myProject, this);
}
myDialog = new ProgressDialog(this, shouldShowBackground, myCancelText, calcParentWindow(parentComponent));
Disposer.register(this, myDialog);
setModalityProgress(shouldShowBackground ? null : this);
addStateDelegate(new MyDelegate());
ApplicationManager.getApplication().getMessageBus().syncPublisher(TOPIC).progressWindowCreated(this);
}
private Window calcParentWindow(@Nullable Component parent) {
if (parent == null && myProject == null && !ApplicationManager.getApplication().isHeadlessEnvironment()) {
parent = JOptionPane.getRootFrame();
}
if (parent != null) {
return UIUtil.getWindow(parent);
}
Window parentWindow = WindowManager.getInstance().suggestParentWindow(myProject);
return parentWindow != null ? parentWindow : WindowManagerEx.getInstanceEx().getMostRecentFocusedWindow();
}
@Override