service/dap: send continued event before step response (#2594)
* service/dap: send continued event before step response Send the continued event before the step response to make sure that there is no time where the client believes that only a single thread is running. Updates golang/vscode-go#1617 * move to helper
This commit is contained in:
parent
38aaf274a9
commit
776b86ffc2
@ -39,16 +39,16 @@ func (c *Client) Expect{{.}}(t *testing.T) *dap.{{.}} {
|
|||||||
|
|
||||||
// Check{{.}} fails the test if m is not *{{.}}.
|
// Check{{.}} fails the test if m is not *{{.}}.
|
||||||
func (c *Client) Check{{.}}(t *testing.T, m dap.Message) *dap.{{.}} {
|
func (c *Client) Check{{.}}(t *testing.T, m dap.Message) *dap.{{.}} {
|
||||||
t.Helper()
|
t.Helper(){{if or (or (eq . "StepInResponse") (eq . "StepOutResponse")) (eq . "NextResponse") }}
|
||||||
|
_, ok := m.(*dap.ContinuedEvent)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("got %#v, want *dap.ContinuedEvent", m)
|
||||||
|
}
|
||||||
|
m = c.ExpectMessage(t){{end}}
|
||||||
r, ok := m.(*dap.{{.}})
|
r, ok := m.(*dap.{{.}})
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("got %#v, want *dap.{{.}}", m)
|
t.Fatalf("got %#v, want *dap.{{.}}", m)
|
||||||
}{{if or (or (eq . "StepInResponse") (eq . "StepOutResponse")) (eq . "NextResponse") }}
|
}
|
||||||
m = c.ExpectMessage(t)
|
|
||||||
_, ok = m.(*dap.ContinuedEvent)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("got %#v, want *dap.ContinuedEvent", m)
|
|
||||||
}{{end}}
|
|
||||||
return r
|
return r
|
||||||
}{{end}}
|
}{{end}}
|
||||||
`))
|
`))
|
||||||
|
|||||||
@ -488,15 +488,15 @@ func (c *Client) ExpectNextResponse(t *testing.T) *dap.NextResponse {
|
|||||||
// CheckNextResponse fails the test if m is not *NextResponse.
|
// CheckNextResponse fails the test if m is not *NextResponse.
|
||||||
func (c *Client) CheckNextResponse(t *testing.T, m dap.Message) *dap.NextResponse {
|
func (c *Client) CheckNextResponse(t *testing.T, m dap.Message) *dap.NextResponse {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
_, ok := m.(*dap.ContinuedEvent)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("got %#v, want *dap.ContinuedEvent", m)
|
||||||
|
}
|
||||||
|
m = c.ExpectMessage(t)
|
||||||
r, ok := m.(*dap.NextResponse)
|
r, ok := m.(*dap.NextResponse)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("got %#v, want *dap.NextResponse", m)
|
t.Fatalf("got %#v, want *dap.NextResponse", m)
|
||||||
}
|
}
|
||||||
m = c.ExpectMessage(t)
|
|
||||||
_, ok = m.(*dap.ContinuedEvent)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("got %#v, want *dap.ContinuedEvent", m)
|
|
||||||
}
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -907,15 +907,15 @@ func (c *Client) ExpectStepInResponse(t *testing.T) *dap.StepInResponse {
|
|||||||
// CheckStepInResponse fails the test if m is not *StepInResponse.
|
// CheckStepInResponse fails the test if m is not *StepInResponse.
|
||||||
func (c *Client) CheckStepInResponse(t *testing.T, m dap.Message) *dap.StepInResponse {
|
func (c *Client) CheckStepInResponse(t *testing.T, m dap.Message) *dap.StepInResponse {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
_, ok := m.(*dap.ContinuedEvent)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("got %#v, want *dap.ContinuedEvent", m)
|
||||||
|
}
|
||||||
|
m = c.ExpectMessage(t)
|
||||||
r, ok := m.(*dap.StepInResponse)
|
r, ok := m.(*dap.StepInResponse)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("got %#v, want *dap.StepInResponse", m)
|
t.Fatalf("got %#v, want *dap.StepInResponse", m)
|
||||||
}
|
}
|
||||||
m = c.ExpectMessage(t)
|
|
||||||
_, ok = m.(*dap.ContinuedEvent)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("got %#v, want *dap.ContinuedEvent", m)
|
|
||||||
}
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -948,15 +948,15 @@ func (c *Client) ExpectStepOutResponse(t *testing.T) *dap.StepOutResponse {
|
|||||||
// CheckStepOutResponse fails the test if m is not *StepOutResponse.
|
// CheckStepOutResponse fails the test if m is not *StepOutResponse.
|
||||||
func (c *Client) CheckStepOutResponse(t *testing.T, m dap.Message) *dap.StepOutResponse {
|
func (c *Client) CheckStepOutResponse(t *testing.T, m dap.Message) *dap.StepOutResponse {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
_, ok := m.(*dap.ContinuedEvent)
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("got %#v, want *dap.ContinuedEvent", m)
|
||||||
|
}
|
||||||
|
m = c.ExpectMessage(t)
|
||||||
r, ok := m.(*dap.StepOutResponse)
|
r, ok := m.(*dap.StepOutResponse)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatalf("got %#v, want *dap.StepOutResponse", m)
|
t.Fatalf("got %#v, want *dap.StepOutResponse", m)
|
||||||
}
|
}
|
||||||
m = c.ExpectMessage(t)
|
|
||||||
_, ok = m.(*dap.ContinuedEvent)
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("got %#v, want *dap.ContinuedEvent", m)
|
|
||||||
}
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1510,24 +1510,37 @@ func (s *Server) onAttachRequest(request *dap.AttachRequest) {
|
|||||||
// onNextRequest handles 'next' request.
|
// onNextRequest handles 'next' request.
|
||||||
// This is a mandatory request to support.
|
// This is a mandatory request to support.
|
||||||
func (s *Server) onNextRequest(request *dap.NextRequest, asyncSetupDone chan struct{}) {
|
func (s *Server) onNextRequest(request *dap.NextRequest, asyncSetupDone chan struct{}) {
|
||||||
s.send(&dap.NextResponse{Response: *newResponse(request.Request)})
|
s.sendStepResponse(request.Arguments.ThreadId, &dap.NextResponse{Response: *newResponse(request.Request)})
|
||||||
s.doStepCommand(api.Next, request.Arguments.ThreadId, asyncSetupDone)
|
s.doStepCommand(api.Next, request.Arguments.ThreadId, asyncSetupDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
// onStepInRequest handles 'stepIn' request
|
// onStepInRequest handles 'stepIn' request
|
||||||
// This is a mandatory request to support.
|
// This is a mandatory request to support.
|
||||||
func (s *Server) onStepInRequest(request *dap.StepInRequest, asyncSetupDone chan struct{}) {
|
func (s *Server) onStepInRequest(request *dap.StepInRequest, asyncSetupDone chan struct{}) {
|
||||||
s.send(&dap.StepInResponse{Response: *newResponse(request.Request)})
|
s.sendStepResponse(request.Arguments.ThreadId, &dap.StepInResponse{Response: *newResponse(request.Request)})
|
||||||
s.doStepCommand(api.Step, request.Arguments.ThreadId, asyncSetupDone)
|
s.doStepCommand(api.Step, request.Arguments.ThreadId, asyncSetupDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
// onStepOutRequest handles 'stepOut' request
|
// onStepOutRequest handles 'stepOut' request
|
||||||
// This is a mandatory request to support.
|
// This is a mandatory request to support.
|
||||||
func (s *Server) onStepOutRequest(request *dap.StepOutRequest, asyncSetupDone chan struct{}) {
|
func (s *Server) onStepOutRequest(request *dap.StepOutRequest, asyncSetupDone chan struct{}) {
|
||||||
s.send(&dap.StepOutResponse{Response: *newResponse(request.Request)})
|
s.sendStepResponse(request.Arguments.ThreadId, &dap.StepOutResponse{Response: *newResponse(request.Request)})
|
||||||
s.doStepCommand(api.StepOut, request.Arguments.ThreadId, asyncSetupDone)
|
s.doStepCommand(api.StepOut, request.Arguments.ThreadId, asyncSetupDone)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) sendStepResponse(threadId int, message dap.Message) {
|
||||||
|
// All of the threads will be continued by this request, so we need to send
|
||||||
|
// a continued event so the UI can properly reflect the current state.
|
||||||
|
s.send(&dap.ContinuedEvent{
|
||||||
|
Event: *newEvent("continued"),
|
||||||
|
Body: dap.ContinuedEventBody{
|
||||||
|
ThreadId: threadId,
|
||||||
|
AllThreadsContinued: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
s.send(message)
|
||||||
|
}
|
||||||
|
|
||||||
func stoppedGoroutineID(state *api.DebuggerState) (id int) {
|
func stoppedGoroutineID(state *api.DebuggerState) (id int) {
|
||||||
if state.SelectedGoroutine != nil {
|
if state.SelectedGoroutine != nil {
|
||||||
id = state.SelectedGoroutine.ID
|
id = state.SelectedGoroutine.ID
|
||||||
@ -1544,15 +1557,6 @@ func stoppedGoroutineID(state *api.DebuggerState) (id int) {
|
|||||||
// due to an error, so the server is ready to receive new requests.
|
// due to an error, so the server is ready to receive new requests.
|
||||||
func (s *Server) doStepCommand(command string, threadId int, asyncSetupDone chan struct{}) {
|
func (s *Server) doStepCommand(command string, threadId int, asyncSetupDone chan struct{}) {
|
||||||
defer s.asyncCommandDone(asyncSetupDone)
|
defer s.asyncCommandDone(asyncSetupDone)
|
||||||
// All of the threads will be continued by this request, so we need to send
|
|
||||||
// a continued event so the UI can properly reflect the current state.
|
|
||||||
s.send(&dap.ContinuedEvent{
|
|
||||||
Event: *newEvent("continued"),
|
|
||||||
Body: dap.ContinuedEventBody{
|
|
||||||
ThreadId: threadId,
|
|
||||||
AllThreadsContinued: true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
_, err := s.debugger.Command(&api.DebuggerCommand{Name: api.SwitchGoroutine, GoroutineID: threadId}, nil)
|
_, err := s.debugger.Command(&api.DebuggerCommand{Name: api.SwitchGoroutine, GoroutineID: threadId}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.log.Errorf("Error switching goroutines while stepping: %v", err)
|
s.log.Errorf("Error switching goroutines while stepping: %v", err)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user