IDEA-130959 (indicator passing + test)
authorRoman Shevchenko <roman.shevchenko@jetbrains.com>
Wed, 12 Nov 2014 14:59:53 +0000 (15:59 +0100)
committerRoman Shevchenko <roman.shevchenko@jetbrains.com>
Wed, 12 Nov 2014 14:59:53 +0000 (15:59 +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 94061b31aceef1cc1b860457721ba75767fbf2be..a864652c503ba44d701b344b7030b90ba405b827 100644 (file)
@@ -17,13 +17,17 @@ 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;
 import com.intellij.util.ExceptionUtil;
 import org.jetbrains.annotations.NotNull;
 
-import java.util.concurrent.*;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 public class ApplicationUtil {
   // throws exception if can't grab read action right now
@@ -50,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<Throwable> error = Ref.create();
 
     Future<T> future = ApplicationManager.getApplication().executeOnPooledThread(new Callable<T>() {
       @Override
       public T call() throws Exception {
-        try {
-          return callable.call();
-        }
-        catch (Throwable t) {
-          error.set(t);
-          return null;
-        }
-      };
+        return ProgressManager.getInstance().runProcess(new Computable<T>() {
+          @Override
+          public T compute() {
+            try {
+              return callable.call();
+            }
+            catch (Throwable t) {
+              error.set(t);
+              return null;
+            }
+          }
+        }, indicator);
+      }
     });
 
     while (true) {
       try {
-        ProgressManager.checkCanceled();
+        indicator.checkCanceled();
       }
       catch (ProcessCanceledException e) {
         future.cancel(true);
index bf4c421c38ea6ef896d14086253344d8d2026faa..1d30e7e7e5d13d7086abecad06e8773ada59e58e 100644 (file)
@@ -389,7 +389,7 @@ public final class LoadTextUtil {
                   public CharSequence call() {
                     return decompiler.decompile(file);
                   }
-                }));
+                }, indicator));
               }
               catch (Throwable t) {
                 error.set(t);
index b67f88b8b1ed514d17d22833f9b3302d011c2de7..098cc7c6667ac90d3a1d02162766625444ba4fa5 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 volatile ProgressIndicator myProgress;
 
   public IdeaDecompiler() {
     myOptions.put(IFernflowerPreferences.HIDE_DEFAULT_CONSTRUCTOR, "0");
@@ -140,6 +144,8 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
       return ClsFileImpl.decompile(file);
     }
 
+    myProgress = ProgressManager.getInstance().getProgressIndicator();
+
     try {
       Map<String, VirtualFile> files = ContainerUtil.newLinkedHashMap();
       files.put(file.getPath(), file);
@@ -193,6 +199,15 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
         throw new CannotDecompileException(e);
       }
     }
+    finally {
+      myProgress = null;
+    }
+  }
+
+  @TestOnly
+  @Nullable
+  public ProgressIndicator getProgress() {
+    return myProgress;
   }
 
   private static class MyBytecodeProvider implements IBytecodeProvider {
index 81df4dd8285910ba3f2b408b94de1f1f03946b82..ac7d270573484abb06bf0565ac6e58cc378870b8 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() {
+    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();
+        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) { }
+  }
 }