IDEA-130959 (indicator passing done the right way)
authorRoman Shevchenko <roman.shevchenko@jetbrains.com>
Thu, 13 Nov 2014 16:16:06 +0000 (17:16 +0100)
committerRoman Shevchenko <roman.shevchenko@jetbrains.com>
Thu, 13 Nov 2014 16:16:06 +0000 (17:16 +0100)
platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java
platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java
plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java
plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java

index c7cf4a8da64cf276e19a90670c306982563f962a..451d3e587ed02f9fbcaa40168c4e56eef61dd489 100644 (file)
@@ -17,6 +17,7 @@ package com.intellij.openapi.application.ex;
 
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.Ref;
@@ -53,25 +54,30 @@ public class ApplicationUtil {
    * Allows to interrupt a process which does not performs checkCancelled() calls by itself.
    * Note that the process may continue to run in background indefinitely - so <b>avoid using this method unless absolutely needed</b>.
    */
-  public static <T> T runWithCheckCanceled(@NotNull final Callable<T> callable) throws Exception {
+  public static <T> T runWithCheckCanceled(@NotNull final Callable<T> callable, @NotNull final ProgressIndicator indicator) throws Exception {
+    final Ref<T> result = Ref.create();
     final Ref<Throwable> error = Ref.create();
 
-    Future<T> future = ApplicationManager.getApplication().executeOnPooledThread(new Callable<T>() {
+    Future<?> future = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
       @Override
-      public T call() throws Exception {
-        try {
-          return callable.call();
-        }
-        catch (Throwable t) {
-          error.set(t);
-          return null;
-        }
+      public void run() {
+        ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
+          @Override
+          public void run() {
+            try {
+              result.set(callable.call());
+            }
+            catch (Throwable t) {
+              error.set(t);
+            }
+          }
+        }, indicator);
       }
     });
 
     while (true) {
       try {
-        ProgressManager.checkCanceled();
+        indicator.checkCanceled();
       }
       catch (ProcessCanceledException e) {
         future.cancel(true);
@@ -79,9 +85,9 @@ public class ApplicationUtil {
       }
 
       try {
-        T result = future.get(200, TimeUnit.MILLISECONDS);
+        future.get(200, TimeUnit.MILLISECONDS);
         ExceptionUtil.rethrowAll(error.get());
-        return result;
+        return result.get();
       }
       catch (TimeoutException ignored) { }
     }
index ca194dd5ce65dc981caf748a11936b341aa0416d..6f1d24e4a8c310c703c2fca490c53e8f60f77958 100644 (file)
@@ -390,7 +390,7 @@ public final class LoadTextUtil {
                   public CharSequence call() {
                     return decompiler.decompile(file);
                   }
-                }));
+                }, indicator));
               }
               catch (Throwable t) {
                 error.set(t);
index b67f88b8b1ed514d17d22833f9b3302d011c2de7..cfae319bae13200da064dde2783960aac22561bb 100644 (file)
@@ -27,6 +27,8 @@ import com.intellij.openapi.application.ex.ApplicationManagerEx;
 import com.intellij.openapi.fileEditor.*;
 import com.intellij.openapi.fileTypes.StdFileTypes;
 import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
 import com.intellij.openapi.project.DefaultProjectFactory;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.DialogWrapper;
@@ -47,6 +49,7 @@ import com.intellij.util.messages.MessageBusConnection;
 import com.intellij.util.ui.UIUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
 import org.jetbrains.java.decompiler.main.decompiler.BaseDecompiler;
 import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider;
 import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
@@ -74,6 +77,7 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
   private final IFernflowerLogger myLogger = new IdeaLogger();
   private final Map<String, Object> myOptions = new HashMap<String, Object>();
   private boolean myLegalNoticeAccepted;
+  private final Map<VirtualFile, ProgressIndicator> myProgress = ContainerUtil.newConcurrentMap();
 
   public IdeaDecompiler() {
     myOptions.put(IFernflowerPreferences.HIDE_DEFAULT_CONSTRUCTOR, "0");
@@ -140,6 +144,9 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
       return ClsFileImpl.decompile(file);
     }
 
+    ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
+    if (indicator != null) myProgress.put(file, indicator);
+
     try {
       Map<String, VirtualFile> files = ContainerUtil.newLinkedHashMap();
       files.put(file.getPath(), file);
@@ -193,6 +200,15 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
         throw new CannotDecompileException(e);
       }
     }
+    finally {
+      myProgress.remove(file);
+    }
+  }
+
+  @TestOnly
+  @Nullable
+  public ProgressIndicator getProgress(@NotNull VirtualFile file) {
+    return myProgress.get(file);
   }
 
   private static class MyBytecodeProvider implements IBytecodeProvider {
index 81df4dd8285910ba3f2b408b94de1f1f03946b82..2947d18c9e7aa696a01f11a40e5b05b4f98f64dc 100644 (file)
@@ -18,8 +18,12 @@ package org.jetbrains.java.decompiler;
 import com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPassFactory;
 import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction;
 import com.intellij.debugger.PositionManager;
+import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
 import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
 import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.registry.Registry;
@@ -28,9 +32,11 @@ import com.intellij.openapi.vfs.*;
 import com.intellij.pom.Navigatable;
 import com.intellij.psi.PsiElement;
 import com.intellij.psi.PsiFile;
+import com.intellij.psi.compiled.ClassFileDecompilers;
 import com.intellij.psi.impl.compiled.ClsFileImpl;
 import com.intellij.testFramework.PlatformTestUtil;
 import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import com.intellij.util.Alarm;
 import com.intellij.util.ThrowableRunnable;
 import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.io.URLUtil;
@@ -169,4 +175,31 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase {
       }
     }).cpuBound().assertTiming();
   }
+
+  public void testCancellation() {
+    final VirtualFile file = getTestFile(PlatformTestUtil.getRtJarPath() + "!/javax/swing/JTable.class");
+
+    final IdeaDecompiler decompiler = (IdeaDecompiler)ClassFileDecompilers.find(file);
+    assertNotNull(decompiler);
+
+    final Alarm alarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, getProject());
+    alarm.addRequest(new Runnable() {
+      @Override
+      public void run() {
+        ProgressIndicator progress = decompiler.getProgress(file);
+        if (progress != null) {
+          progress.cancel();
+        }
+        else {
+          alarm.addRequest(this, 200, ModalityState.any());
+        }
+      }
+    }, 750, ModalityState.any());
+
+    try {
+      FileDocumentManager.getInstance().getDocument(file);
+      fail("should have been cancelled");
+    }
+    catch (ProcessCanceledException ignored) { }
+  }
 }