[platform] Task is aware of the parent JComponent; minor encapsulation improvements

GitOrigin-RevId: 454c4d94fa8cf7eb2fc293a4d72409971a6446f7
This commit is contained in:
Andrew Kozlov
2021-03-24 14:59:44 +00:00
committed by intellij-monorepo-bot
parent 7eccd82499
commit 21e12f7258
18 changed files with 235 additions and 203 deletions
@@ -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)
}
}
@@ -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, E extends Exception> T runProcessWithProgressSynchronously(@NotNull ThrowableComputable<T, E> 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.
@@ -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
@@ -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, E extends Exception> T runProcessWithProgressSynchronously(@NotNull ThrowableComputable<T, E> process,
@NotNull @ProgressTitle String progressTitle,
boolean canBeCanceled,
@Nullable Project project,
@Nullable JComponent parentComponent) throws E {
AtomicReference<T> result = new AtomicReference<>();
AtomicReference<Throwable> 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<Throwable> 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;
}
@@ -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);
}
}
@@ -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<Path, IOException> 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<Pair<? extends PluginInstallOperation, ? extends IdeaPluginDescriptor>, RuntimeException> computable = () -> {
PluginInstallOperation operation = new PluginInstallOperation(List.of(),
CustomPluginRepositoryService.getInstance()
.getCustomRepositoryPlugins(),
pluginEnabler,
ProgressManager.getInstance().getProgressIndicator());
operation.setAllowInstallWithoutRestart(true);
Task.WithResult<Pair<? extends PluginInstallOperation, ? extends IdeaPluginDescriptor>, RuntimeException> task =
new Task.WithResult<>(null,
parent,
IdeBundle.message("progress.title.checking.plugin.dependencies"),
true) {
@Override
protected @NotNull Pair<? extends PluginInstallOperation, ? extends IdeaPluginDescriptor> 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<? extends PluginInstallOperation, ? extends IdeaPluginDescriptor> pair = ProgressManager.getInstance()
.runProcessWithProgressSynchronously(computable,
IdeBundle.message("progress.title.checking.plugin.dependencies"),
true,
null,
parent);
Pair<? extends PluginInstallOperation, ? extends IdeaPluginDescriptor> pair = ProgressManager.getInstance().run(task);
PluginInstallOperation operation = pair.getFirst();
if (operation == null) {
return false;
@@ -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<TaskData> myProcessor;
@NotNull private final Object TEST_TASK_LOCK = new Object();
protected final @NlsContexts.ProgressTitle @NotNull String myTitle;
protected final @NotNull QueueProcessor<TaskData> 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<Runnable> {
}
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();
}
}
@@ -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();
@@ -74,7 +74,7 @@ public abstract class VcsBackgroundTask<T> extends Task.ConditionalModal {
@Override
public void onSuccess() {
if (!myExceptions.isEmpty()) {
AbstractVcsHelper.getInstance(myProject).showErrors(myExceptions, myTitle);
AbstractVcsHelper.getInstance(getProject()).showErrors(myExceptions, getTitle());
}
}
@@ -214,10 +214,10 @@ private class FindNewCodeSmellsTask(project: Project, private val files: List<Vi
override fun compute(indicator: ProgressIndicator): List<CodeSmellInfo> {
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
}
@@ -148,7 +148,7 @@ class TodoCheckinHandler(private val commitPanel: CheckinProjectPanel) : Checkin
private class FindTodoItemsTask(project: Project, changes: Collection<Change>, 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? {
@@ -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 {
@@ -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
@@ -101,16 +101,16 @@ private class ShowLogInDialogTask(project: Project, val roots: List<VirtualFile>
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)
@@ -182,20 +182,20 @@ internal fun updateBranches(project: Project, repositories: List<GitRepository>,
}
// 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")))
}
}
})
@@ -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();
}
@@ -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());
}
}
}
@@ -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<FilePath> 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<Change> 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();
});
}