package gw.plugin.ij.util;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiElement;
import gw.internal.gosu.parser.TypeMayHaveBeenDeletedException;
import gw.internal.gosu.parser.TypeResolveException;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.module.IModule;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.Callable;
public abstract class SafeCallable<R> implements Computable<R>, Callable<R>, Runnable {
private R _result;
private IModule _module;
public SafeCallable() {
}
public SafeCallable(IModule module) {
_module = module;
}
public SafeCallable(@NotNull PsiElement context) {
try {
_module = GosuModuleUtil.findModuleForPsiElement(context);
if (_module == null) {
_module = TypeSystem.getGlobalModule();
}
}
catch (Exception e) {
if( !ExceptionUtil.isWrappedCanceled( e ) ) {
if( e instanceof RuntimeException ) {
throw (RuntimeException)e;
}
throw new RuntimeException( e );
}
// Eat ankle-biting ProcessCancelledExceptions
}
}
public abstract R execute() throws Exception;
private R _execute() throws Exception {
if (_module != null) {
TypeSystem.pushModule(_module);
}
try {
_result = execute();
return _result;
}
catch (TypeResolveException e) {
if (e instanceof TypeMayHaveBeenDeletedException) {
((TypeMayHaveBeenDeletedException) e).deleteTheType();
}
return handleNull( e );
}
catch (Exception e) {
if( !ExceptionUtil.isWrappedCanceled( e ) ) {
return handleNull( e );
}
throw e;
}
finally {
if (_module != null) {
TypeSystem.popModule(_module);
}
}
}
@Override
public final R compute() {
try {
return _execute();
} catch (Exception e) {
if( e instanceof RuntimeException ) {
throw (RuntimeException)e;
}
throw new RuntimeException(e);
}
}
@Override
public final R call() throws Exception {
return _execute();
}
public R handleNull( Throwable exception ) {
return null;
}
@Override
public final void run() {
try {
_execute();
} catch (Exception e) {
if( e instanceof RuntimeException ) {
throw (RuntimeException)e;
}
throw new RuntimeException(e);
}
}
public R getResult() {
return _result;
}
}