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; } }