package com.sap.runlet.expressionpad.launch;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.DebugElement;
import org.eclipse.debug.core.model.IRegisterGroup;
import org.eclipse.debug.core.model.IStackFrame;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.debug.core.model.IVariable;
import com.sap.runlet.abstractinterpreter.AbstractObjectFormatter;
import com.sap.runlet.abstractinterpreter.StackFrame;
import com.sap.runlet.abstractinterpreter.objects.RunletObject;
import com.sap.runlet.expressionpad.Activator;
import com.sap.tc.moin.repository.mmi.reflect.RefObject;
public abstract class AbstractRunletStackFrame<LinkEndMetaObject, TypeUsage, ClassUsage extends TypeUsage, SignatureImplementationType> extends DebugElement implements IStackFrame {
private StackFrame<LinkEndMetaObject, TypeUsage, ClassUsage, SignatureImplementationType> stackFrame;
private RunletThread runletThread;
private AbstractObjectFormatter<LinkEndMetaObject, TypeUsage, ClassUsage, SignatureImplementationType> formatter;
protected AbstractObjectFormatter<LinkEndMetaObject, TypeUsage, ClassUsage, SignatureImplementationType> getFormatter() {
return formatter;
}
public AbstractRunletStackFrame(RunletThread runletThread, RunletDebugTarget debugTarget,
StackFrame<LinkEndMetaObject, TypeUsage, ClassUsage, SignatureImplementationType> stackFrame, AbstractObjectFormatter<LinkEndMetaObject, TypeUsage, ClassUsage, SignatureImplementationType> formatter) {
super(debugTarget);
this.runletThread = runletThread;
this.stackFrame = stackFrame;
this.formatter = formatter;
}
public int hashCode() {
return getStackFrame().hashCode();
}
public boolean equals(Object o) {
boolean result = false;
if (o instanceof AbstractRunletStackFrame<?, ?, ?, ?>) {
result = getStackFrame().equals(((AbstractRunletStackFrame<?, ?, ?, ?>) o).getStackFrame());
}
return result;
}
@Override
public int getCharEnd() {
// TODO good gracious... this is about finding the "source location" in some concrete syntax corresponding to the current stack frame; this suggests we need more information about "where we are" in a StackFrame element
return 0;
}
@Override
public int getCharStart(){
// TODO see getCharEnd()
return 0;
}
@Override
public int getLineNumber() {
// TODO see getCharEnd()
return 0;
}
@Override
public String getName() {
StringBuilder result = new StringBuilder();
StackFrame<?, ?, ?, SignatureImplementationType> frame = getStackFrame();
if (frame.getCurrentlyExecutingImplementation() != null) {
result.append(getFormatter().formatSignatureOfImpl(frame.getCurrentlyExecutingImplementation()));
result.append(' ');
}
result.append('[');
RefObject currentlyEvaluating = getStackFrame().getCurrentlyEvaluating();
if (currentlyEvaluating != null) {
result.append(getFormatter().formatCurrentlyEvaluatingRefObject(currentlyEvaluating));
}
result.append(']');
return result.toString();
}
/**
* Runlet doesn't have registers
*/
@Override
public IRegisterGroup[] getRegisterGroups() {
return new IRegisterGroup[0];
}
@Override
public IThread getThread() {
return runletThread;
}
@Override
public IVariable[] getVariables() {
StackFrame<LinkEndMetaObject, TypeUsage, ClassUsage, SignatureImplementationType> frame = getStackFrame();
List<IVariable> result = new LinkedList<IVariable>();
Map<String, RunletObject<LinkEndMetaObject, TypeUsage, ClassUsage>> allVisibleVariables = frame.getAllVisibleVariableValues();
for (String varName : allVisibleVariables.keySet()) {
result.add(createVariable(allVisibleVariables, varName));
}
return result.toArray(new IVariable[result.size()]);
}
protected abstract RunletVariable createVariable(
Map<String, RunletObject<LinkEndMetaObject, TypeUsage, ClassUsage>> allVisibleVariables, String varName);
@Override
public boolean hasRegisterGroups() {
return false;
}
@Override
public boolean hasVariables() {
return getVariables().length > 0;
}
@Override
public RunletDebugTarget getDebugTarget() {
return (RunletDebugTarget) super.getDebugTarget();
}
@Override
public String getModelIdentifier() {
return Activator.PLUGIN_ID;
}
/**
* Stepping into is possible if this is the top frame.
*/
@Override
public boolean canStepInto() {
return getStackFrame() == getDebugTarget().getInterpreter().getCallstack().peek();
}
@Override
public boolean canStepOver() {
return true;
}
@Override
public boolean canStepReturn() {
return true;
}
@Override
public boolean isStepping() {
return getThread().isStepping();
}
@Override
public void stepInto() throws DebugException {
getThread().stepInto();
}
@Override
public void stepOver() throws DebugException {
getThread().stepOver();
}
@Override
public void stepReturn() throws DebugException {
getThread().stepReturn();
}
@Override
public boolean canResume() {
return getThread().canResume();
}
@Override
public boolean canSuspend() {
return getThread().canSuspend();
}
@Override
public boolean isSuspended() {
return getThread().isSuspended();
}
@Override
public void resume() throws DebugException {
getThread().resume();
}
@Override
public void suspend() throws DebugException {
getThread().suspend();
}
@Override
public boolean canTerminate() {
return getThread().canTerminate();
}
@Override
public boolean isTerminated() {
return getThread().isTerminated();
}
@Override
public void terminate() throws DebugException {
getThread().terminate();
}
private StackFrame<LinkEndMetaObject, TypeUsage, ClassUsage, SignatureImplementationType> getStackFrame() {
return stackFrame;
}
}