package com.intellij.openapi.application.ex;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
import org.jetbrains.annotations.NotNull;
+import java.util.concurrent.*;
+
public class ApplicationUtil {
// throws exception if can't grab read action right now
public static <T> T tryRunReadAction(@NotNull final Computable<T> computable) throws CannotRunReadActionException {
}
}
- public static class CannotRunReadActionException extends RuntimeException{
+ /**
+ * 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 Callable<T> callable) throws ExecutionException, InterruptedException {
+ Future<T> future = ApplicationManager.getApplication().executeOnPooledThread(callable);
+
+ while (true) {
+ try {
+ ProgressManager.checkCanceled();
+ }
+ catch (ProcessCanceledException e) {
+ future.cancel(true);
+ throw e;
+ }
+
+ try {
+ return future.get(200, TimeUnit.MILLISECONDS);
+ }
+ catch (TimeoutException ignored) { }
+ }
+ }
+
+ public static class CannotRunReadActionException extends RuntimeException {
+ @SuppressWarnings({"NullableProblems", "NonSynchronizedMethodOverridesSynchronizedMethod"})
@Override
public Throwable fillInStackTrace() {
return this;
package com.intellij.openapi.fileEditor.impl;
import com.intellij.lang.properties.charset.Native2AsciiCharset;
-import com.intellij.openapi.fileTypes.*;
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ex.ApplicationUtil;
+import com.intellij.openapi.fileTypes.BinaryFileDecompiler;
+import com.intellij.openapi.fileTypes.BinaryFileTypeDecompilers;
+import com.intellij.openapi.fileTypes.CharsetUtil;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
+import java.util.concurrent.Callable;
public final class LoadTextUtil {
@Nls private static final String AUTO_DETECTED_FROM_BOM = "auto-detected from BOM";
}
@NotNull
- public static CharSequence loadText(@NotNull VirtualFile file) {
+ public static CharSequence loadText(@NotNull final VirtualFile file) {
if (file instanceof LightVirtualFile) {
return ((LightVirtualFile)file).getContent();
}
if (fileType.isBinary()) {
final BinaryFileDecompiler decompiler = BinaryFileTypeDecompilers.INSTANCE.forFileType(fileType);
if (decompiler != null) {
- CharSequence text = decompiler.decompile(file);
+ CharSequence text;
+
+ final Application app = ApplicationManager.getApplication();
+ if (app != null && app.isDispatchThread()) {
+ final Ref<CharSequence> result = Ref.create(ArrayUtil.EMPTY_CHAR_SEQUENCE);
+ final Ref<RuntimeException> exception = Ref.create();
+
+ ProgressManager.getInstance().run(new Task.Modal(null, "Decompiling " + file.getName(), true) {
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ indicator.setIndeterminate(true);
+ try {
+ result.set(ApplicationUtil.runWithCheckCanceled(new Callable<CharSequence>() {
+ @Override
+ public CharSequence call() {
+ return decompiler.decompile(file);
+ }
+ }));
+ }
+ catch (RuntimeException e) {
+ exception.set(e);
+ }
+ catch (Exception ignored) { }
+ }
+ });
+
+ if (!exception.isNull()) {
+ throw exception.get();
+ }
+
+ text = result.get();
+ }
+ else {
+ text = decompiler.decompile(file);
+ }
+
StringUtil.assertValidSeparators(text);
return text;
}
package org.jetbrains.java.decompiler;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProcessCanceledException;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
public class IdeaLogger extends IFernflowerLogger {
@Override
public void writeMessage(String message, Throwable t) {
if (t instanceof InternalException) throw (InternalException)t;
+ else if (t instanceof ProcessCanceledException) throw (ProcessCanceledException)t;
+ else if (t instanceof InterruptedException) throw new ProcessCanceledException(t);
else throw new InternalException(message, t);
}