package org.rascalmpl.eclipse.editor;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.List;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.rascalmpl.eclipse.Activator;
import org.rascalmpl.eclipse.debug.core.model.RascalValue;
import org.rascalmpl.eclipse.debug.core.model.RascalVariable;
import org.rascalmpl.eclipse.nature.ProjectEvaluatorFactory;
import org.rascalmpl.interpreter.Evaluator;
import org.rascalmpl.interpreter.JavaToRascal;
import org.rascalmpl.interpreter.env.ModuleEnvironment;
import org.rascalmpl.interpreter.env.Pair;
import org.rascalmpl.interpreter.load.StandardLibraryContributor;
import org.rascalmpl.interpreter.result.AbstractFunction;
import io.usethesource.vallang.IString;
import io.usethesource.vallang.IValue;
import io.usethesource.vallang.type.Type;
import io.usethesource.impulse.runtime.RuntimePlugin;
public class ValueContributionItem extends ContributionItem {
private static final class FunctionAction extends Action {
private final IValue val;
private final AbstractFunction f;
private FunctionAction(String name, IValue val, AbstractFunction f) {
super(name);
this.val = val;
this.f = f;
}
@Override
public void runWithEvent(Event event) {
try {
f.call(new Type[] { val.getType() }, new IValue[] { val }, null);
}
catch (Throwable e) {
Activator.log("failed to execute " + getText(), e);
}
}
}
private static final String UTIL_VALUE_UI = "util::ValueUI";
private static PrintWriter out;
private static PrintWriter err;
private static Evaluator eval;
public ValueContributionItem() {
}
public ValueContributionItem(String id) {
super(id);
}
private static void init() {
try {
out = new PrintWriter(new OutputStreamWriter(RuntimePlugin.getInstance().getConsoleStream(), "UTF16"));
err = new PrintWriter(new OutputStreamWriter(RuntimePlugin.getInstance().getConsoleStream(), "UTF16"), true);
eval = new JavaToRascal(out, err).getEvaluator();
eval.addRascalSearchPathContributor(StandardLibraryContributor.getInstance());
ProjectEvaluatorFactory.configure(eval);
eval.doImport(null, UTIL_VALUE_UI);
} catch (UnsupportedEncodingException e) {
Activator.log("could not init value contributions", e);
throw new RuntimeException(e);
}
}
@Override
public boolean isDynamic() {
return true;
}
private IValue getSelectedValue() {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (window != null) {
ISelection sel = window.getSelectionService().getSelection();
if (sel instanceof IStructuredSelection) {
IStructuredSelection selection = (IStructuredSelection) sel;
Object firstElement = selection.getFirstElement();
if (firstElement instanceof RascalVariable) {
return ((RascalVariable) firstElement).getRuntimeValue();
}
else if (firstElement instanceof RascalValue) {
return ((RascalValue) firstElement).getRuntimeValue();
}
else if (firstElement instanceof IValue) {
return (IValue) firstElement;
}
}
}
return null;
}
@Override
public void fill(final Menu menu, int index) {
final IValue val = getSelectedValue();
if (val == null) {
return;
}
if (eval == null) {
init();
}
ModuleEnvironment module = eval.getHeap().getModule(UTIL_VALUE_UI);
for (Pair<String, List<AbstractFunction>> func : module.getFunctions()) {
final String name = func.getFirst();
for (final AbstractFunction f : func.getSecond()) {
if (f.getArity() == 1
&& f.getReturnType().isBottom()
&& val.getType().isSubtypeOf(f.getFunctionType().getArgumentTypes().getFieldType(0))) {
IString label = (IString) f.getTag("label");
Action a = new FunctionAction(label != null ? label.getValue() : name, val, f);
new ActionContributionItem(a).fill(menu, index);
};
}
}
}
}