From 21e12f7258d3394b2ac471e128effc2a65ca846b Mon Sep 17 00:00:00 2001 From: Andrew Kozlov Date: Tue, 23 Mar 2021 17:31:20 +0100 Subject: [PATCH] [platform] Task is aware of the parent JComponent; minor encapsulation improvements GitOrigin-RevId: 454c4d94fa8cf7eb2fc293a4d72409971a6446f7 --- .../util/UnknownAlternativeSdkResolver.kt | 9 +- .../openapi/progress/ProgressManager.java | 22 ---- .../com/intellij/openapi/progress/Task.java | 81 ++++++++++-- .../progress/impl/CoreProgressManager.java | 75 +++++------ .../util/SequentialModalProgressTask.java | 2 +- .../intellij/ide/plugins/PluginInstaller.java | 56 +++++---- .../openapi/progress/BackgroundTaskQueue.java | 117 +++++++++--------- .../progress/impl/ProgressManagerImpl.java | 4 +- .../intellij/util/ui/VcsBackgroundTask.java | 2 +- .../CodeAnalysisBeforeCheckinHandler.kt | 4 +- .../openapi/vcs/checkin/TodoCheckinHandler.kt | 2 +- .../intellij/vcs/commit/AbstractCommitter.kt | 2 +- .../src/git4idea/commands/GitTask.java | 6 +- .../git4idea/log/GitShowExternalLogAction.kt | 8 +- .../ui/branch/GitBranchActionsUtil.kt | 12 +- .../idea/svn/BackgroundTaskGroup.java | 4 +- .../idea/svn/actions/CleanupWorker.java | 11 +- .../integrate/SvnIntegrateChangesTask.java | 21 ++-- 18 files changed, 235 insertions(+), 203 deletions(-) diff --git a/java/execution/impl/src/com/intellij/execution/util/UnknownAlternativeSdkResolver.kt b/java/execution/impl/src/com/intellij/execution/util/UnknownAlternativeSdkResolver.kt index 218b486a6687..b5ae852bd3cc 100644 --- a/java/execution/impl/src/com/intellij/execution/util/UnknownAlternativeSdkResolver.kt +++ b/java/execution/impl/src/com/intellij/execution/util/UnknownAlternativeSdkResolver.kt @@ -14,8 +14,11 @@ import com.intellij.openapi.projectRoots.JavaSdk import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.projectRoots.impl.UnknownSdkFixAction import com.intellij.openapi.projectRoots.impl.UnknownSdkTracker -import com.intellij.openapi.roots.ui.configuration.* +import com.intellij.openapi.roots.ui.configuration.SdkLookup import com.intellij.openapi.roots.ui.configuration.SdkLookup.Companion.newLookupBuilder +import com.intellij.openapi.roots.ui.configuration.SdkLookupDecision +import com.intellij.openapi.roots.ui.configuration.SdkLookupDownloadDecision +import com.intellij.openapi.roots.ui.configuration.SdkLookupParameters import com.intellij.openapi.util.registry.Registry import com.intellij.openapi.util.text.HtmlBuilder import com.intellij.openapi.util.text.HtmlChunk @@ -64,11 +67,11 @@ class UnknownAlternativeSdkResolver(private val project: Project) { SdkLookup.getInstance().lookupBlocking(lookup as SdkLookupParameters) val fix = theFix.get() - if (theSdk.get() == null && fix != null && UnknownSdkTracker.getInstance(myProject).isAutoFixAction(fix)) { + if (theSdk.get() == null && fix != null && UnknownSdkTracker.getInstance(project).isAutoFixAction(fix)) { theFix.set(null) invokeAndWaitIfNeeded { if (project.isDisposed) return@invokeAndWaitIfNeeded - val sdk = UnknownSdkTracker.getInstance(myProject).applyAutoFixAndNotify(fix, indicator) + val sdk = UnknownSdkTracker.getInstance(project).applyAutoFixAndNotify(fix, indicator) theSdk.set(sdk) } } diff --git a/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java b/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java index df1d19d200d6..d577cec512f9 100644 --- a/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java +++ b/platform/core-api/src/com/intellij/openapi/progress/ProgressManager.java @@ -134,28 +134,6 @@ public abstract class ProgressManager extends ProgressIndicatorProvider { boolean canBeCanceled, @Nullable Project project) throws E; - /** - * Runs the specified operation in a background thread and shows a modal progress dialog in the - * main thread while the operation is executing. - * If a dialog can't be shown (e.g. under write action or in headless environment), - * runs the given operation synchronously in the calling thread. - * - * @param process the operation to execute. - * @param progressTitle the title of the progress window. - * @param canBeCanceled whether "Cancel" button is shown on the progress window. - * @param project the project in the context of which the operation is executed. - * @param parentComponent the component which will be used to calculate the progress window ancestor - * @return true result of operation - * @throws E exception thrown by process - */ - @ApiStatus.Internal - public abstract T runProcessWithProgressSynchronously(@NotNull ThrowableComputable process, - @NotNull @ProgressTitle String progressTitle, - boolean canBeCanceled, - @Nullable Project project, - @Nullable JComponent parentComponent) throws E; - - /** * Runs the specified operation in a background thread and shows a modal progress dialog in the * main thread while the operation is executing. diff --git a/platform/core-api/src/com/intellij/openapi/progress/Task.java b/platform/core-api/src/com/intellij/openapi/progress/Task.java index cdcae1382e9e..4198b147e45b 100644 --- a/platform/core-api/src/com/intellij/openapi/progress/Task.java +++ b/platform/core-api/src/com/intellij/openapi/progress/Task.java @@ -14,6 +14,8 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; + /** * Intended to run tasks, both modal and non-modal (backgroundable). * Example of use: @@ -34,15 +36,25 @@ import org.jetbrains.annotations.Nullable; public abstract class Task implements TaskInfo, Progressive { private static final Logger LOG = Logger.getInstance(Task.class); - protected final Project myProject; - protected @NlsContexts.ProgressTitle String myTitle; + protected final @Nullable Project myProject; + protected final @Nullable JComponent myParentComponent; + /** + * @deprecated Please use {@link #getTitle()} property, to be defined private. + */ + @Deprecated + @SuppressWarnings("DeprecatedIsStillUsed") + protected @NlsContexts.ProgressTitle @NotNull String myTitle; private final boolean myCanBeCancelled; private @NlsContexts.Button String myCancelText = CoreBundle.message("button.cancel"); private @NlsContexts.Tooltip String myCancelTooltipText = CoreBundle.message("button.cancel"); - private Task(@Nullable Project project, @NlsContexts.ProgressTitle @NotNull String title, boolean canBeCancelled) { + private Task(@Nullable Project project, + @Nullable JComponent parentComponent, + @NlsContexts.ProgressTitle @NotNull String title, + boolean canBeCancelled) { myProject = project; + myParentComponent = parentComponent; myTitle = title; myCanBeCancelled = canBeCancelled; } @@ -99,16 +111,21 @@ public abstract class Task implements TaskInfo, Progressive { return EdtReplacementThread.EDT_WITH_IW; } + @SuppressWarnings("NullableProblems") public final Project getProject() { return myProject; } + public final @Nullable JComponent getParentComponent() { + return myParentComponent; + } + public final void queue() { ProgressManager.getInstance().run(this); } @Override - public final @NotNull String getTitle() { + public final @NlsContexts.ProgressTitle @NotNull String getTitle() { return myTitle; } @@ -171,13 +188,17 @@ public abstract class Task implements TaskInfo, Progressive { } public abstract static class Backgroundable extends Task implements PerformInBackgroundOption { + private final @NotNull PerformInBackgroundOption myBackgroundOption; - public Backgroundable(@Nullable Project project, @NlsContexts.ProgressTitle @NotNull String title) { + public Backgroundable(@Nullable Project project, + @NlsContexts.ProgressTitle @NotNull String title) { this(project, title, true); } - public Backgroundable(@Nullable Project project, @NlsContexts.ProgressTitle @NotNull String title, boolean canBeCancelled) { + public Backgroundable(@Nullable Project project, + @NlsContexts.ProgressTitle @NotNull String title, + boolean canBeCancelled) { this(project, title, canBeCancelled, ALWAYS_BACKGROUND); } @@ -185,7 +206,15 @@ public abstract class Task implements TaskInfo, Progressive { @NlsContexts.ProgressTitle @NotNull String title, boolean canBeCancelled, @Nullable PerformInBackgroundOption backgroundOption) { - super(project, title, canBeCancelled); + this(project, null, title, canBeCancelled, backgroundOption); + } + + public Backgroundable(@Nullable Project project, + @Nullable JComponent parentComponent, + @NlsContexts.ProgressTitle @NotNull String title, + boolean canBeCancelled, + @Nullable PerformInBackgroundOption backgroundOption) { + super(project, parentComponent, title, canBeCancelled); myBackgroundOption = ObjectUtils.notNull(backgroundOption, ALWAYS_BACKGROUND); if (StringUtil.isEmptyOrSpaces(title)) { LOG.warn("Empty title for backgroundable task.", new Throwable()); @@ -214,9 +243,19 @@ public abstract class Task implements TaskInfo, Progressive { } public abstract static class Modal extends Task { - public Modal(@Nullable Project project, @NlsContexts.DialogTitle @NotNull String title, boolean canBeCancelled) { + + public Modal(@Nullable Project project, + @NlsContexts.DialogTitle @NotNull String title, + boolean canBeCancelled) { + this(project, null, title, canBeCancelled); + } + + public Modal(@Nullable Project project, + @Nullable JComponent parentComponent, + @NlsContexts.DialogTitle @NotNull String title, + boolean canBeCancelled) { //noinspection DialogTitleCapitalization - super(project, title, canBeCancelled); + super(project, parentComponent, title, canBeCancelled); } @Override @@ -226,11 +265,20 @@ public abstract class Task implements TaskInfo, Progressive { } public abstract static class ConditionalModal extends Backgroundable { + public ConditionalModal(@Nullable Project project, @NlsContexts.ProgressTitle @NotNull String title, boolean canBeCancelled, @NotNull PerformInBackgroundOption backgroundOption) { - super(project, title, canBeCancelled, backgroundOption); + this(project, null, title, canBeCancelled, backgroundOption); + } + + public ConditionalModal(@Nullable Project project, + @Nullable JComponent parentComponent, + @NlsContexts.ProgressTitle @NotNull String title, + boolean canBeCancelled, + @NotNull PerformInBackgroundOption backgroundOption) { + super(project, parentComponent, title, canBeCancelled, backgroundOption); } @Override @@ -282,8 +330,17 @@ public abstract class Task implements TaskInfo, Progressive { private volatile T myResult; private volatile Throwable myError; - public WithResult(@Nullable Project project, @NlsContexts.DialogTitle @NotNull String title, boolean canBeCancelled) { - super(project, title, canBeCancelled); + public WithResult(@Nullable Project project, + @NlsContexts.DialogTitle @NotNull String title, + boolean canBeCancelled) { + this(project, null, title, canBeCancelled); + } + + public WithResult(@Nullable Project project, + @Nullable JComponent component, + @NlsContexts.DialogTitle @NotNull String title, + boolean canBeCancelled) { + super(project, component, title, canBeCancelled); } @Override diff --git a/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java b/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java index 052612cca3ac..97904ef47e1f 100644 --- a/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java +++ b/platform/core-impl/src/com/intellij/openapi/progress/impl/CoreProgressManager.java @@ -7,12 +7,14 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.ex.ApplicationEx; +import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.application.ex.ApplicationUtil; import com.intellij.openapi.diagnostic.Attachment; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.NlsContexts; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.wm.ex.ProgressIndicatorEx; @@ -36,8 +38,6 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.LockSupport; -import static com.intellij.openapi.util.NlsContexts.ProgressTitle; - public class CoreProgressManager extends ProgressManager implements Disposable { private static final Logger LOG = Logger.getInstance(CoreProgressManager.class); @@ -253,7 +253,7 @@ public class CoreProgressManager extends ProgressManager implements Disposable { @Override public boolean runProcessWithProgressSynchronously(@NotNull Runnable process, - @NotNull @ProgressTitle String progressTitle, + @NotNull @NlsContexts.ProgressTitle String progressTitle, boolean canBeCanceled, @Nullable Project project) { return runProcessWithProgressSynchronously(process, progressTitle, canBeCanceled, project, null); @@ -264,16 +264,6 @@ public class CoreProgressManager extends ProgressManager implements Disposable { @NotNull String progressTitle, boolean canBeCanceled, @Nullable Project project) throws E { - return runProcessWithProgressSynchronously(process, progressTitle, canBeCanceled, project, null); - } - - // FROM EDT->UI: bg OR calling if can't - @Override - public T runProcessWithProgressSynchronously(@NotNull ThrowableComputable process, - @NotNull @ProgressTitle String progressTitle, - boolean canBeCanceled, - @Nullable Project project, - @Nullable JComponent parentComponent) throws E { AtomicReference result = new AtomicReference<>(); AtomicReference exception = new AtomicReference<>(); @@ -288,7 +278,7 @@ public class CoreProgressManager extends ProgressManager implements Disposable { exception.set(t); } } - }, parentComponent); + }); Throwable t = exception.get(); if (t != null) { @@ -303,23 +293,23 @@ public class CoreProgressManager extends ProgressManager implements Disposable { // FROM EDT: bg OR calling if can't @Override public boolean runProcessWithProgressSynchronously(@NotNull Runnable process, - @NotNull @ProgressTitle String progressTitle, + @NotNull @NlsContexts.DialogTitle String progressTitle, boolean canBeCanceled, @Nullable Project project, @Nullable JComponent parentComponent) { - Task.Modal task = new Task.Modal(project, progressTitle, canBeCanceled) { + Task.Modal task = new Task.Modal(project, parentComponent, progressTitle, canBeCanceled) { @Override public void run(@NotNull ProgressIndicator indicator) { process.run(); } }; - return runProcessWithProgressSynchronously(task, parentComponent); + return runProcessWithProgressSynchronously(task); } // bg; runnables on UI/EDT? @Override public void runProcessWithProgressAsynchronously(@NotNull Project project, - @NotNull @ProgressTitle String progressTitle, + @NotNull @NlsContexts.ProgressTitle String progressTitle, @NotNull Runnable process, @Nullable Runnable successRunnable, @Nullable Runnable canceledRunnable) { @@ -329,7 +319,7 @@ public class CoreProgressManager extends ProgressManager implements Disposable { // bg; runnables on UI/EDT? @Override public void runProcessWithProgressAsynchronously(@NotNull Project project, - @NotNull @ProgressTitle String progressTitle, + @NotNull @NlsContexts.ProgressTitle String progressTitle, @NotNull Runnable process, @Nullable Runnable successRunnable, @Nullable Runnable canceledRunnable, @@ -392,19 +382,19 @@ public class CoreProgressManager extends ProgressManager implements Disposable { public void run(@NotNull Task task) { if (task.isHeadless() && !shouldKeepTasksAsynchronousInHeadlessMode()) { if (SwingUtilities.isEventDispatchThread()) { - runProcessWithProgressSynchronously(task, null); + runProcessWithProgressSynchronously(task); } else { runProcessWithProgressInCurrentThread(task, new EmptyProgressIndicator(), ModalityState.defaultModalityState()); } } else if (task.isModal()) { - runSynchronously(task.asModal()); + runProcessWithProgressSynchronously(task.asModal()); } else { Task.Backgroundable backgroundable = task.asBackgroundable(); if (backgroundable.isConditionalModal() && !backgroundable.shouldStartInBackground()) { - runSynchronously(task); + runProcessWithProgressSynchronously(backgroundable); } else { runAsynchronously(backgroundable); @@ -412,11 +402,6 @@ public class CoreProgressManager extends ProgressManager implements Disposable { } } - // from any: bg or edt if can't - private void runSynchronously(@NotNull Task task) { - runProcessWithProgressSynchronously(task, null); - } - // from any: bg private void runAsynchronously(@NotNull Task.Backgroundable task) { if (ApplicationManager.getApplication().isDispatchThread()) { @@ -560,29 +545,31 @@ public class CoreProgressManager extends ProgressManager implements Disposable { // ASSERT IS EDT->UI bg or calling if cant // NEW: no assert; bg or calling ... - public boolean runProcessWithProgressSynchronously(@NotNull Task task, @Nullable JComponent parentComponent) { + protected boolean runProcessWithProgressSynchronously(@NotNull Task task) { Ref exceptionRef = new Ref<>(); - Runnable taskContainer = new TaskContainer(task) { - @Override - public void run() { - try { - startTask(task, getProgressIndicator(), null); - } - catch (ProcessCanceledException e) { - throw e; - } - catch (Throwable e) { - exceptionRef.set(e); - } + Runnable taskContainer = () -> { + try { + startTask(task, getProgressIndicator(), null); + } + catch (ProcessCanceledException e) { + throw e; + } + catch (Throwable e) { + exceptionRef.set(e); } }; - ApplicationEx application = (ApplicationEx)ApplicationManager.getApplication(); - boolean result = application.runProcessWithProgressSynchronously(taskContainer, task.getTitle(), task.isCancellable(), + ApplicationEx application = ApplicationManagerEx.getApplicationEx(); + boolean result = application.runProcessWithProgressSynchronously(taskContainer, + task.getTitle(), + task.isCancellable(), task.isModal(), - task.getProject(), parentComponent, task.getCancelText()); + task.getProject(), + task.getParentComponent(), + task.getCancelText()); - ApplicationUtil.invokeAndWaitSomewhere(task.whereToRunCallbacks(), ApplicationManager.getApplication().getDefaultModalityState(), + ApplicationUtil.invokeAndWaitSomewhere(task.whereToRunCallbacks(), + application.getDefaultModalityState(), () -> finishTask(task, !result, exceptionRef.get())); return result; } diff --git a/platform/core-impl/src/com/intellij/util/SequentialModalProgressTask.java b/platform/core-impl/src/com/intellij/util/SequentialModalProgressTask.java index cc0cad965863..fdc7a6847290 100644 --- a/platform/core-impl/src/com/intellij/util/SequentialModalProgressTask.java +++ b/platform/core-impl/src/com/intellij/util/SequentialModalProgressTask.java @@ -44,7 +44,7 @@ public class SequentialModalProgressTask extends Task.Modal { doRun(indicator); } catch (Exception e) { - LOG.info("Unexpected exception occurred during processing sequential task '" + myTitle + "'", e); + LOG.info("Unexpected exception occurred during processing sequential task '" + getTitle() + "'", e); } } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java index 19589aa9a667..56215317601e 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java @@ -15,11 +15,12 @@ import com.intellij.openapi.extensions.PluginDescriptor; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.ui.ex.MessagesEx; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.registry.Registry; @@ -155,12 +156,17 @@ public final class PluginInstaller { @Nullable JComponent parent) { Path result; try { - result = ProgressManager.getInstance() - .runProcessWithProgressSynchronously(() -> unpackPlugin(sourceFile, getPluginsPath()), - IdeBundle.message("progress.title.installing.plugin", descriptor.getName()), - false, - null, - parent); + Task.WithResult task = new Task.WithResult<>(null, + parent, + IdeBundle + .message("progress.title.installing.plugin", descriptor.getName()), + false) { + @Override + protected Path compute(@NotNull ProgressIndicator indicator) throws IOException { + return unpackPlugin(sourceFile, getPluginsPath()); + } + }; + result = ProgressManager.getInstance().run(task); } catch (Throwable throwable) { LOG.warn("Plugin " + descriptor + " failed to install without restart. " + throwable.getMessage(), throwable); @@ -254,25 +260,27 @@ public final class PluginInstaller { ? (PluginManagerMain.PluginEnabler)model : new PluginManagerMain.PluginEnabler.HEADLESS(); - ThrowableComputable, RuntimeException> computable = () -> { - PluginInstallOperation operation = new PluginInstallOperation(List.of(), - CustomPluginRepositoryService.getInstance() - .getCustomRepositoryPlugins(), - pluginEnabler, - ProgressManager.getInstance().getProgressIndicator()); - operation.setAllowInstallWithoutRestart(true); + Task.WithResult, RuntimeException> task = + new Task.WithResult<>(null, + parent, + IdeBundle.message("progress.title.checking.plugin.dependencies"), + true) { + @Override + protected @NotNull Pair compute(@NotNull ProgressIndicator indicator) { + PluginInstallOperation operation = new PluginInstallOperation(List.of(), + CustomPluginRepositoryService.getInstance() + .getCustomRepositoryPlugins(), + pluginEnabler, + ProgressManager.getInstance().getProgressIndicator()); + operation.setAllowInstallWithoutRestart(true); - return operation.checkMissingDependencies(pluginDescriptor, null) ? - Pair.create(operation, operation.checkDependenciesAndReplacements(pluginDescriptor)) : - Pair.empty(); - }; + return operation.checkMissingDependencies(pluginDescriptor, null) ? + Pair.create(operation, operation.checkDependenciesAndReplacements(pluginDescriptor)) : + Pair.empty(); + } + }; - Pair pair = ProgressManager.getInstance() - .runProcessWithProgressSynchronously(computable, - IdeBundle.message("progress.title.checking.plugin.dependencies"), - true, - null, - parent); + Pair pair = ProgressManager.getInstance().run(task); PluginInstallOperation operation = pair.getFirst(); if (operation == null) { return false; diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java b/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java index 7d1026d123bb..d5dd92f1eb70 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java @@ -9,17 +9,16 @@ import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator; import com.intellij.openapi.progress.impl.CoreProgressManager; import com.intellij.openapi.progress.impl.ProgressManagerImpl; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.NlsContexts; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.Consumer; import com.intellij.util.concurrency.QueueProcessor; -import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; +import java.util.function.Consumer; + import static com.intellij.util.concurrency.QueueProcessor.ThreadToUse; /** @@ -29,17 +28,20 @@ import static com.intellij.util.concurrency.QueueProcessor.ThreadToUse; */ @SomeQueue public class BackgroundTaskQueue { - @Nls(capitalization = Nls.Capitalization.Title) @NotNull protected final String myTitle; - @NotNull protected final QueueProcessor myProcessor; - @NotNull private final Object TEST_TASK_LOCK = new Object(); + protected final @NlsContexts.ProgressTitle @NotNull String myTitle; + protected final @NotNull QueueProcessor myProcessor; + + private final Object TEST_TASK_LOCK = new Object(); private volatile boolean myForceAsyncInTests; - public BackgroundTaskQueue(@Nullable Project project, @NlsContexts.ProgressTitle @NotNull String title) { + public BackgroundTaskQueue(@Nullable Project project, + @NlsContexts.ProgressTitle @NotNull String title) { myTitle = title; - - Condition disposeCondition = project != null ? project.getDisposed() : ApplicationManager.getApplication().getDisposed(); - myProcessor = new QueueProcessor<>(TaskData::consume, true, ThreadToUse.AWT, disposeCondition); + myProcessor = new QueueProcessor<>(TaskData::accept, + true, + ThreadToUse.AWT, + project != null ? project.getDisposed() : ApplicationManager.getApplication().getDisposed()); } public void clear() { @@ -55,54 +57,46 @@ public class BackgroundTaskQueue { } public void run(@NotNull Task.Backgroundable task) { - run(task, null, null); + run(task, ModalityState.NON_MODAL, null); } - public void run(@NotNull Task.Backgroundable task, @Nullable ModalityState modalityState, @Nullable ProgressIndicator indicator) { - BackgroundableTaskData taskData = new BackgroundableTaskData(task, modalityState, indicator); + public void run(@NotNull Task.Backgroundable task, + @NotNull ModalityState modalityState, + @Nullable ProgressIndicator indicator) { if (!myForceAsyncInTests && ApplicationManager.getApplication().isUnitTestMode()) { - runTaskInCurrentThread(taskData); + // prohibit simultaneous execution from different threads + synchronized (TEST_TASK_LOCK) { + getProgressManager().runProcessWithProgressInCurrentThread(task, + indicator != null ? indicator : new EmptyProgressIndicator(), + modalityState); + } } else { + BackgroundableTaskData taskData = new BackgroundableTaskData(task, + modalityState, + indicator); myProcessor.add(taskData, modalityState); } } - @TestOnly public void setForceAsyncInTests(boolean value, @NotNull Disposable disposable) { myForceAsyncInTests = value; Disposer.register(disposable, () -> myForceAsyncInTests = false); } - private void runTaskInCurrentThread(@NotNull BackgroundableTaskData data) { - Task.Backgroundable task = data.myTask; - - ProgressIndicator indicator = data.myIndicator; - if (indicator == null) indicator = new EmptyProgressIndicator(); - - ModalityState modalityState = data.myModalityState; - if (modalityState == null) modalityState = ModalityState.NON_MODAL; - - ProgressManagerImpl pm = (ProgressManagerImpl)ProgressManager.getInstance(); - - // prohibit simultaneous execution from different threads - synchronized (TEST_TASK_LOCK) { - pm.runProcessWithProgressInCurrentThread(task, indicator, modalityState); - } - } - @FunctionalInterface protected interface TaskData extends Consumer { } - protected class BackgroundableTaskData implements TaskData { - @NotNull private final Task.Backgroundable myTask; - @Nullable private final ModalityState myModalityState; - @Nullable private final ProgressIndicator myIndicator; + private final class BackgroundableTaskData implements TaskData { + + private final @NotNull Task.Backgroundable myTask; + private final @NotNull ModalityState myModalityState; + private final @Nullable ProgressIndicator myIndicator; BackgroundableTaskData(@NotNull Task.Backgroundable task, - @Nullable ModalityState modalityState, + @NotNull ModalityState modalityState, @Nullable ProgressIndicator indicator) { myTask = task; myModalityState = modalityState; @@ -110,46 +104,47 @@ public class BackgroundTaskQueue { } @Override - public void consume(@NotNull Runnable continuation) { - Task.Backgroundable task = myTask; - Project taskProject = task.getProject(); + public void accept(@NotNull Runnable continuation) { + Project taskProject = myTask.getProject(); if (taskProject != null && taskProject.isDisposed()) { continuation.run(); return; } - ProgressIndicator indicator = myIndicator; - if (indicator == null) { - if (ApplicationManager.getApplication().isHeadlessEnvironment()) { - indicator = new EmptyProgressIndicator(); - } - else { - // BackgroundableProcessIndicator should be created from EDT - indicator = new BackgroundableProcessIndicator(task); - } + + if (StringUtil.isEmptyOrSpaces(myTask.getTitle())) { + myTask.setTitle(myTitle); } - ModalityState modalityState = myModalityState; - if (modalityState == null) modalityState = ModalityState.NON_MODAL; + boolean synchronous = + myTask.isHeadless() && !CoreProgressManager.shouldKeepTasksAsynchronousInHeadlessMode() && !myForceAsyncInTests || + myTask.isConditionalModal() && !myTask.shouldStartInBackground(); - if (StringUtil.isEmptyOrSpaces(task.getTitle())) { - task.setTitle(myTitle); - } - - boolean synchronous = task.isHeadless() && !CoreProgressManager.shouldKeepTasksAsynchronousInHeadlessMode() && !myForceAsyncInTests || - task.isConditionalModal() && !task.shouldStartInBackground(); - - ProgressManagerImpl pm = (ProgressManagerImpl)ProgressManager.getInstance(); if (synchronous) { try { - pm.runProcessWithProgressSynchronously(task, null); + getProgressManager().runProcessWithProgressSynchronously(myTask); } finally { continuation.run(); } } else { - pm.runProcessWithProgressAsynchronously(task, indicator, continuation, modalityState); + getProgressManager().runProcessWithProgressAsynchronously(myTask, + getIndicator(), + continuation, + myModalityState); } } + + private @NotNull ProgressIndicator getIndicator() { + return myIndicator != null ? + myIndicator : + ApplicationManager.getApplication().isHeadlessEnvironment() ? + new EmptyProgressIndicator() : + new BackgroundableProcessIndicator(myTask); // BackgroundableProcessIndicator should be created from EDT + } + } + + private static @NotNull ProgressManagerImpl getProgressManager() { + return (ProgressManagerImpl)ProgressManager.getInstance(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java index 99a77ac69c4b..58773617dd3b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java @@ -84,9 +84,9 @@ public class ProgressManagerImpl extends CoreProgressManager implements Disposab } @Override - public boolean runProcessWithProgressSynchronously(@NotNull Task task, @Nullable JComponent parentComponent) { + public boolean runProcessWithProgressSynchronously(@NotNull Task task) { long start = System.currentTimeMillis(); - boolean result = super.runProcessWithProgressSynchronously(task, parentComponent); + boolean result = super.runProcessWithProgressSynchronously(task); if (result) { long end = System.currentTimeMillis(); Task.NotificationInfo notificationInfo = task.notifyFinished(); diff --git a/platform/vcs-api/src/com/intellij/util/ui/VcsBackgroundTask.java b/platform/vcs-api/src/com/intellij/util/ui/VcsBackgroundTask.java index 887f7b9fcb63..66e5755c473b 100644 --- a/platform/vcs-api/src/com/intellij/util/ui/VcsBackgroundTask.java +++ b/platform/vcs-api/src/com/intellij/util/ui/VcsBackgroundTask.java @@ -74,7 +74,7 @@ public abstract class VcsBackgroundTask extends Task.ConditionalModal { @Override public void onSuccess() { if (!myExceptions.isEmpty()) { - AbstractVcsHelper.getInstance(myProject).showErrors(myExceptions, myTitle); + AbstractVcsHelper.getInstance(getProject()).showErrors(myExceptions, getTitle()); } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/CodeAnalysisBeforeCheckinHandler.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/CodeAnalysisBeforeCheckinHandler.kt index 5ee9df26d97e..3ca2b8dd28b6 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/CodeAnalysisBeforeCheckinHandler.kt +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/CodeAnalysisBeforeCheckinHandler.kt @@ -214,10 +214,10 @@ private class FindNewCodeSmellsTask(project: Project, private val files: List { indicator.isIndeterminate = true - val codeSmells = CodeAnalysisBeforeCheckinShowOnlyNew.runAnalysis(myProject!!, files, indicator) + val codeSmells = CodeAnalysisBeforeCheckinShowOnlyNew.runAnalysis(project, files, indicator) indicator.text = message("before.checkin.waiting.for.smart.mode") - DumbService.getInstance(myProject).waitForSmartMode() + DumbService.getInstance(project).waitForSmartMode() return codeSmells } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.kt b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.kt index c142f998b5a2..45d95bb5f3bc 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.kt +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.kt @@ -148,7 +148,7 @@ class TodoCheckinHandler(private val commitPanel: CheckinProjectPanel) : Checkin private class FindTodoItemsTask(project: Project, changes: Collection, todoFilter: TodoFilter?) : Task.Modal(project, message("checkin.dialog.title.looking.for.new.edited.todo.items"), true) { - private val worker = TodoCheckinHandlerWorker(myProject, changes, todoFilter) + private val worker = TodoCheckinHandlerWorker(project, changes, todoFilter) private var result: TodoCheckinHandlerWorker? = null fun find(): TodoCheckinHandlerWorker? { diff --git a/platform/vcs-impl/src/com/intellij/vcs/commit/AbstractCommitter.kt b/platform/vcs-impl/src/com/intellij/vcs/commit/AbstractCommitter.kt index 8b930fa1b642..1bbc3c144a5d 100644 --- a/platform/vcs-impl/src/com/intellij/vcs/commit/AbstractCommitter.kt +++ b/platform/vcs-impl/src/com/intellij/vcs/commit/AbstractCommitter.kt @@ -48,7 +48,7 @@ abstract class AbstractCommitter( fun runCommit(taskName: @Nls String, sync: Boolean) { val task = object : Task.Backgroundable(project, taskName, true, configuration.commitOption) { override fun run(indicator: ProgressIndicator) { - val vcsManager = ProjectLevelVcsManager.getInstance(myProject) + val vcsManager = ProjectLevelVcsManager.getInstance(project) val activity = IdeActivity.started(myProject, "vcs", "commit") // NON-NLS vcsManager.startBackgroundVcsOperation() try { diff --git a/plugins/git4idea/src/git4idea/commands/GitTask.java b/plugins/git4idea/src/git4idea/commands/GitTask.java index ddce880e0290..b5bcee7c38a1 100644 --- a/plugins/git4idea/src/git4idea/commands/GitTask.java +++ b/plugins/git4idea/src/git4idea/commands/GitTask.java @@ -281,7 +281,7 @@ public class GitTask { private void justRun() { String oldTitle = myProgressIndicator.getText(); - myProgressIndicator.setText(myTitle); + myProgressIndicator.setText(getTitle()); myDelegate.run(myProgressIndicator); myProgressIndicator.setText(oldTitle); if (myProgressIndicator.isCanceled()) { @@ -294,7 +294,7 @@ public class GitTask { @Override public void execute(ProgressIndicator indicator) { addListeners(this, indicator); - GitHandlerUtil.runInCurrentThread(myHandler, indicator, false, myTitle); + GitHandlerUtil.runInCurrentThread(myHandler, indicator, false, getTitle()); } @Override @@ -319,7 +319,7 @@ public class GitTask { @Override public void execute(ProgressIndicator indicator) { addListeners(this, indicator); - GitHandlerUtil.runInCurrentThread(myHandler, indicator, false, myTitle); + GitHandlerUtil.runInCurrentThread(myHandler, indicator, false, getTitle()); } @Override diff --git a/plugins/git4idea/src/git4idea/log/GitShowExternalLogAction.kt b/plugins/git4idea/src/git4idea/log/GitShowExternalLogAction.kt index fb558b0f3d0d..0361928ab5db 100644 --- a/plugins/git4idea/src/git4idea/log/GitShowExternalLogAction.kt +++ b/plugins/git4idea/src/git4idea/log/GitShowExternalLogAction.kt @@ -101,16 +101,16 @@ private class ShowLogInDialogTask(project: Project, val roots: List Backgroundable(project, GitBundle.message( "git.log.external.loading.process"), true) { override fun run(indicator: ProgressIndicator) { - if (!GitExecutableManager.getInstance().testGitExecutableVersionValid(myProject)) { + if (!GitExecutableManager.getInstance().testGitExecutableVersionValid(project)) { throw ProcessCanceledException() } } override fun onSuccess() { - if (!myProject.isDisposed) { - val content = createManagerAndContent(myProject, vcs, roots, false) + if (!project.isDisposed) { + val content = createManagerAndContent(project, vcs, roots, false) val window = WindowWrapperBuilder(WindowWrapper.Mode.FRAME, content) - .setProject(myProject) + .setProject(project) .setTitle(GitBundle.message("git.log.external.window.title")) .setPreferredFocusedComponent(content) .setDimensionServiceKey(GitShowExternalLogAction::class.java.name) diff --git a/plugins/git4idea/src/git4idea/ui/branch/GitBranchActionsUtil.kt b/plugins/git4idea/src/git4idea/ui/branch/GitBranchActionsUtil.kt index fe7d9c42e901..37b97f830605 100644 --- a/plugins/git4idea/src/git4idea/ui/branch/GitBranchActionsUtil.kt +++ b/plugins/git4idea/src/git4idea/ui/branch/GitBranchActionsUtil.kt @@ -182,20 +182,20 @@ internal fun updateBranches(project: Project, repositories: List, } // Update all current branches in the selection if (currentBranchesMap.isNotEmpty()) { - GitUpdateExecutionProcess(myProject, + GitUpdateExecutionProcess(project, repositories, currentBranchesMap, - GitVcsSettings.getInstance(myProject).updateMethod, + GitVcsSettings.getInstance(project).updateMethod, false).execute() } } override fun onSuccess() { if (successfullyUpdated.isNotEmpty()) { - VcsNotifier.getInstance(myProject).notifySuccess(BRANCHES_UPDATE_SUCCESSFUL, "", - GitBundle.message("branches.selected.branches.updated.title", - successfullyUpdated.size, - successfullyUpdated.joinToString("\n"))) + VcsNotifier.getInstance(project).notifySuccess(BRANCHES_UPDATE_SUCCESSFUL, "", + GitBundle.message("branches.selected.branches.updated.title", + successfullyUpdated.size, + successfullyUpdated.joinToString("\n"))) } } }) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/BackgroundTaskGroup.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/BackgroundTaskGroup.java index 009ac50f8b42..e35064d77695 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/BackgroundTaskGroup.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/BackgroundTaskGroup.java @@ -39,7 +39,9 @@ public class BackgroundTaskGroup extends BackgroundTaskQueue { } @Override - public void run(@NotNull Task.Backgroundable task, @Nullable ModalityState modalityState, @Nullable ProgressIndicator indicator) { + public void run(@NotNull Task.Backgroundable task, + @NotNull ModalityState modalityState, + @Nullable ProgressIndicator indicator) { throw new UnsupportedOperationException(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CleanupWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CleanupWorker.java index 708996d2da4c..1a6ce2e8d1ca 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CleanupWorker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CleanupWorker.java @@ -79,23 +79,24 @@ public class CleanupWorker extends Task.Backgroundable { @Override public void onSuccess() { - if (myProject.isDisposed()) return; + assert getProject() != null; + if (getProject().isDisposed()) return; getApplication().invokeLater(() -> getApplication().runWriteAction(() -> { - if (!myProject.isDisposed()) { + if (!getProject().isDisposed()) { LocalFileSystem.getInstance().refreshFiles(myRoots, false, true, null); } })); - markFilesDirty(myProject, myRoots); + markFilesDirty(getProject(), myRoots); if (!myExceptions.isEmpty()) { - AbstractVcsHelper.getInstance(myProject).showErrors( + AbstractVcsHelper.getInstance(getProject()).showErrors( myExceptions.stream() .map(pair -> new VcsException( message("action.Subversion.cleanup.error.message", toSystemDependentName(pair.second.getPath()), pair.first == null ? "" : pair.first.getMessage()))) .collect(toList()), - myTitle); + getTitle()); } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java index d95abf360731..53621b3afb43 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesTask.java @@ -153,7 +153,7 @@ public class SvnIntegrateChangesTask extends Task.Backgroundable { } private void onTaskFinished(boolean wasCancelled) { - TransactionGuard.submitTransaction(myProject, () -> { + TransactionGuard.submitTransaction(getProject(), () -> { try { afterExecution(wasCancelled); } @@ -178,7 +178,7 @@ public class SvnIntegrateChangesTask extends Task.Backgroundable { if ((!myMerger.hasNext()) || haveConflicts || (!myExceptions.isEmpty()) || myAccumulatedFiles.containErrors() || wasCanceled) { initMergeTarget(); if (myAccumulatedFiles.isEmpty() && myExceptions.isEmpty() && (myMergeTarget == null) && (!wasCanceled)) { - Messages.showMessageDialog(message("action.Subversion.integrate.changes.message.files.up.to.date.text"), myTitle, + Messages.showMessageDialog(message("action.Subversion.integrate.changes.message.files.up.to.date.text"), getTitle(), Messages.getInformationIcon()); } else { if (haveConflicts) { @@ -210,7 +210,7 @@ public class SvnIntegrateChangesTask extends Task.Backgroundable { } final Collection files = gatherChangedPaths(); - VcsDirtyScopeManager.getInstance(myProject).filePathsDirty(files, null); + VcsDirtyScopeManager.getInstance(getProject()).filePathsDirty(files, null); prepareAndShowResults(); } @@ -226,11 +226,12 @@ public class SvnIntegrateChangesTask extends Task.Backgroundable { } private void showUpdateTree() { - RestoreUpdateTree restoreUpdateTree = RestoreUpdateTree.getInstance(myProject); + RestoreUpdateTree restoreUpdateTree = RestoreUpdateTree.getInstance(getProject()); // action info is actually NOT used restoreUpdateTree.registerUpdateInformation(myAccumulatedFiles.getUpdatedFiles(), INTEGRATE); - UpdateInfoTree tree = myProjectLevelVcsManager.showUpdateProjectInfo(myAccumulatedFiles.getUpdatedFiles(), myTitle, INTEGRATE, false); - if (tree != null) ViewUpdateInfoNotification.focusUpdateInfoTree(myProject, tree); + UpdateInfoTree tree = + myProjectLevelVcsManager.showUpdateProjectInfo(myAccumulatedFiles.getUpdatedFiles(), getTitle(), INTEGRATE, false); + if (tree != null) ViewUpdateInfoNotification.focusUpdateInfoTree(getProject(), tree); } private void stepToNextChangeList() { @@ -255,15 +256,15 @@ public class SvnIntegrateChangesTask extends Task.Backgroundable { // for changes to be detected, we need switch to background change list manager update thread and back to dispatch thread // so callback is used; ok to be called after VCS update markup closed: no remote operations - VcsDirtyScopeManager.getInstance(myProject).filePathsDirty(files, null); - final ChangeListManager changeListManager = ChangeListManager.getInstance(myProject); - changeListManager.invokeAfterUpdateWithModal(true, myTitle, () -> { + VcsDirtyScopeManager.getInstance(getProject()).filePathsDirty(files, null); + final ChangeListManager changeListManager = ChangeListManager.getInstance(getProject()); + changeListManager.invokeAfterUpdateWithModal(true, getTitle(), () -> { Collection changes = new ArrayList<>(); for (FilePath file : files) { ContainerUtil.addIfNotNull(changes, changeListManager.getChange(file)); } - CommitChangeListDialog.commitChanges(myProject, changes, null, null, myMerger.getComment()); + CommitChangeListDialog.commitChanges(getProject(), changes, null, null, myMerger.getComment()); prepareAndShowResults(); }); }