package jetbrains.mps.debugger.java.runtime.engine.requests;
/*Generated by MPS */
import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import jetbrains.mps.debug.api.IDebuggableFramesSelector;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.StackFrame;
import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.AbsentInformationException;
import com.sun.jdi.event.StepEvent;
import com.sun.jdi.request.StepRequest;
import org.jetbrains.annotations.NotNull;
import com.sun.jdi.Location;
public class StepRequestor implements Requestor {
public static final int STOP = 0;
private static final Logger LOG = LogManager.getLogger(StepRequestor.class);
private final int myStepType;
private String myDeclaringType;
private int myLineNumber;
private int myFrameCount;
private String mySourceName;
private final IDebuggableFramesSelector myFramesSelector;
public StepRequestor(ThreadReference thread, int stepType, IDebuggableFramesSelector framesSelector) {
myStepType = stepType;
myFramesSelector = framesSelector;
try {
if (thread != null) {
myFrameCount = thread.frameCount();
StackFrame frame = thread.frame(0);
if (frame != null) {
myDeclaringType = frame.location().declaringType().name();
myLineNumber = frame.location().lineNumber();
mySourceName = frame.location().sourceName();
}
}
} catch (IncompatibleThreadStateException e) {
LOG.error(null, e);
} catch (AbsentInformationException e) {
LOG.error(null, e);
}
}
public int nextStep(StepEvent event) {
ThreadReference thread = event.thread();
if (thread == null) {
return defaultStepType();
}
try {
if (thread.frameCount() == 0) {
return defaultStepType();
}
StackFrame frame = thread.frame(0);
return nextStep(thread, frame);
} catch (IncompatibleThreadStateException e) {
return defaultStepType();
}
}
private int defaultStepType() {
if (myStepType == StepRequest.STEP_OVER || myStepType == StepRequest.STEP_INTO) {
return myStepType;
}
return STOP;
}
private int nextStep(@NotNull ThreadReference thread, @NotNull StackFrame frame) {
// decides whether we need to step again; depends on whether our current line in generated java class has been changed.
if (myStepType == StepRequest.STEP_OVER || myStepType == StepRequest.STEP_INTO) {
int frameCount = -1;
Location location = frame.location();
String sourceName = "";
try {
frameCount = thread.frameCount();
sourceName = location.sourceName();
} catch (IncompatibleThreadStateException e) {
LOG.error(null, e);
} catch (AbsentInformationException e) {
LOG.error(null, e);
}
// if we are not in debuggable position we step again
// TODO this place may lead (and does lead) to bad performance (see MPS-8725)
if (!(sourceName.isEmpty()) && !(myFramesSelector.isDebuggablePosition(location.declaringType().name(), sourceName, location.lineNumber()))) {
return myStepType;
}
boolean filesEqual = myDeclaringType.equals(location.declaringType().name());
// if we are on the same place we should step again
if (myFramesSelector.isSamePosition(myDeclaringType, mySourceName, myLineNumber, myFrameCount, location.declaringType().name(), sourceName, location.lineNumber(), frameCount)) {
return myStepType;
}
}
return STOP;
}
}