diff --git a/service/dap/daptest/client.go b/service/dap/daptest/client.go index 1a97e428..67a70966 100644 --- a/service/dap/daptest/client.go +++ b/service/dap/daptest/client.go @@ -59,16 +59,35 @@ func (c *Client) expectReadProtocolMessage(t *testing.T) dap.Message { return m } -func (c *Client) ExpectDisconnectResponse(t *testing.T) *dap.DisconnectResponse { - t.Helper() - return c.expectReadProtocolMessage(t).(*dap.DisconnectResponse) -} - func (c *Client) ExpectErrorResponse(t *testing.T) *dap.ErrorResponse { t.Helper() return c.expectReadProtocolMessage(t).(*dap.ErrorResponse) } +func (c *Client) expectErrorResponse(t *testing.T, id int, message string) *dap.ErrorResponse { + t.Helper() + er := c.expectReadProtocolMessage(t).(*dap.ErrorResponse) + if er.Body.Error.Id != id || er.Message != message { + t.Errorf("\ngot %#v\nwant Id=%d Message=%q", er, id, message) + } + return er +} + +func (c *Client) ExpectNotYetImplementedErrorResponse(t *testing.T) *dap.ErrorResponse { + t.Helper() + return c.expectErrorResponse(t, 7777, "Not yet implemented") +} + +func (c *Client) ExpectUnsupportedCommandErrorResponse(t *testing.T) *dap.ErrorResponse { + t.Helper() + return c.expectErrorResponse(t, 9999, "Unsupported command") +} + +func (c *Client) ExpectDisconnectResponse(t *testing.T) *dap.DisconnectResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.DisconnectResponse) +} + func (c *Client) ExpectContinueResponse(t *testing.T) *dap.ContinueResponse { t.Helper() return c.expectReadProtocolMessage(t).(*dap.ContinueResponse) @@ -128,6 +147,106 @@ func (c *Client) ExpectStackTraceResponse(t *testing.T) *dap.StackTraceResponse return c.expectReadProtocolMessage(t).(*dap.StackTraceResponse) } +func (c *Client) ExpectTerminateResponse(t *testing.T) *dap.TerminateResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.TerminateResponse) +} + +func (c *Client) ExpectRestartResponse(t *testing.T) *dap.RestartResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.RestartResponse) +} + +func (c *Client) ExpectSetFunctionBreakpointsResponse(t *testing.T) *dap.SetFunctionBreakpointsResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.SetFunctionBreakpointsResponse) +} + +func (c *Client) ExpectStepBackResponse(t *testing.T) *dap.StepBackResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.StepBackResponse) +} + +func (c *Client) ExpectReverseContinueResponse(t *testing.T) *dap.ReverseContinueResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.ReverseContinueResponse) +} + +func (c *Client) ExpectRestartFrameResponse(t *testing.T) *dap.RestartFrameResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.RestartFrameResponse) +} + +func (c *Client) ExpectSetExpressionResponse(t *testing.T) *dap.SetExpressionResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.SetExpressionResponse) +} + +func (c *Client) ExpectTerminateThreadsResponse(t *testing.T) *dap.TerminateThreadsResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.TerminateThreadsResponse) +} + +func (c *Client) ExpectStepInTargetsResponse(t *testing.T) *dap.StepInTargetsResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.StepInTargetsResponse) +} + +func (c *Client) ExpectGotoTargetsResponse(t *testing.T) *dap.GotoTargetsResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.GotoTargetsResponse) +} + +func (c *Client) ExpectCompletionsResponse(t *testing.T) *dap.CompletionsResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.CompletionsResponse) +} + +func (c *Client) ExpectExceptionInfoResponse(t *testing.T) *dap.ExceptionInfoResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.ExceptionInfoResponse) +} + +func (c *Client) ExpectLoadedSourcesResponse(t *testing.T) *dap.LoadedSourcesResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.LoadedSourcesResponse) +} + +func (c *Client) ExpectDataBreakpointInfoResponse(t *testing.T) *dap.DataBreakpointInfoResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.DataBreakpointInfoResponse) +} + +func (c *Client) ExpectSetDataBreakpointsResponse(t *testing.T) *dap.SetDataBreakpointsResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.SetDataBreakpointsResponse) +} + +func (c *Client) ExpectReadMemoryResponse(t *testing.T) *dap.ReadMemoryResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.ReadMemoryResponse) +} + +func (c *Client) ExpectDisassembleResponse(t *testing.T) *dap.DisassembleResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.DisassembleResponse) +} + +func (c *Client) ExpectCancelResponse(t *testing.T) *dap.CancelResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.CancelResponse) +} + +func (c *Client) ExpectBreakpointLocationsResponse(t *testing.T) *dap.BreakpointLocationsResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.BreakpointLocationsResponse) +} + +func (c *Client) ExpectModulesResponse(t *testing.T) *dap.ModulesResponse { + t.Helper() + return c.expectReadProtocolMessage(t).(*dap.ModulesResponse) +} + // InitializeRequest sends an 'initialize' request. func (c *Client) InitializeRequest() { request := &dap.InitializeRequest{Request: *c.newRequest("initialize")} @@ -165,6 +284,13 @@ func (c *Client) LaunchRequestWithArgs(arguments map[string]interface{}) { c.send(request) } +// AttachRequest sends an 'attach' request. +func (c *Client) AttachRequest() { + request := &dap.AttachRequest{Request: *c.newRequest("attach")} + // TODO(polina): populate meaningful arguments + c.send(request) +} + // DisconnectRequest sends a 'disconnect' request. func (c *Client) DisconnectRequest() { request := &dap.DisconnectRequest{Request: *c.newRequest("disconnect")} @@ -207,6 +333,34 @@ func (c *Client) ContinueRequest(thread int) { c.send(request) } +// NextRequest sends a 'next' request. +func (c *Client) NextRequest() { + request := &dap.NextRequest{Request: *c.newRequest("next")} + // TODO(polina): arguments + c.send(request) +} + +// StepInRequest sends a 'stepIn' request. +func (c *Client) StepInRequest() { + request := &dap.NextRequest{Request: *c.newRequest("stepIn")} + // TODO(polina): arguments + c.send(request) +} + +// StepOutRequest sends a 'stepOut' request. +func (c *Client) StepOutRequest() { + request := &dap.NextRequest{Request: *c.newRequest("stepOut")} + // TODO(polina): arguments + c.send(request) +} + +// PauseRequest sends a 'pause' request. +func (c *Client) PauseRequest() { + request := &dap.NextRequest{Request: *c.newRequest("pause")} + // TODO(polina): arguments + c.send(request) +} + // ThreadsRequest sends a 'threads' request. func (c *Client) ThreadsRequest() { request := &dap.ThreadsRequest{Request: *c.newRequest("threads")} @@ -219,6 +373,138 @@ func (c *Client) StackTraceRequest() { c.send(request) } +// ScopesRequest sends a 'scopes' request. +func (c *Client) ScopesRequest() { + request := &dap.ScopesRequest{Request: *c.newRequest("scopes")} + c.send(request) +} + +// VariablesRequest sends a 'scopes' request. +func (c *Client) VariablesRequest() { + request := &dap.ScopesRequest{Request: *c.newRequest("variables")} + c.send(request) +} + +// TeriminateRequest sends a 'terminate' request. +func (c *Client) TerminateRequest() { + c.send(&dap.TerminateRequest{Request: *c.newRequest("terminate")}) +} + +// RestartRequest sends a 'restart' request. +func (c *Client) RestartRequest() { + c.send(&dap.RestartRequest{Request: *c.newRequest("restart")}) +} + +// SetFunctionBreakpointsRequest sends a 'setFunctionBreakpoints' request. +func (c *Client) SetFunctionBreakpointsRequest() { + c.send(&dap.SetFunctionBreakpointsRequest{Request: *c.newRequest("setFunctionBreakpoints")}) +} + +// StepBackRequest sends a 'stepBack' request. +func (c *Client) StepBackRequest() { + c.send(&dap.StepBackRequest{Request: *c.newRequest("stepBack")}) +} + +// ReverseContinueRequest sends a 'reverseContinue' request. +func (c *Client) ReverseContinueRequest() { + c.send(&dap.ReverseContinueRequest{Request: *c.newRequest("reverseContinue")}) +} + +// SetVariableRequest sends a 'setVariable' request. +func (c *Client) SetVariableRequest() { + c.send(&dap.ReverseContinueRequest{Request: *c.newRequest("setVariable")}) +} + +// RestartFrameRequest sends a 'restartFrame' request. +func (c *Client) RestartFrameRequest() { + c.send(&dap.RestartFrameRequest{Request: *c.newRequest("restartFrame")}) +} + +// GotoRequest sends a 'goto' request. +func (c *Client) GotoRequest() { + c.send(&dap.GotoRequest{Request: *c.newRequest("goto")}) +} + +// SetExpressionRequest sends a 'setExpression' request. +func (c *Client) SetExpressionRequest() { + c.send(&dap.SetExpressionRequest{Request: *c.newRequest("setExpression")}) +} + +// SourceRequest sends a 'source' request. +func (c *Client) SourceRequest() { + c.send(&dap.SourceRequest{Request: *c.newRequest("source")}) +} + +// TerminateThreadsRequest sends a 'terminateThreads' request. +func (c *Client) TerminateThreadsRequest() { + c.send(&dap.TerminateThreadsRequest{Request: *c.newRequest("terminateThreads")}) +} + +// EvaluateRequest sends a 'evaluate' request. +func (c *Client) EvaluateRequest() { + c.send(&dap.EvaluateRequest{Request: *c.newRequest("evaluate")}) +} + +// StepInTargetsRequest sends a 'stepInTargets' request. +func (c *Client) StepInTargetsRequest() { + c.send(&dap.StepInTargetsRequest{Request: *c.newRequest("stepInTargets")}) +} + +// GotoTargetsRequest sends a 'gotoTargets' request. +func (c *Client) GotoTargetsRequest() { + c.send(&dap.GotoTargetsRequest{Request: *c.newRequest("gotoTargets")}) +} + +// CompletionsRequest sends a 'completions' request. +func (c *Client) CompletionsRequest() { + c.send(&dap.CompletionsRequest{Request: *c.newRequest("completions")}) +} + +// ExceptionInfoRequest sends a 'exceptionInfo' request. +func (c *Client) ExceptionInfoRequest() { + c.send(&dap.ExceptionInfoRequest{Request: *c.newRequest("exceptionInfo")}) +} + +// LoadedSourcesRequest sends a 'loadedSources' request. +func (c *Client) LoadedSourcesRequest() { + c.send(&dap.LoadedSourcesRequest{Request: *c.newRequest("loadedSources")}) +} + +// DataBreakpointInfoRequest sends a 'dataBreakpointInfo' request. +func (c *Client) DataBreakpointInfoRequest() { + c.send(&dap.DataBreakpointInfoRequest{Request: *c.newRequest("dataBreakpointInfo")}) +} + +// SetDataBreakpointsRequest sends a 'setDataBreakpoints' request. +func (c *Client) SetDataBreakpointsRequest() { + c.send(&dap.SetDataBreakpointsRequest{Request: *c.newRequest("setDataBreakpoints")}) +} + +// ReadMemoryRequest sends a 'readMemory' request. +func (c *Client) ReadMemoryRequest() { + c.send(&dap.ReadMemoryRequest{Request: *c.newRequest("readMemory")}) +} + +// DisassembleRequest sends a 'disassemble' request. +func (c *Client) DisassembleRequest() { + c.send(&dap.DisassembleRequest{Request: *c.newRequest("disassemble")}) +} + +// CancelRequest sends a 'cancel' request. +func (c *Client) CancelRequest() { + c.send(&dap.CancelRequest{Request: *c.newRequest("cancel")}) +} + +// BreakpointLocationsRequest sends a 'breakpointLocations' request. +func (c *Client) BreakpointLocationsRequest() { + c.send(&dap.BreakpointLocationsRequest{Request: *c.newRequest("breakpointLocations")}) +} + +// ModulesRequest sends a 'modules' request. +func (c *Client) ModulesRequest() { + c.send(&dap.ModulesRequest{Request: *c.newRequest("modules")}) +} + // UnknownRequest triggers dap.DecodeProtocolMessageFieldError. func (c *Client) UnknownRequest() { request := c.newRequest("unknown") diff --git a/service/dap/error_ids.go b/service/dap/error_ids.go index 9f1b9f05..6fbd0b6c 100644 --- a/service/dap/error_ids.go +++ b/service/dap/error_ids.go @@ -4,6 +4,7 @@ package dap const ( UnsupportedCommand int = 9999 InternalError int = 8888 + NotYetImplemented int = 7777 // The values below come from the vscode-go debug adaptor. // Although the spec says they should be unique, the adaptor diff --git a/service/dap/server.go b/service/dap/server.go index 3ce27b6c..847de76f 100644 --- a/service/dap/server.go +++ b/service/dap/server.go @@ -194,82 +194,150 @@ func (s *Server) handleRequest(request dap.Message) { switch request := request.(type) { case *dap.InitializeRequest: + // Required s.onInitializeRequest(request) case *dap.LaunchRequest: + // Required s.onLaunchRequest(request) case *dap.AttachRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Required + // TODO: implement this request in V0 + s.onAttachRequest(request) case *dap.DisconnectRequest: + // Required s.onDisconnectRequest(request) case *dap.TerminateRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Optional (capability ‘supportsTerminateRequest‘) + // TODO: implement this request in V1 + s.onTerminateRequest(request) case *dap.RestartRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Optional (capability ‘supportsRestartRequest’) + // TODO: implement this request in V1 + s.onRestartRequest(request) case *dap.SetBreakpointsRequest: + // Required s.onSetBreakpointsRequest(request) case *dap.SetFunctionBreakpointsRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Optional (capability ‘supportsFunctionBreakpoints’) + // TODO: implement this request in V1 + s.onSetFunctionBreakpointsRequest(request) case *dap.SetExceptionBreakpointsRequest: + // Optional (capability ‘exceptionBreakpointFilters’) s.onSetExceptionBreakpointsRequest(request) case *dap.ConfigurationDoneRequest: + // Optional (capability ‘supportsConfigurationDoneRequest’) + // Supported by vscode-go s.onConfigurationDoneRequest(request) case *dap.ContinueRequest: + // Required s.onContinueRequest(request) case *dap.NextRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Required + // TODO: implement this request in V0 + s.onNextRequest(request) case *dap.StepInRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Required + // TODO: implement this request in V0 + s.onStepInRequest(request) case *dap.StepOutRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Required + // TODO: implement this request in V0 + s.onStepOutRequest(request) case *dap.StepBackRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Optional (capability ‘supportsStepBack’) + // TODO: implement this request in V1 + s.onStepBackRequest(request) case *dap.ReverseContinueRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Optional (capability ‘supportsStepBack’) + // TODO: implement this request in V1 + s.onReverseContinueRequest(request) case *dap.RestartFrameRequest: + // Optional (capability ’supportsRestartFrame’) s.sendUnsupportedErrorResponse(request.Request) case *dap.GotoRequest: + // Optional (capability ‘supportsGotoTargetsRequest’) s.sendUnsupportedErrorResponse(request.Request) case *dap.PauseRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Required + // TODO: implement this request in V0 + s.onPauseRequest(request) case *dap.StackTraceRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Required + // TODO: implement this request in V0 + s.onStackTraceRequest(request) case *dap.ScopesRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Required + // TODO: implement this request in V0 + s.onScopesRequest(request) case *dap.VariablesRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Required + // TODO: implement this request in V0 + s.onVariablesRequest(request) case *dap.SetVariableRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Optional (capability ‘supportsSetVariable’) + // Supported by vscode-go + // TODO: implement this request in V0 + s.onSetVariableRequest(request) case *dap.SetExpressionRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Optional (capability ‘supportsSetExpression’) + // TODO: implement this request in V1 + s.onSetExpressionRequest(request) case *dap.SourceRequest: + // Required + // This does not make sense in the context of Go as + // the source cannot be a string eval'ed at runtime. s.sendUnsupportedErrorResponse(request.Request) case *dap.ThreadsRequest: + // Required s.onThreadsRequest(request) case *dap.TerminateThreadsRequest: + // Optional (capability ‘supportsTerminateThreadsRequest’) s.sendUnsupportedErrorResponse(request.Request) case *dap.EvaluateRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Required - TODO + // TODO: implement this request in V0 + s.onEvaluateRequest(request) case *dap.StepInTargetsRequest: + // Optional (capability ‘supportsStepInTargetsRequest’) s.sendUnsupportedErrorResponse(request.Request) case *dap.GotoTargetsRequest: + // Optional (capability ‘supportsGotoTargetsRequest’) s.sendUnsupportedErrorResponse(request.Request) case *dap.CompletionsRequest: + // Optional (capability ‘supportsCompletionsRequest’) s.sendUnsupportedErrorResponse(request.Request) case *dap.ExceptionInfoRequest: + // Optional (capability ‘supportsExceptionInfoRequest’) + // TODO: does this request make sense for delve? s.sendUnsupportedErrorResponse(request.Request) case *dap.LoadedSourcesRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Optional (capability ‘supportsLoadedSourcesRequest’) + // TODO: implement this request in V1 + s.onLoadedSourcesRequest(request) case *dap.DataBreakpointInfoRequest: + // Optional (capability ‘supportsDataBreakpoints’) s.sendUnsupportedErrorResponse(request.Request) case *dap.SetDataBreakpointsRequest: + // Optional (capability ‘supportsDataBreakpoints’) s.sendUnsupportedErrorResponse(request.Request) case *dap.ReadMemoryRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Optional (capability ‘supportsReadMemoryRequest‘) + // TODO: implement this request in V1 + s.onReadMemoryRequest(request) case *dap.DisassembleRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Optional (capability ‘supportsDisassembleRequest’) + // TODO: implement this request in V1 + s.onDisassembleRequest(request) case *dap.CancelRequest: - s.sendUnsupportedErrorResponse(request.Request) + // Optional (capability ‘supportsCancelRequest’) + // TODO: does this request make sense for delve? + s.onCancelRequest(request) case *dap.BreakpointLocationsRequest: + // Optional (capability ‘supportsBreakpointLocationsRequest’) + s.sendUnsupportedErrorResponse(request.Request) + case *dap.ModulesRequest: + // Optional (capability ‘supportsModulesRequest’) + // TODO: does this request make sense for delve? s.sendUnsupportedErrorResponse(request.Request) default: // This is a DAP message that go-dap has a struct for, so @@ -291,6 +359,16 @@ func (s *Server) onInitializeRequest(request *dap.InitializeRequest) { response.Body.SupportsConfigurationDoneRequest = true // TODO(polina): support this to match vscode-go functionality response.Body.SupportsSetVariable = false + // TODO(polina): support these requests in addition to vscode-go feature parity + response.Body.SupportsTerminateRequest = false + response.Body.SupportsRestartRequest = false + response.Body.SupportsFunctionBreakpoints = false + response.Body.SupportsStepBack = false + response.Body.SupportsSetExpression = false + response.Body.SupportsLoadedSourcesRequest = false + response.Body.SupportsReadMemoryRequest = false + response.Body.SupportsDisassembleRequest = false + response.Body.SupportsCancelRequest = false s.send(response) } @@ -422,7 +500,7 @@ func (s *Server) onSetBreakpointsRequest(request *dap.SetBreakpointsRequest) { func (s *Server) onSetExceptionBreakpointsRequest(request *dap.SetExceptionBreakpointsRequest) { // Unlike what DAP documentation claims, this request is always sent - // even though we specified no filters at initializatin. Handle as no-op. + // even though we specified no filters at initialization. Handle as no-op. s.send(&dap.SetExceptionBreakpointsResponse{Response: *newResponse(request.Request)}) } @@ -488,6 +566,126 @@ func (s *Server) onThreadsRequest(request *dap.ThreadsRequest) { s.send(response) } +// onAttachRequest sends a not-yet-implemented error response. +// This is a mandatory request to support. +func (s *Server) onAttachRequest(request *dap.AttachRequest) { // TODO V0 + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onNextRequest sends a not-yet-implemented error response. +// This is a mandatory request to support. +func (s *Server) onNextRequest(request *dap.NextRequest) { // TODO V0 + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onStepInRequest sends a not-yet-implemented error response. +// This is a mandatory request to support. +func (s *Server) onStepInRequest(request *dap.StepInRequest) { // TODO V0 + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onStepOutRequest sends a not-yet-implemented error response. +// This is a mandatory request to support. +func (s *Server) onStepOutRequest(request *dap.StepOutRequest) { // TODO V0 + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onPauseRequest sends a not-yet-implemented error response. +// This is a mandatory request to support. +func (s *Server) onPauseRequest(request *dap.PauseRequest) { // TODO V0 + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onStackTraceRequest sends a not-yet-implemented error response. +// This is a mandatory request to support. +func (s *Server) onStackTraceRequest(request *dap.StackTraceRequest) { // TODO V0 + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onScopesRequest sends a not-yet-implemented error response. +// This is a mandatory request to support. +func (s *Server) onScopesRequest(request *dap.ScopesRequest) { // TODO V0 + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onVariablesRequest sends a not-yet-implemented error response. +// This is a mandatory request to support. +func (s *Server) onVariablesRequest(request *dap.VariablesRequest) { // TODO V0 + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onEvaluateRequest sends a not-yet-implemented error response. +// This is a mandatory request to support. +func (s *Server) onEvaluateRequest(request *dap.EvaluateRequest) { // TODO V0 + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onTerminateRequest sends a not-yet-implemented error response. +// Capability 'supportsTerminateRequest' is not set in 'initialize' response. +func (s *Server) onTerminateRequest(request *dap.TerminateRequest) { + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onRestartRequest sends a not-yet-implemented error response +// Capability 'supportsRestartRequest' is not set in 'initialize' response. +func (s *Server) onRestartRequest(request *dap.RestartRequest) { + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onSetFunctionBreakpointsRequest sends a not-yet-implemented error response. +// Capability 'supportsFunctionBreakpoints' is not set 'initialize' response. +func (s *Server) onSetFunctionBreakpointsRequest(request *dap.SetFunctionBreakpointsRequest) { + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onStepBackRequest sends a not-yet-implemented error response. +// Capability 'supportsStepBack' is not set 'initialize' response. +func (s *Server) onStepBackRequest(request *dap.StepBackRequest) { + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onReverseContinueRequest sends a not-yet-implemented error response. +// Capability 'supportsStepBack' is not set 'initialize' response. +func (s *Server) onReverseContinueRequest(request *dap.ReverseContinueRequest) { + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onSetVariableRequest sends a not-yet-implemented error response. +// Capability 'supportsSetVariable' is not set 'initialize' response. +func (s *Server) onSetVariableRequest(request *dap.SetVariableRequest) { // TODO V0 + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onSetExpression sends a not-yet-implemented error response. +// Capability 'supportsSetExpression' is not set 'initialize' response. +func (s *Server) onSetExpressionRequest(request *dap.SetExpressionRequest) { + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onLoadedSourcesRequest sends a not-yet-implemented error response. +// Capability 'supportsLoadedSourcesRequest' is not set 'initialize' response. +func (s *Server) onLoadedSourcesRequest(request *dap.LoadedSourcesRequest) { + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onReadMemoryRequest sends a not-yet-implemented error response. +// Capability 'supportsReadMemoryRequest' is not set 'initialize' response. +func (s *Server) onReadMemoryRequest(request *dap.ReadMemoryRequest) { + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onDisassembleRequest sends a not-yet-implemented error response. +// Capability 'supportsDisassembleRequest' is not set 'initialize' response. +func (s *Server) onDisassembleRequest(request *dap.DisassembleRequest) { + s.sendNotYetImplementedErrorResponse(request.Request) +} + +// onCancelRequest sends a not-yet-implemented error response. +// Capability 'supportsCancelRequest' is not set 'initialize' response. +func (s *Server) onCancelRequest(request *dap.CancelRequest) { + s.sendNotYetImplementedErrorResponse(request.Request) +} + func (s *Server) sendErrorResponse(request dap.Request, id int, summary string, details string) { er := &dap.ErrorResponse{} er.Type = "response" @@ -521,6 +719,11 @@ func (s *Server) sendUnsupportedErrorResponse(request dap.Request) { fmt.Sprintf("cannot process '%s' request", request.Command)) } +func (s *Server) sendNotYetImplementedErrorResponse(request dap.Request) { + s.sendErrorResponse(request, NotYetImplemented, "Not yet implemented", + fmt.Sprintf("cannot process '%s' request", request.Command)) +} + func newResponse(request dap.Request) *dap.Response { return &dap.Response{ ProtocolMessage: dap.ProtocolMessage{ diff --git a/service/dap/server_test.go b/service/dap/server_test.go index f578676c..2577419e 100644 --- a/service/dap/server_test.go +++ b/service/dap/server_test.go @@ -168,15 +168,15 @@ func TestStopOnEntry(t *testing.T) { // 8 >> stackTrace, << stackTrace client.StackTraceRequest() stResp := client.ExpectErrorResponse(t) - if stResp.Seq != 0 || stResp.RequestSeq != 8 || stResp.Message != "Unsupported command" { - t.Errorf("\ngot %#v\nwant Seq=0, RequestSeq=8 Message=\"Unsupported command\"", stResp) + if stResp.Seq != 0 || stResp.RequestSeq != 8 || stResp.Message != "Not yet implemented" { + t.Errorf("\ngot %#v\nwant Seq=0, RequestSeq=8 Message=\"Not yet implemented\"", stResp) } // 9 >> stackTrace, << stackTrace client.StackTraceRequest() stResp = client.ExpectErrorResponse(t) - if stResp.Seq != 0 || stResp.RequestSeq != 9 || stResp.Message != "Unsupported command" { - t.Errorf("\ngot %#v\nwant Seq=0, RequestSeq=9 Message=\"Unsupported command\"", stResp) + if stResp.Seq != 0 || stResp.RequestSeq != 9 || stResp.Message != "Not yet implemented" { + t.Errorf("\ngot %#v\nwant Seq=0, RequestSeq=9 Message=\"Not yet implemented\"", stResp) } // 10 >> continue, << continue, << terminated @@ -366,6 +366,147 @@ func TestLaunchTestRequest(t *testing.T) { }) } +func TestUnupportedCommandResponses(t *testing.T) { + var got *dap.ErrorResponse + runTest(t, "increment", func(client *daptest.Client, fixture protest.Fixture) { + seqCnt := 1 + expectUnsupportedCommand := func(cmd string) { + t.Helper() + got = client.ExpectUnsupportedCommandErrorResponse(t) + if got.RequestSeq != seqCnt || got.Command != cmd { + t.Errorf("\ngot %#v\nwant RequestSeq=%d Command=%s", got, seqCnt, cmd) + } + seqCnt++ + } + + client.RestartFrameRequest() + expectUnsupportedCommand("restartFrame") + + client.GotoRequest() + expectUnsupportedCommand("goto") + + client.SourceRequest() + expectUnsupportedCommand("source") + + client.TerminateThreadsRequest() + expectUnsupportedCommand("terminateThreads") + + client.StepInTargetsRequest() + expectUnsupportedCommand("stepInTargets") + + client.GotoTargetsRequest() + expectUnsupportedCommand("gotoTargets") + + client.CompletionsRequest() + expectUnsupportedCommand("completions") + + client.ExceptionInfoRequest() + expectUnsupportedCommand("exceptionInfo") + + client.DataBreakpointInfoRequest() + expectUnsupportedCommand("dataBreakpointInfo") + + client.SetDataBreakpointsRequest() + expectUnsupportedCommand("setDataBreakpoints") + + client.BreakpointLocationsRequest() + expectUnsupportedCommand("breakpointLocations") + + client.ModulesRequest() + expectUnsupportedCommand("modules") + }) +} + +func TestRequiredNotYetImplementedResponses(t *testing.T) { + var got *dap.ErrorResponse + runTest(t, "increment", func(client *daptest.Client, fixture protest.Fixture) { + seqCnt := 1 + expectNotYetImplemented := func(cmd string) { + t.Helper() + got = client.ExpectNotYetImplementedErrorResponse(t) + if got.RequestSeq != seqCnt || got.Command != cmd { + t.Errorf("\ngot %#v\nwant RequestSeq=%d Command=%s", got, seqCnt, cmd) + } + seqCnt++ + } + + client.AttachRequest() + expectNotYetImplemented("attach") + + client.NextRequest() + expectNotYetImplemented("next") + + client.StepInRequest() + expectNotYetImplemented("stepIn") + + client.StepOutRequest() + expectNotYetImplemented("stepOut") + + client.PauseRequest() + expectNotYetImplemented("pause") + + client.StackTraceRequest() + expectNotYetImplemented("stackTrace") + + client.ScopesRequest() + expectNotYetImplemented("scopes") + + client.VariablesRequest() + expectNotYetImplemented("variables") + + client.EvaluateRequest() + expectNotYetImplemented("evaluate") + }) +} + +func TestOptionalNotYetImplementedResponses(t *testing.T) { + var got *dap.ErrorResponse + runTest(t, "increment", func(client *daptest.Client, fixture protest.Fixture) { + seqCnt := 1 + expectNotYetImplemented := func(cmd string) { + t.Helper() + got = client.ExpectNotYetImplementedErrorResponse(t) + if got.RequestSeq != seqCnt || got.Command != cmd { + t.Errorf("\ngot %#v\nwant RequestSeq=%d Command=%s", got, seqCnt, cmd) + } + seqCnt++ + } + + client.TerminateRequest() + expectNotYetImplemented("terminate") + + client.RestartRequest() + expectNotYetImplemented("restart") + + client.SetFunctionBreakpointsRequest() + expectNotYetImplemented("setFunctionBreakpoints") + + client.StepBackRequest() + expectNotYetImplemented("stepBack") + + client.ReverseContinueRequest() + expectNotYetImplemented("reverseContinue") + + client.SetVariableRequest() + expectNotYetImplemented("setVariable") + + client.SetExpressionRequest() + expectNotYetImplemented("setExpression") + + client.LoadedSourcesRequest() + expectNotYetImplemented("loadedSources") + + client.ReadMemoryRequest() + expectNotYetImplemented("readMemory") + + client.DisassembleRequest() + expectNotYetImplemented("disassemble") + + client.CancelRequest() + expectNotYetImplemented("cancel") + }) +} + func TestBadLaunchRequests(t *testing.T) { runTest(t, "increment", func(client *daptest.Client, fixture protest.Fixture) { seqCnt := 1