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 cd9be62a8b55..97597d6ff881 100644 --- a/platform/core-api/src/com/intellij/openapi/progress/Task.java +++ b/platform/core-api/src/com/intellij/openapi/progress/Task.java @@ -61,19 +61,32 @@ public abstract class Task implements TaskInfo, Progressive { /** * This callback will be invoked on AWT dispatch thread. + * + * Callback executed when run() throws {@link ProcessCanceledException} or if its {@link ProgressIndicator} was canceled. */ public void onCancel() { - onFinished(); } /** * This callback will be invoked on AWT dispatch thread. */ public void onSuccess() { - onFinished(); } - protected void onFinished() {} + /** + * This callback will be invoked on AWT dispatch thread. + * + * Callback executed when run() throws an exception (except PCE). + */ + public void onError(@NotNull Exception error) { + LOG.error(error); + } + + /** + * This callback will be invoked on AWT dispatch thread, after other specific handlers + */ + public void onFinished() { + } public final Project getProject() { return myProject; 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 33dd9b4667ed..b8c85d28034e 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 @@ -344,30 +344,27 @@ public class CoreProgressManager extends ProgressManager implements Disposable { Runnable action = new TaskContainer(task) { @Override public void run() { - boolean canceled = false; + boolean processCanceled = false; + Exception exception = null; try { ProgressManager.getInstance().runProcess(process, progressIndicator); } catch (ProcessCanceledException e) { - canceled = true; + processCanceled = true; + } + catch (Exception e) { + exception = e; } - if (canceled || progressIndicator.isCanceled()) { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - task.onCancel(); - } - }, modalityState); - } - else { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - task.onSuccess(); - } - }, modalityState); - } + final boolean finalCanceled = processCanceled || progressIndicator.isCanceled(); + final Exception finalException = exception; + + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + finishTask(task, finalCanceled, finalException); + } + }, modalityState); } }; @@ -375,22 +372,47 @@ public class CoreProgressManager extends ProgressManager implements Disposable { } protected boolean runProcessWithProgressSynchronously(@NotNull final Task task, @Nullable final JComponent parentComponent) { - final boolean result = ((ApplicationEx)ApplicationManager.getApplication()) - .runProcessWithProgressSynchronously(new TaskContainer(task) { - @Override - public void run() { - new TaskRunnable(task, ProgressManager.getInstance().getProgressIndicator()).run(); - } - }, task.getTitle(), task.isCancellable(), task.getProject(), parentComponent, task.getCancelText()); - if (result) { - task.onSuccess(); - } - else { - task.onCancel(); - } + final Ref exceptionRef = new Ref(); + TaskContainer taskContainer = new TaskContainer(task) { + @Override + public void run() { + try { + new TaskRunnable(task, ProgressManager.getInstance().getProgressIndicator()).run(); + } + catch (ProcessCanceledException e) { + throw e; + } + catch (Exception e) { + exceptionRef.set(e); + } + } + }; + + ApplicationEx application = (ApplicationEx)ApplicationManager.getApplication(); + boolean result = application.runProcessWithProgressSynchronously(taskContainer, task.getTitle(), task.isCancellable(), + task.getProject(), parentComponent, task.getCancelText()); + + finishTask(task, !result, exceptionRef.get()); return result; } + protected static void finishTask(@NotNull Task task, boolean canceled, @Nullable Exception exception) { + try { + if (exception != null) { + task.onError(exception); + } + else if (canceled) { + task.onCancel(); + } + else { + task.onSuccess(); + } + } + finally { + task.onFinished(); + } + } + @Override public void runProcessWithProgressAsynchronously(@NotNull Task.Backgroundable task, @NotNull ProgressIndicator progressIndicator) { runProcessWithProgressAsynchronously(task, progressIndicator, null); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java index 58481a2c591c..d171512b0031 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/BackgroundUpdaterTask.java @@ -136,13 +136,12 @@ public abstract class BackgroundUpdaterTask extends Task.Backgroundable { @Override public void onSuccess() { - onFinished(); myPopup.setCaption(getCaption(getCurrentSize())); paintBusy(false); } @Override - protected void onFinished() { + public void onFinished() { myFinished = true; } 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 71f0b7b08cb6..485327594487 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 @@ -120,21 +120,26 @@ public class ProgressManagerImpl extends CoreProgressManager implements Disposab TaskContainer action = new TaskContainer(task) { @Override public void run() { - boolean canceled = false; + boolean processCanceled = false; + Exception exception = null; + final long start = System.currentTimeMillis(); try { ProgressManager.getInstance().runProcess(process, progressIndicator); } catch (ProcessCanceledException e) { - canceled = true; + processCanceled = true; + } + catch (Exception e) { + exception = e; } final long end = System.currentTimeMillis(); final long time = end - start; - if (canceled || progressIndicator.isCanceled()) { - ApplicationManager.getApplication().invokeLater(() -> task.onCancel(), modalityState); - } - else { + final boolean finalCanceled = processCanceled || progressIndicator.isCanceled(); + final Exception finalException = exception; + + if (!finalCanceled) { final Task.NotificationInfo notificationInfo = task.notifyFinished(); if (notificationInfo != null && time > 5000) { // snow notification if process took more than 5 secs final Component window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); @@ -142,8 +147,9 @@ public class ProgressManagerImpl extends CoreProgressManager implements Disposab systemNotify(notificationInfo); } } - ApplicationManager.getApplication().invokeLater(() -> task.onSuccess(), modalityState); } + + ApplicationManager.getApplication().invokeLater(() -> finishTask(task, finalCanceled, finalException), modalityState); } };