in com.microsoft.java.debug.core/src/main/java/com/microsoft/java/debug/core/adapter/handler/StepRequestHandler.java [64:143]
public CompletableFuture<Response> handle(Command command, Arguments arguments, Response response,
IDebugAdapterContext context) {
if (context.getDebugSession() == null) {
return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.EMPTY_DEBUG_SESSION, "Debug Session doesn't exist.");
}
long threadId = ((StepArguments) arguments).threadId;
ThreadReference thread = DebugUtility.getThread(context.getDebugSession(), threadId);
if (thread != null) {
JdiExceptionReference exception = context.getExceptionManager().removeException(threadId);
context.getStepResultManager().removeMethodResult(threadId);
try {
ThreadState threadState = new ThreadState();
threadState.threadId = threadId;
threadState.pendingStepType = command;
threadState.stackDepth = thread.frameCount();
threadState.stepLocation = getTopFrame(thread).location();
threadState.eventSubscription = context.getDebugSession().getEventHub().events()
.filter(debugEvent -> (debugEvent.event instanceof StepEvent && debugEvent.event.request().equals(threadState.pendingStepRequest))
|| (debugEvent.event instanceof MethodExitEvent && debugEvent.event.request().equals(threadState.pendingMethodExitRequest))
|| debugEvent.event instanceof BreakpointEvent
|| debugEvent.event instanceof ExceptionEvent)
.subscribe(debugEvent -> {
handleDebugEvent(debugEvent, context.getDebugSession(), context, threadState);
});
if (command == Command.STEPIN) {
threadState.pendingStepRequest = DebugUtility.createStepIntoRequest(thread,
context.getStepFilters().allowClasses,
context.getStepFilters().skipClasses);
} else if (command == Command.STEPOUT) {
threadState.pendingStepRequest = DebugUtility.createStepOutRequest(thread,
context.getStepFilters().allowClasses,
context.getStepFilters().skipClasses);
} else {
threadState.pendingStepRequest = DebugUtility.createStepOverRequest(thread, null);
}
threadState.pendingStepRequest.enable();
MethodExitRequest methodExitRequest = thread.virtualMachine().eventRequestManager().createMethodExitRequest();
methodExitRequest.addThreadFilter(thread);
methodExitRequest.addClassFilter(threadState.stepLocation.declaringType());
if (thread.virtualMachine().canUseInstanceFilters()) {
try {
ObjectReference thisObject = getTopFrame(thread).thisObject();
if (thisObject != null) {
methodExitRequest.addInstanceFilter(thisObject);
}
} catch (Exception e) {
// ignore
}
}
methodExitRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
threadState.pendingMethodExitRequest = methodExitRequest;
methodExitRequest.enable();
DebugUtility.resumeThread(thread);
ThreadsRequestHandler.checkThreadRunningAndRecycleIds(thread, context);
} catch (IncompatibleThreadStateException ex) {
// Roll back the Exception info if stepping fails.
context.getExceptionManager().setException(threadId, exception);
final String failureMessage = String.format("Failed to step because the thread '%s' is not suspended in the target VM.", thread.name());
throw AdapterUtils.createCompletionException(
failureMessage,
ErrorCode.STEP_FAILURE,
ex);
} catch (IndexOutOfBoundsException ex) {
// Roll back the Exception info if stepping fails.
context.getExceptionManager().setException(threadId, exception);
final String failureMessage = String.format("Failed to step because the thread '%s' doesn't contain any stack frame", thread.name());
throw AdapterUtils.createCompletionException(
failureMessage,
ErrorCode.STEP_FAILURE,
ex);
}
}
return CompletableFuture.completedFuture(response);
}