Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support debug protocol. #160

Merged
merged 1 commit into from
Mar 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.microsoft.java.debug.core.adapter.handler.HotCodeReplaceHandler;
import com.microsoft.java.debug.core.adapter.handler.InitializeRequestHandler;
import com.microsoft.java.debug.core.adapter.handler.LaunchRequestHandler;
import com.microsoft.java.debug.core.adapter.handler.RestartFrameHandler;
import com.microsoft.java.debug.core.adapter.handler.ScopesRequestHandler;
import com.microsoft.java.debug.core.adapter.handler.SetBreakpointsRequestHandler;
import com.microsoft.java.debug.core.adapter.handler.SetExceptionBreakpointsRequestHandler;
Expand Down Expand Up @@ -106,6 +107,7 @@ private void initialize() {
registerHandler(new SetVariableRequestHandler());
registerHandler(new EvaluateRequestHandler());
registerHandler(new HotCodeReplaceHandler());
registerHandler(new RestartFrameHandler());
}

private void registerHandler(IDebugRequestHandler handler) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public enum ErrorCode {
INVALID_ENCODING(1012),
VM_TERMINATED(1013),
LAUNCH_IN_TERMINAL_FAILURE(1014),
STEP_FAILURE(1015);
STEP_FAILURE(1015),
RESTARTFRAME_FAILURE(1016);

private int id;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public CompletableFuture<Messages.Response> handle(Requests.Command command, Req
caps.supportsConditionalBreakpoints = true;
caps.supportsSetVariable = true;
caps.supportTerminateDebuggee = true;
caps.supportsRestartFrame = true;
Types.ExceptionBreakpointFilter[] exceptionFilters = {
Types.ExceptionBreakpointFilter.UNCAUGHT_EXCEPTION_FILTER,
Types.ExceptionBreakpointFilter.CAUGHT_EXCEPTION_FILTER,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*******************************************************************************
* Copyright (c) 2017 Microsoft Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Microsoft Corporation - initial API and implementation
*******************************************************************************/

package com.microsoft.java.debug.core.adapter.handler;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import com.microsoft.java.debug.core.DebugException;
import com.microsoft.java.debug.core.DebugUtility;
import com.microsoft.java.debug.core.StackFrameUtility;
import com.microsoft.java.debug.core.adapter.AdapterUtils;
import com.microsoft.java.debug.core.adapter.ErrorCode;
import com.microsoft.java.debug.core.adapter.IDebugAdapterContext;
import com.microsoft.java.debug.core.adapter.IDebugRequestHandler;
import com.microsoft.java.debug.core.adapter.variables.StackFrameReference;
import com.microsoft.java.debug.core.protocol.Events;
import com.microsoft.java.debug.core.protocol.Events.UserNotificationEvent.NotificationType;
import com.microsoft.java.debug.core.protocol.Messages.Response;
import com.microsoft.java.debug.core.protocol.Requests;
import com.microsoft.java.debug.core.protocol.Requests.Arguments;
import com.microsoft.java.debug.core.protocol.Requests.Command;
import com.microsoft.java.debug.core.protocol.Requests.RestartFrameArguments;
import com.sun.jdi.StackFrame;
import com.sun.jdi.ThreadReference;
import com.sun.jdi.request.StepRequest;

/**
* Support Eclipse's `Drop To Frame` action, which is restartFrame in VSCode's
* debug.
*/
public class RestartFrameHandler implements IDebugRequestHandler {

@Override
public List<Command> getTargetCommands() {
return Arrays.asList(Requests.Command.RESTARTFRAME);
}

@Override
public CompletableFuture<Response> handle(Command command, Arguments arguments, Response response, IDebugAdapterContext context) {
RestartFrameArguments restartFrameArgs = (RestartFrameArguments) arguments;
StackFrameReference stackFrameReference = (StackFrameReference) context.getRecyclableIdPool().getObjectById(restartFrameArgs.frameId);

if (stackFrameReference == null) {
return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.RESTARTFRAME_FAILURE,
String.format("RestartFrame: cannot find the stack frame with frameID %s", restartFrameArgs.frameId));
}

if (canRestartFrame(context, stackFrameReference)) {
try {
ThreadReference reference = stackFrameReference.getThread();
popStackFrames(context, reference, stackFrameReference.getDepth());
stepInto(context, reference);
} catch (DebugException de) {
context.getProtocolServer().sendEvent(new Events.UserNotificationEvent(NotificationType.ERROR, de.getMessage()));
}
return CompletableFuture.completedFuture(response);
} else {
context.getProtocolServer().sendEvent(new Events.UserNotificationEvent(NotificationType.ERROR, "Current stack frame doesn't support restart."));
context.getProtocolServer().sendEvent(new Events.StoppedEvent("restartframe", stackFrameReference.getThread().uniqueID()));
return AdapterUtils.createAsyncErrorResponse(response, ErrorCode.RESTARTFRAME_FAILURE, "Failed to restart the selected stack frame.");
}
}

private boolean canRestartFrame(IDebugAdapterContext context, StackFrameReference frameReference) {
if (!context.getDebugSession().getVM().canPopFrames()) {
return false;
}
ThreadReference reference = frameReference.getThread();
StackFrame[] frames = context.getStackFrameManager().reloadStackFrames(reference);

// The frame cannot be the bottom one of the call stack:
if (frames.length <= frameReference.getDepth() + 1) {
return false;
}

// Cannot restart frame involved with native call stacks:
for (int i = 0; i <= frameReference.getDepth() + 1; i++) {
if (StackFrameUtility.isNative(frames[i])) {
return false;
}
}
return true;
}

private void popStackFrames(IDebugAdapterContext context, ThreadReference thread, int depth) throws DebugException {
StackFrame[] frames = context.getStackFrameManager().reloadStackFrames(thread);
StackFrameUtility.pop(frames[depth]);
}

private void stepInto(IDebugAdapterContext context, ThreadReference thread) {
StepRequest request = DebugUtility.createStepIntoRequest(thread, context.getStepFilters().classNameFilters);
context.getDebugSession().getEventHub().stepEvents().filter(debugEvent -> request.equals(debugEvent.event.request())).take(1).subscribe(debugEvent -> {
debugEvent.shouldResume = false;
// Have to send two events to keep the UI sync with the step in operations:
context.getProtocolServer().sendEvent(new Events.StoppedEvent("step", thread.uniqueID()));
context.getProtocolServer().sendEvent(new Events.ContinuedEvent(thread.uniqueID()));
});
request.enable();
thread.resume();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@ public static class RedefineClassesArguments extends Arguments {

}

public static class RestartFrameArguments extends Arguments {
public int frameId;
}

public static enum Command {
INITIALIZE("initialize", InitializeArguments.class),
LAUNCH("launch", LaunchArguments.class),
Expand All @@ -271,6 +275,7 @@ public static enum Command {
STEPOUT("stepOut", StepOutArguments.class),
PAUSE("pause", PauseArguments.class),
STACKTRACE("stackTrace", StackTraceArguments.class),
RESTARTFRAME("restartFrame", RestartFrameArguments.class),
SCOPES("scopes", ScopesArguments.class),
VARIABLES("variables", VariablesArguments.class),
SETVARIABLE("setVariable", SetVariableArguments.class),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ public static class Capabilities {
public boolean supportsHitConditionalBreakpoints;
public boolean supportsConditionalBreakpoints;
public boolean supportsEvaluateForHovers;
public boolean supportsRestartFrame;
public boolean supportsSetVariable;
public boolean supportsRestartRequest;
public boolean supportTerminateDebuggee;
Expand Down