package com.sun.tools.javac.code;
import java.util.HashMap;
import java.util.Map;
import com.sun.tools.javac.code.Kinds.Kind;
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.Completer;
import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.util.Context;
public class DeferredCompletionFailureHandler {
protected static final Context.Key<DeferredCompletionFailureHandler> deferredCompletionFailureHandlerKey = new Context.Key<>();
public static DeferredCompletionFailureHandler instance(Context context) {
DeferredCompletionFailureHandler instance = context.get(deferredCompletionFailureHandlerKey);
if (instance == null)
instance = new DeferredCompletionFailureHandler(context);
return instance;
}
public final Handler userCodeHandler = new Handler() {
private final Map<ClassSymbol, FlipSymbolDescription> class2Flip = new HashMap<>();
public void install() {
class2Flip.values().forEach(f -> f.flip());
}
public void handleAPICompletionFailure(CompletionFailure cf) {
}
public void classSymbolCompleteFailed(ClassSymbol sym, Completer origCompleter) {
class2Flip.put(sym, new FlipSymbolDescription(sym, new DeferredCompleter(origCompleter) {
@Override public void complete(Symbol sym) throws CompletionFailure {
class2Flip.remove(sym);
super.complete(sym);
}
}));
}
public void classSymbolRemoved(ClassSymbol sym) {
class2Flip.remove(sym);
}
public void uninstall() {
class2Flip.values().forEach(f -> f.flip());
}
};
public final Handler speculativeCodeHandler = new Handler() {
private final Map<ClassSymbol, FlipSymbolDescription> class2Flip = new HashMap<>();
public void install() {
}
public void handleAPICompletionFailure(CompletionFailure cf) {
throw cf;
}
public void classSymbolCompleteFailed(ClassSymbol sym, Completer origCompleter) {
class2Flip.put(sym, new FlipSymbolDescription(sym, new DeferredCompleter(origCompleter)));
}
public void classSymbolRemoved(ClassSymbol sym) {
class2Flip.remove(sym);
}
public void uninstall() {
class2Flip.values().forEach(f -> f.flip());
class2Flip.clear();
}
};
public final Handler javacCodeHandler = new Handler() {
public void install() {
}
public void handleAPICompletionFailure(CompletionFailure cf) {
throw cf;
}
public void classSymbolCompleteFailed(ClassSymbol sym, Completer origCompleter) {}
public void classSymbolRemoved(ClassSymbol sym) {}
public void uninstall() {
}
};
private Handler handler = javacCodeHandler;
protected DeferredCompletionFailureHandler(Context context) {
context.put(deferredCompletionFailureHandlerKey, this);
}
public Handler setHandler(Handler h) {
if (h == handler) return handler;
handler.uninstall();
Handler prev = handler;
handler = h;
handler.install();
return prev;
}
public void handleAPICompletionFailure(CompletionFailure cf) {
handler.handleAPICompletionFailure(cf);
}
public void classSymbolCompleteFailed(ClassSymbol sym, Completer origCompleter) {
handler.classSymbolCompleteFailed(sym, origCompleter);
}
public void classSymbolRemoved(ClassSymbol sym) {
handler.classSymbolRemoved(sym);
}
public boolean isDeferredCompleter(Completer c) {
return c instanceof DeferredCompleter;
}
public interface Handler {
public void install();
public void handleAPICompletionFailure(CompletionFailure cf);
public void classSymbolCompleteFailed(ClassSymbol sym, Completer origCompleter);
public void classSymbolRemoved(ClassSymbol sym);
public void uninstall();
}
private class DeferredCompleter implements Completer {
private final Completer origCompleter;
public DeferredCompleter(Completer origCompleter) {
this.origCompleter = origCompleter;
}
@Override
public void complete(Symbol sym) throws CompletionFailure {
origCompleter.complete(sym);
}
}
private static class FlipSymbolDescription {
public final ClassSymbol sym;
public Type type;
public Kind kind;
public WriteableScope members;
public Completer completer;
public FlipSymbolDescription(ClassSymbol sym, Completer completer) {
this.sym = sym;
this.type = sym.type;
this.kind = sym.kind;
this.members = null;
this.completer = completer;
}
public void flip() {
Type prevType = sym.type;
sym.type = type;
this.type = prevType;
Kind prevKind = sym.kind;
sym.kind = kind;
this.kind = prevKind;
Completer prevCompleter = sym.completer;
sym.completer = completer;
this.completer = prevCompleter;
WriteableScope prevMembers = sym.members_field;
sym.members_field = members;
this.members = prevMembers;
}
}
}