WARNING: this should only be called in the async portion of a request handler, otherwise a deadlock can occur.
(ctx context.Context, s *Server, info lsproto.RequestInfo[Req, Resp], params Req)
| 605 | // WARNING: this should only be called in the async portion of a request handler, |
| 606 | // otherwise a deadlock can occur. |
| 607 | func sendClientRequest[Req, Resp any](ctx context.Context, s *Server, info lsproto.RequestInfo[Req, Resp], params Req) (Resp, error) { |
| 608 | id := jsonrpc.NewIDString(fmt.Sprintf("ts%d", s.clientSeq.Add(1))) |
| 609 | req := info.NewRequestMessage(id, params) |
| 610 | |
| 611 | responseChan := make(chan *lsproto.ResponseMessage, 1) |
| 612 | s.pendingServerRequestsMu.Lock() |
| 613 | s.pendingServerRequests[*id] = responseChan |
| 614 | s.pendingServerRequestsMu.Unlock() |
| 615 | |
| 616 | defer func() { |
| 617 | s.pendingServerRequestsMu.Lock() |
| 618 | defer s.pendingServerRequestsMu.Unlock() |
| 619 | if respChan, ok := s.pendingServerRequests[*id]; ok { |
| 620 | close(respChan) |
| 621 | delete(s.pendingServerRequests, *id) |
| 622 | } |
| 623 | }() |
| 624 | |
| 625 | if err := s.send(req.Message()); err != nil { |
| 626 | return *new(Resp), err |
| 627 | } |
| 628 | |
| 629 | select { |
| 630 | case <-ctx.Done(): |
| 631 | return *new(Resp), ctx.Err() |
| 632 | case resp := <-responseChan: |
| 633 | if resp.Error != nil { |
| 634 | return *new(Resp), fmt.Errorf("request failed: %s", resp.Error.String()) |
| 635 | } |
| 636 | return info.UnmarshalResult(resp.Result) |
| 637 | } |
| 638 | } |
| 639 | |
| 640 | // sendClientRequestFireAndForget sends a request to the client without waiting for a response. |
| 641 | // The response, if any, will be silently ignored by the read loop since no pending channel is registered. |
no test coverage detected