Skip to content

Commit

Permalink
Implement CancelationManager
Browse files Browse the repository at this point in the history
  • Loading branch information
Earthcomputer authored and jaskarth committed Sep 4, 2023
1 parent 4b86b2e commit 74d40fb
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 4 deletions.
14 changes: 14 additions & 0 deletions src/org/jetbrains/java/decompiler/main/ClassWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.jetbrains.java.decompiler.code.InstructionSequence;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.collectors.ImportCollector;
import org.jetbrains.java.decompiler.main.decompiler.CancelationManager;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.main.rels.ClassWrapper;
Expand Down Expand Up @@ -80,6 +81,8 @@ private static boolean invokeProcessors(TextBuffer buffer, ClassNode node) {
if (method.root != null) {
try {
SwitchHelper.simplifySwitches(method.root, method.methodStruct, method.root);
} catch (CancelationManager.CanceledException e) {
throw e;
} catch (Throwable e) {
DecompilerContext.getLogger().writeMessage("Method " + method.methodStruct.getName() + " " + method.methodStruct.getDescriptor() + " in class " + node.classStruct.qualifiedName + " couldn't be written.",
IFernflowerLogger.Severity.WARN,
Expand Down Expand Up @@ -113,6 +116,8 @@ private static boolean invokeProcessors(TextBuffer buffer, ClassNode node) {
mw.varproc.rerunClashing(mw.root);
}
}
} catch (CancelationManager.CanceledException e) {
throw e;
} catch (Throwable t) {
DecompilerContext.getLogger().writeMessage("Class " + node.simpleName + " couldn't be written.",
IFernflowerLogger.Severity.WARN,
Expand Down Expand Up @@ -250,6 +255,9 @@ public void classLambdaToJava(ClassNode node, TextBuffer buffer, Exprent method_
codeBuffer.addBytecodeMapping(root.getDummyExit().bytecode);
buffer.append(codeBuffer, node.classStruct.qualifiedName, InterpreterUtil.makeUniqueKey(methodWrapper.methodStruct.getName(), methodWrapper.methodStruct.getDescriptor()));
}
catch (CancelationManager.CanceledException e) {
throw e;
}
catch (Throwable ex) {
DecompilerContext.getLogger().writeMessage("Method " + mt.getName() + " " + mt.getDescriptor() + " in class " + node.classStruct.qualifiedName + " couldn't be written.",
IFernflowerLogger.Severity.WARN,
Expand Down Expand Up @@ -894,6 +902,9 @@ private static void methodLambdaToJava(ClassNode lambdaNode,
childBuf.addBytecodeMapping(root.getDummyExit().bytecode);
buffer.append(childBuf, classWrapper.getClassStruct().qualifiedName, InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()));
}
catch (CancelationManager.CanceledException e) {
throw e;
}
catch (Throwable t) {
String message = "Method " + mt.getName() + " " + mt.getDescriptor() + " in class " + lambdaNode.classStruct.qualifiedName + " couldn't be written.";
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN, t);
Expand Down Expand Up @@ -1216,6 +1227,9 @@ else if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarT
buffer.append(code, cl.qualifiedName, InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()));
}
}
catch (CancelationManager.CanceledException e) {
throw e;
}
catch (Throwable t) {
String message = "Method " + mt.getName() + " " + mt.getDescriptor() + " in class " + node.classStruct.qualifiedName + " couldn't be written.";
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN, t);
Expand Down
8 changes: 6 additions & 2 deletions src/org/jetbrains/java/decompiler/main/ClassesProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.jetbrains.java.decompiler.code.InstructionSequence;
import org.jetbrains.java.decompiler.main.collectors.BytecodeSourceMapper;
import org.jetbrains.java.decompiler.main.collectors.ImportCollector;
import org.jetbrains.java.decompiler.main.decompiler.CancelationManager;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.main.extern.IIdentifierRenamer;
Expand Down Expand Up @@ -432,6 +433,8 @@ public void processClass(StructClass cl) throws IOException {
new NestedMemberAccess().propagateMemberAccess(root);
}
}
} catch (CancelationManager.CanceledException e) {
throw e;
} finally {
DecompilerContext.getLogger().endProcessingClass();
}
Expand Down Expand Up @@ -501,8 +504,9 @@ else if (moduleInfo) {
}
}
}
}
finally {
} catch (CancelationManager.CanceledException e) {
throw e;
} finally {
destroyWrappers(root);
DecompilerContext.getLogger().endReadingClass();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.ClassesProcessor.ClassNode;
import org.jetbrains.java.decompiler.main.decompiler.CancelationManager;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.main.rels.ClassWrapper;
Expand All @@ -29,6 +30,8 @@ public static void extractInitializers(ClassWrapper wrapper) {
if (method != null && method.root != null) { // successfully decompiled static constructor
extractStaticInitializers(wrapper, method);
}
} catch (CancelationManager.CanceledException e) {
throw e;
} catch (Throwable t) {
StructMethod mt = method.methodStruct;
String message = "Method " + mt.getName() + " " + mt.getDescriptor() + " in class " + wrapper.getClassStruct().qualifiedName + " couldn't be written.";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.jetbrains.java.decompiler.main.decompiler;

/**
* Used for cancelling the decompilation process. This can for example be useful in GUI frontends with cancelation
* support.
*/
public final class CancelationManager {
private static Runnable cancelationChecker = () -> {};

private CancelationManager() {
}

/**
* Cancels the decompilation process by throwing a {@linkplain CanceledException}.
*/
public static void cancel() {
throw CanceledException.INSTANCE;
}

/**
* Polled frequently by the decompiler to check if decompilation has been canceled. Use
* {@linkplain #setCancelationChecker(Runnable)} to set the logic for checking cancelation.
*/
public static void checkCanceled() {
cancelationChecker.run();
}

/**
* Sets the logic for checking cancelation. To cancel decompilation, call {@linkplain #cancel()} inside the checker.
*/
public static void setCancelationChecker(Runnable checker) {
cancelationChecker = checker;
}

/**
* The exception that is thrown upon cancelation.
*/
public static final class CanceledException extends RuntimeException {
public static final CanceledException INSTANCE = new CanceledException();

private CanceledException() {
}

@Override
public Throwable fillInStackTrace() {
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,11 @@ else if (arg.startsWith("-only=") || arg.startsWith("--only=")) {
decompiler.addWhitelist(prefix);
}

decompiler.decompileContext();
try {
decompiler.decompileContext();
} catch (CancelationManager.CanceledException e) {
System.out.println("Decompilation canceled");
}
}

@SuppressWarnings("UseOfSystemOutOrSystemErr")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.jetbrains.java.decompiler.api.plugin.pass.NamedPass;
import org.jetbrains.java.decompiler.api.plugin.pass.PassContext;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.decompiler.CancelationManager;
import org.jetbrains.java.decompiler.struct.StructClass;

import java.util.*;
Expand Down Expand Up @@ -54,6 +55,7 @@ public boolean runPasses(JavaPassLocation location, PassContext ctx) {
List<NamedPass> passes = this.passes.getOrDefault(location, Collections.emptyList());

for (NamedPass pass : passes) {
CancelationManager.checkCanceled();
if (pass.run(ctx) && location.isLoop()) {
return true;
}
Expand Down
4 changes: 4 additions & 0 deletions src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.main.collectors.VarNamesCollector;
import org.jetbrains.java.decompiler.main.decompiler.CancelationManager;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent;
Expand Down Expand Up @@ -137,6 +138,9 @@ public void init(LanguageSpec spec) {
}
}
}
catch (CancelationManager.CanceledException e) {
throw e;
}
catch (Throwable t) {
String message = "Method " + mt.getName() + " " + mt.getDescriptor() + " in class " + classStruct.qualifiedName + " couldn't be decompiled.";
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN, t);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.jetbrains.java.decompiler.code.cfg.ControlFlowGraph;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.main.decompiler.CancelationManager;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.main.plugins.PluginContext;
Expand Down Expand Up @@ -67,6 +68,9 @@ public void run() {
DecompilerContext.setCurrentContext(parentContext);
root = codeToJava(klass, method, methodDescriptor, varProc, spec);
}
catch (CancelationManager.CanceledException e) {
throw e;
}
catch (Throwable t) {
error = t;
}
Expand All @@ -81,6 +85,8 @@ public void run() {
}

public static RootStatement codeToJava(StructClass cl, StructMethod mt, MethodDescriptor md, VarProcessor varProc, LanguageSpec spec) throws IOException {
CancelationManager.checkCanceled();

debugCurrentlyDecompiling.set(null);
debugCurrentCFG.set(null);
debugCurrentDecompileRecord.set(null);
Expand Down
9 changes: 8 additions & 1 deletion src/org/jetbrains/java/decompiler/struct/ContextUnit.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import org.jetbrains.java.decompiler.main.ClassWriter;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.decompiler.CancelationManager;
import org.jetbrains.java.decompiler.main.extern.IContextSource;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
Expand Down Expand Up @@ -223,7 +224,13 @@ private static void waitForAll(final List<Future<?>> futures) {
for (Future<?> future : futures) {
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
} catch (ExecutionException e) {
if (e.getCause() instanceof CancelationManager.CanceledException) {
throw (CancelationManager.CanceledException) e.getCause();
} else {
throw new RuntimeException(e);
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.main.decompiler.CancelationManager;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.util.TextUtil;
import org.jetbrains.java.decompiler.struct.gen.VarType;
Expand Down Expand Up @@ -50,6 +51,9 @@ public static GenericClassDescriptor parseClassSignature(String qualifiedName, S

return descriptor;
}
catch (CancelationManager.CanceledException e) {
throw e;
}
catch (RuntimeException e) {
DecompilerContext.getLogger().writeMessage("Invalid signature: " + original, IFernflowerLogger.Severity.WARN);
return null;
Expand All @@ -60,6 +64,9 @@ public static GenericFieldDescriptor parseFieldSignature(String signature) {
try {
return new GenericFieldDescriptor(GenericType.parse(signature));
}
catch (CancelationManager.CanceledException e) {
throw e;
}
catch (RuntimeException e) {
DecompilerContext.getLogger().writeMessage("Invalid signature: " + signature, IFernflowerLogger.Severity.WARN);
return null;
Expand Down Expand Up @@ -98,6 +105,9 @@ public static GenericMethodDescriptor parseMethodSignature(String signature) {

return new GenericMethodDescriptor(typeParameters, typeParameterBounds, parameterTypes, returnType, exceptionTypes);
}
catch (CancelationManager.CanceledException e) {
throw e;
}
catch (RuntimeException e) {
DecompilerContext.getLogger().writeMessage("Invalid signature: " + original, IFernflowerLogger.Severity.WARN);
return null;
Expand Down

0 comments on commit 74d40fb

Please sign in to comment.