mirror of
https://github.com/c-cube/linol.git
synced 2025-12-06 03:05:31 -05:00
Merge pull request #41 from wintersteiger/christoph/more-error-handlers
Add more error handlers and exception catchers
This commit is contained in:
commit
f09e36523f
7 changed files with 147 additions and 61 deletions
|
|
@ -10,7 +10,9 @@ let ( let* ) x f = f x
|
||||||
let ( and+ ) a b = a, b
|
let ( and+ ) a b = a, b
|
||||||
let return x = x
|
let return x = x
|
||||||
let failwith = failwith
|
let failwith = failwith
|
||||||
let fail = raise
|
|
||||||
|
let fail = Printexc.raise_with_backtrace
|
||||||
|
|
||||||
let stdin = fun () -> stdin
|
let stdin = fun () -> stdin
|
||||||
let stdout = fun () -> stdout
|
let stdout = fun () -> stdout
|
||||||
|
|
||||||
|
|
@ -25,7 +27,12 @@ let default_spawn f =
|
||||||
in
|
in
|
||||||
ignore (Thread.create run ())
|
ignore (Thread.create run ())
|
||||||
|
|
||||||
let catch f g = try f () with e -> g e
|
let catch f g =
|
||||||
|
try f ()
|
||||||
|
with e ->
|
||||||
|
let bt = Printexc.get_raw_backtrace () in
|
||||||
|
g e bt
|
||||||
|
|
||||||
let n_bytes_written = Atomic.make 0
|
let n_bytes_written = Atomic.make 0
|
||||||
let n_bytes_read = Atomic.make 0
|
let n_bytes_read = Atomic.make 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
module Trace = Trace_core
|
module Trace = Trace_core
|
||||||
|
|
||||||
let ( let@ ) = ( @@ )
|
let ( let@ ) = ( @@ )
|
||||||
|
let spf = Printf.sprintf
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,10 @@ module IO_eio :
|
||||||
let return x = x
|
let return x = x
|
||||||
let failwith = failwith
|
let failwith = failwith
|
||||||
let fail = raise
|
let fail = raise
|
||||||
let catch f handler = try f () with exn -> handler exn
|
|
||||||
|
let catch f handler = try f () with exn ->
|
||||||
|
let bt = Printexc.get_raw_backtrace () in
|
||||||
|
handler exn bt
|
||||||
|
|
||||||
let stdin env = Eio.Buf_read.of_flow ~max_size:1_000_000 (Eio.Stdenv.stdin env)
|
let stdin env = Eio.Buf_read.of_flow ~max_size:1_000_000 (Eio.Stdenv.stdin env)
|
||||||
let stdout = Eio.Stdenv.stdout
|
let stdout = Eio.Stdenv.stdout
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,6 @@ module Make (IO : IO) : S with module IO = IO = struct
|
||||||
|
|
||||||
type json = J.t
|
type json = J.t
|
||||||
|
|
||||||
let spf = Printf.sprintf
|
|
||||||
|
|
||||||
module ErrorCode = Jsonrpc.Response.Error.Code
|
module ErrorCode = Jsonrpc.Response.Error.Code
|
||||||
(*
|
(*
|
||||||
module Err = struct
|
module Err = struct
|
||||||
|
|
@ -138,7 +136,7 @@ module Make (IO : IO) : S with module IO = IO = struct
|
||||||
(fun () ->
|
(fun () ->
|
||||||
let+ x = f () in
|
let+ x = f () in
|
||||||
Ok x)
|
Ok x)
|
||||||
(fun e -> IO.return (Error e))
|
(fun e bt -> IO.return (Error (e, bt)))
|
||||||
|
|
||||||
(** Sends a server notification to the LSP client. *)
|
(** Sends a server notification to the LSP client. *)
|
||||||
let send_server_notification (self : t) (n : Lsp.Server_notification.t) :
|
let send_server_notification (self : t) (n : Lsp.Server_notification.t) :
|
||||||
|
|
@ -166,10 +164,15 @@ module Make (IO : IO) : S with module IO = IO = struct
|
||||||
(** Wraps some action and, in case the [IO.t] request has failed, logs the
|
(** Wraps some action and, in case the [IO.t] request has failed, logs the
|
||||||
failure to the LSP client. *)
|
failure to the LSP client. *)
|
||||||
let with_error_handler (self : t) (action : unit -> unit IO.t) : unit IO.t =
|
let with_error_handler (self : t) (action : unit -> unit IO.t) : unit IO.t =
|
||||||
IO.catch action (fun e ->
|
IO.catch action (fun exn bt ->
|
||||||
|
let message =
|
||||||
|
spf "LSP handler failed with %s\n%s" (Printexc.to_string exn)
|
||||||
|
(Printexc.raw_backtrace_to_string bt)
|
||||||
|
in
|
||||||
|
Log.err (fun k -> k "%s" message);
|
||||||
let msg =
|
let msg =
|
||||||
Lsp.Types.LogMessageParams.create ~type_:Lsp.Types.MessageType.Error
|
Lsp.Types.LogMessageParams.create ~type_:Lsp.Types.MessageType.Error
|
||||||
~message:(Printexc.to_string e)
|
~message
|
||||||
in
|
in
|
||||||
let msg =
|
let msg =
|
||||||
Lsp.Server_notification.LogMessage msg
|
Lsp.Server_notification.LogMessage msg
|
||||||
|
|
@ -191,11 +194,12 @@ module Make (IO : IO) : S with module IO = IO = struct
|
||||||
|
|
||||||
let handle_request (self : t) (r : Jsonrpc.Request.t) : unit IO.t =
|
let handle_request (self : t) (r : Jsonrpc.Request.t) : unit IO.t =
|
||||||
let protect ~id f =
|
let protect ~id f =
|
||||||
IO.catch f (fun e ->
|
IO.catch f (fun e bt ->
|
||||||
let message =
|
let message =
|
||||||
spf "%s\n%s" (Printexc.to_string e) (Printexc.get_backtrace ())
|
spf "%s\n%s" (Printexc.to_string e)
|
||||||
|
(Printexc.raw_backtrace_to_string bt)
|
||||||
in
|
in
|
||||||
Log.err (fun k -> k "error: %s" message);
|
Log.err (fun k -> k "error in request handler: %s" message);
|
||||||
let r =
|
let r =
|
||||||
Jsonrpc.Response.error id
|
Jsonrpc.Response.error id
|
||||||
(Jsonrpc.Response.Error.make
|
(Jsonrpc.Response.Error.make
|
||||||
|
|
@ -215,13 +219,23 @@ module Make (IO : IO) : S with module IO = IO = struct
|
||||||
~notify_back:(send_server_notification self)
|
~notify_back:(send_server_notification self)
|
||||||
~server_request:(server_request self)
|
~server_request:(server_request self)
|
||||||
in
|
in
|
||||||
|
let response =
|
||||||
|
match reply with
|
||||||
|
| Ok reply ->
|
||||||
let reply_json = Lsp.Client_request.yojson_of_result r reply in
|
let reply_json = Lsp.Client_request.yojson_of_result r reply in
|
||||||
let response = Jsonrpc.Response.ok id reply_json in
|
Jsonrpc.Response.ok id reply_json
|
||||||
|
| Error message ->
|
||||||
|
Jsonrpc.Response.error id
|
||||||
|
(Jsonrpc.Response.Error.make
|
||||||
|
~code:Jsonrpc.Response.Error.Code.InternalError ~message ())
|
||||||
|
in
|
||||||
|
|
||||||
send_response self response
|
send_response self response
|
||||||
| Error e -> IO.failwith (spf "cannot decode request: %s" e))
|
| Error e -> IO.failwith (spf "cannot decode request: %s" e))
|
||||||
(fun e ->
|
(fun e bt ->
|
||||||
let message =
|
let message =
|
||||||
spf "%s\n%s" (Printexc.to_string e) (Printexc.get_backtrace ())
|
spf "%s\n%s" (Printexc.to_string e)
|
||||||
|
(Printexc.raw_backtrace_to_string bt)
|
||||||
in
|
in
|
||||||
Log.err (fun k -> k "error: %s" message);
|
Log.err (fun k -> k "error: %s" message);
|
||||||
let r =
|
let r =
|
||||||
|
|
@ -273,7 +287,8 @@ module Make (IO : IO) : S with module IO = IO = struct
|
||||||
| _ -> j
|
| _ -> j
|
||||||
|
|
||||||
(* read a full message *)
|
(* read a full message *)
|
||||||
let read_msg (self : t) : (Jsonrpc.Packet.t, exn) result IO.t =
|
let read_msg (self : t) :
|
||||||
|
(Jsonrpc.Packet.t, exn * Printexc.raw_backtrace) result IO.t =
|
||||||
let rec read_headers acc =
|
let rec read_headers acc =
|
||||||
let*? line = try_ @@ fun () -> IO.read_line self.ic in
|
let*? line = try_ @@ fun () -> IO.read_line self.ic in
|
||||||
match String.trim line with
|
match String.trim line with
|
||||||
|
|
@ -292,8 +307,9 @@ module Make (IO : IO) : S with module IO = IO = struct
|
||||||
with
|
with
|
||||||
| pair -> read_headers (pair :: acc)
|
| pair -> read_headers (pair :: acc)
|
||||||
| exception _ ->
|
| exception _ ->
|
||||||
IO.return
|
let bt = Printexc.get_raw_backtrace () in
|
||||||
(Error (E (ErrorCode.ParseError, spf "invalid header: %S" line))))
|
let exn = E (ErrorCode.ParseError, spf "invalid header: %S" line) in
|
||||||
|
IO.return (Error (exn, bt)))
|
||||||
in
|
in
|
||||||
let*? headers = read_headers [] in
|
let*? headers = read_headers [] in
|
||||||
Log.debug (fun k ->
|
Log.debug (fun k ->
|
||||||
|
|
@ -323,15 +339,21 @@ module Make (IO : IO) : S with module IO = IO = struct
|
||||||
(match Jsonrpc.Packet.t_of_yojson @@ fix_null_in_params j with
|
(match Jsonrpc.Packet.t_of_yojson @@ fix_null_in_params j with
|
||||||
| m -> IO.return @@ Ok m
|
| m -> IO.return @@ Ok m
|
||||||
| exception exn ->
|
| exception exn ->
|
||||||
|
let bt = Printexc.get_raw_backtrace () in
|
||||||
Log.err (fun k ->
|
Log.err (fun k ->
|
||||||
k "cannot decode json message: %s" (Printexc.to_string exn));
|
k "cannot decode json message: %s\n%s" (Printexc.to_string exn)
|
||||||
IO.return (Error (E (ErrorCode.ParseError, "cannot decode json"))))
|
(Printexc.raw_backtrace_to_string bt));
|
||||||
|
let exn = E (ErrorCode.ParseError, "cannot decode json") in
|
||||||
|
IO.return (Error (exn, bt)))
|
||||||
| exception _ ->
|
| exception _ ->
|
||||||
|
let bt = Printexc.get_raw_backtrace () in
|
||||||
IO.return
|
IO.return
|
||||||
@@ Error (E (ErrorCode.ParseError, "missing content-length' header"))
|
@@ Error (E (ErrorCode.ParseError, "missing content-length' header"), bt)
|
||||||
) else
|
) else (
|
||||||
|
let bt = Printexc.get_callstack 10 in
|
||||||
IO.return
|
IO.return
|
||||||
@@ Error (E (ErrorCode.InvalidRequest, "content-type must be 'utf-8'"))
|
@@ Error (E (ErrorCode.InvalidRequest, "content-type must be 'utf-8'"), bt)
|
||||||
|
)
|
||||||
|
|
||||||
let send_server_request (self : t) (req : 'from_server Lsp.Server_request.t)
|
let send_server_request (self : t) (req : 'from_server Lsp.Server_request.t)
|
||||||
(cb : ('from_server, Jsonrpc.Response.Error.t) result -> unit IO.t) :
|
(cb : ('from_server, Jsonrpc.Response.Error.t) result -> unit IO.t) :
|
||||||
|
|
@ -369,7 +391,7 @@ module Make (IO : IO) : S with module IO = IO = struct
|
||||||
| Ok r ->
|
| Ok r ->
|
||||||
let* () = process_msg r in
|
let* () = process_msg r in
|
||||||
loop ()
|
loop ()
|
||||||
| Error e -> IO.fail e
|
| Error (e, bt) -> IO.fail e bt
|
||||||
in
|
in
|
||||||
loop ()
|
loop ()
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,12 @@ module IO_lwt :
|
||||||
let write = Lwt_io.write_from_exactly
|
let write = Lwt_io.write_from_exactly
|
||||||
let read = Lwt_io.read_into_exactly
|
let read = Lwt_io.read_into_exactly
|
||||||
let read_line = Lwt_io.read_line
|
let read_line = Lwt_io.read_line
|
||||||
let catch = Lwt.catch
|
|
||||||
let fail = Lwt.fail
|
let catch f g =
|
||||||
|
let bt = Printexc.get_callstack 10 in
|
||||||
|
Lwt.catch f (fun exn -> g exn bt)
|
||||||
|
|
||||||
|
let fail e _bt = Lwt.fail e
|
||||||
end
|
end
|
||||||
|
|
||||||
(** Spawn function.
|
(** Spawn function.
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ module Make (IO : IO) = struct
|
||||||
server_request:send_request ->
|
server_request:send_request ->
|
||||||
id:Req_id.t ->
|
id:Req_id.t ->
|
||||||
'a Lsp.Client_request.t ->
|
'a Lsp.Client_request.t ->
|
||||||
'a IO.t
|
('a, string) result IO.t
|
||||||
(** Method called to handle client requests.
|
(** Method called to handle client requests.
|
||||||
@param notify_back an object used to reply to the client, send progress
|
@param notify_back an object used to reply to the client, send progress
|
||||||
messages, diagnostics, etc.
|
messages, diagnostics, etc.
|
||||||
|
|
@ -76,7 +76,14 @@ module Make (IO : IO) = struct
|
||||||
end
|
end
|
||||||
|
|
||||||
let async (self : #base_server) f : unit IO.t =
|
let async (self : #base_server) f : unit IO.t =
|
||||||
self#spawn_query_handler f;
|
self#spawn_query_handler (fun () ->
|
||||||
|
IO.catch f (fun exn bt ->
|
||||||
|
let msg =
|
||||||
|
spf "LSP async notification handler failed with %s\n%s"
|
||||||
|
(Printexc.to_string exn)
|
||||||
|
(Printexc.raw_backtrace_to_string bt)
|
||||||
|
in
|
||||||
|
IO.return @@ Log.err (fun k -> k "%s" msg)));
|
||||||
IO.return ()
|
IO.return ()
|
||||||
|
|
||||||
(** A wrapper to more easily reply to notifications *)
|
(** A wrapper to more easily reply to notifications *)
|
||||||
|
|
@ -150,6 +157,11 @@ module Make (IO : IO) = struct
|
||||||
}
|
}
|
||||||
(** Current state of a document. *)
|
(** Current state of a document. *)
|
||||||
|
|
||||||
|
let[@inline] lift_ok x =
|
||||||
|
let open IO in
|
||||||
|
let+ x = x in
|
||||||
|
Ok x
|
||||||
|
|
||||||
(** An easily overloadable class. Pick the methods you want to support.
|
(** An easily overloadable class. Pick the methods you want to support.
|
||||||
The user must provide at least the callbacks for document lifecycle:
|
The user must provide at least the callbacks for document lifecycle:
|
||||||
open, close, update. The most basic LSP server should check documents
|
open, close, update. The most basic LSP server should check documents
|
||||||
|
|
@ -337,10 +349,24 @@ module Make (IO : IO) = struct
|
||||||
server_request:_ ->
|
server_request:_ ->
|
||||||
id:Req_id.t ->
|
id:Req_id.t ->
|
||||||
r Lsp.Client_request.t ->
|
r Lsp.Client_request.t ->
|
||||||
r IO.t =
|
(r, string) result IO.t =
|
||||||
fun ~notify_back ~server_request ~id (r : _ Lsp.Client_request.t) ->
|
fun ~notify_back ~server_request ~id (r : _ Lsp.Client_request.t) ->
|
||||||
Trace.with_span ~__FILE__ ~__LINE__ "linol.on-request"
|
Trace.with_span ~__FILE__ ~__LINE__ "linol.on-request"
|
||||||
@@ fun _sp : r IO.t ->
|
@@ fun _sp : (r, string) result IO.t ->
|
||||||
|
(* handler to catch all errors *)
|
||||||
|
let try_catch : (unit -> (r, _) result IO.t) -> (r, _) result IO.t =
|
||||||
|
fun f ->
|
||||||
|
IO.catch f (fun exn bt ->
|
||||||
|
let msg =
|
||||||
|
spf "LSP request handler failed with %s\n%s"
|
||||||
|
(Printexc.to_string exn)
|
||||||
|
(Printexc.raw_backtrace_to_string bt)
|
||||||
|
in
|
||||||
|
Log.err (fun k -> k "%s" msg);
|
||||||
|
IO.return @@ Error msg)
|
||||||
|
in
|
||||||
|
|
||||||
|
try_catch @@ fun () ->
|
||||||
Log.debug (fun k ->
|
Log.debug (fun k ->
|
||||||
k "handle request[id=%s] <opaque>" (Req_id.to_string id));
|
k "handle request[id=%s] <opaque>" (Req_id.to_string id));
|
||||||
|
|
||||||
|
|
@ -353,7 +379,7 @@ module Make (IO : IO) = struct
|
||||||
~server_request ()
|
~server_request ()
|
||||||
in
|
in
|
||||||
status <- `ReceivedShutdown;
|
status <- `ReceivedShutdown;
|
||||||
self#on_req_shutdown ~notify_back ~id
|
lift_ok @@ self#on_req_shutdown ~notify_back ~id
|
||||||
| Lsp.Client_request.Initialize i ->
|
| Lsp.Client_request.Initialize i ->
|
||||||
Log.debug (fun k -> k "req: initialize");
|
Log.debug (fun k -> k "req: initialize");
|
||||||
let notify_back =
|
let notify_back =
|
||||||
|
|
@ -361,21 +387,22 @@ module Make (IO : IO) = struct
|
||||||
~partialResultToken:None ~workDoneToken:i.workDoneToken
|
~partialResultToken:None ~workDoneToken:i.workDoneToken
|
||||||
~notify_back ~server_request ()
|
~notify_back ~server_request ()
|
||||||
in
|
in
|
||||||
self#on_req_initialize ~notify_back i
|
lift_ok @@ self#on_req_initialize ~notify_back i
|
||||||
| Lsp.Client_request.TextDocumentHover
|
| Lsp.Client_request.TextDocumentHover
|
||||||
{ textDocument; position; workDoneToken } ->
|
{ textDocument; position; workDoneToken } ->
|
||||||
let uri = textDocument.uri in
|
let uri = textDocument.uri in
|
||||||
Log.debug (fun k -> k "req: hover '%s'" (DocumentUri.to_path uri));
|
Log.debug (fun k -> k "req: hover '%s'" (DocumentUri.to_path uri));
|
||||||
|
|
||||||
(match Hashtbl.find_opt docs uri with
|
(match Hashtbl.find_opt docs uri with
|
||||||
| None -> IO.return None
|
| None -> IO.return @@ Ok None
|
||||||
| Some doc_st ->
|
| Some doc_st ->
|
||||||
let notify_back =
|
let notify_back =
|
||||||
new notify_back
|
new notify_back
|
||||||
~workDoneToken ~partialResultToken:None ~uri ~notify_back
|
~workDoneToken ~partialResultToken:None ~uri ~notify_back
|
||||||
~server_request ()
|
~server_request ()
|
||||||
in
|
in
|
||||||
self#on_req_hover ~notify_back ~id ~uri ~pos:position
|
lift_ok
|
||||||
|
@@ self#on_req_hover ~notify_back ~id ~uri ~pos:position
|
||||||
~workDoneToken doc_st)
|
~workDoneToken doc_st)
|
||||||
| Lsp.Client_request.TextDocumentCompletion
|
| Lsp.Client_request.TextDocumentCompletion
|
||||||
{
|
{
|
||||||
|
|
@ -389,14 +416,15 @@ module Make (IO : IO) = struct
|
||||||
Log.debug (fun k ->
|
Log.debug (fun k ->
|
||||||
k "req: complete '%s'" (DocumentUri.to_path uri));
|
k "req: complete '%s'" (DocumentUri.to_path uri));
|
||||||
(match Hashtbl.find_opt docs uri with
|
(match Hashtbl.find_opt docs uri with
|
||||||
| None -> IO.return None
|
| None -> IO.return @@ Ok None
|
||||||
| Some doc_st ->
|
| Some doc_st ->
|
||||||
let notify_back =
|
let notify_back =
|
||||||
new notify_back
|
new notify_back
|
||||||
~partialResultToken ~workDoneToken ~uri ~notify_back
|
~partialResultToken ~workDoneToken ~uri ~notify_back
|
||||||
~server_request ()
|
~server_request ()
|
||||||
in
|
in
|
||||||
self#on_req_completion ~notify_back ~id ~uri ~workDoneToken
|
lift_ok
|
||||||
|
@@ self#on_req_completion ~notify_back ~id ~uri ~workDoneToken
|
||||||
~partialResultToken ~pos:position ~ctx:context doc_st)
|
~partialResultToken ~pos:position ~ctx:context doc_st)
|
||||||
| Lsp.Client_request.TextDocumentDefinition
|
| Lsp.Client_request.TextDocumentDefinition
|
||||||
{ textDocument; position; workDoneToken; partialResultToken } ->
|
{ textDocument; position; workDoneToken; partialResultToken } ->
|
||||||
|
|
@ -410,9 +438,10 @@ module Make (IO : IO) = struct
|
||||||
in
|
in
|
||||||
|
|
||||||
(match Hashtbl.find_opt docs uri with
|
(match Hashtbl.find_opt docs uri with
|
||||||
| None -> IO.return None
|
| None -> IO.return @@ Ok None
|
||||||
| Some doc_st ->
|
| Some doc_st ->
|
||||||
self#on_req_definition ~notify_back ~id ~workDoneToken
|
lift_ok
|
||||||
|
@@ self#on_req_definition ~notify_back ~id ~workDoneToken
|
||||||
~partialResultToken ~uri ~pos:position doc_st)
|
~partialResultToken ~uri ~pos:position doc_st)
|
||||||
| Lsp.Client_request.TextDocumentCodeLens
|
| Lsp.Client_request.TextDocumentCodeLens
|
||||||
{ textDocument; workDoneToken; partialResultToken } ->
|
{ textDocument; workDoneToken; partialResultToken } ->
|
||||||
|
|
@ -426,9 +455,10 @@ module Make (IO : IO) = struct
|
||||||
in
|
in
|
||||||
|
|
||||||
(match Hashtbl.find_opt docs uri with
|
(match Hashtbl.find_opt docs uri with
|
||||||
| None -> IO.return []
|
| None -> IO.return @@ Ok []
|
||||||
| Some doc_st ->
|
| Some doc_st ->
|
||||||
self#on_req_code_lens ~notify_back ~id ~uri ~workDoneToken
|
lift_ok
|
||||||
|
@@ self#on_req_code_lens ~notify_back ~id ~uri ~workDoneToken
|
||||||
~partialResultToken doc_st)
|
~partialResultToken doc_st)
|
||||||
| Lsp.Client_request.TextDocumentCodeLensResolve cl ->
|
| Lsp.Client_request.TextDocumentCodeLensResolve cl ->
|
||||||
Log.debug (fun k -> k "req: codelens resolve");
|
Log.debug (fun k -> k "req: codelens resolve");
|
||||||
|
|
@ -437,7 +467,7 @@ module Make (IO : IO) = struct
|
||||||
~workDoneToken:None ~partialResultToken:None ~notify_back
|
~workDoneToken:None ~partialResultToken:None ~notify_back
|
||||||
~server_request ()
|
~server_request ()
|
||||||
in
|
in
|
||||||
self#on_req_code_lens_resolve ~notify_back ~id cl
|
lift_ok @@ self#on_req_code_lens_resolve ~notify_back ~id cl
|
||||||
| Lsp.Client_request.ExecuteCommand
|
| Lsp.Client_request.ExecuteCommand
|
||||||
{ command; arguments; workDoneToken } ->
|
{ command; arguments; workDoneToken } ->
|
||||||
Log.debug (fun k -> k "req: execute command '%s'" command);
|
Log.debug (fun k -> k "req: execute command '%s'" command);
|
||||||
|
|
@ -446,8 +476,9 @@ module Make (IO : IO) = struct
|
||||||
~workDoneToken ~partialResultToken:None ~notify_back
|
~workDoneToken ~partialResultToken:None ~notify_back
|
||||||
~server_request ()
|
~server_request ()
|
||||||
in
|
in
|
||||||
self#on_req_execute_command ~notify_back ~id ~workDoneToken command
|
lift_ok
|
||||||
arguments
|
@@ self#on_req_execute_command ~notify_back ~id ~workDoneToken
|
||||||
|
command arguments
|
||||||
| Lsp.Client_request.DocumentSymbol
|
| Lsp.Client_request.DocumentSymbol
|
||||||
{ textDocument = d; workDoneToken; partialResultToken } ->
|
{ textDocument = d; workDoneToken; partialResultToken } ->
|
||||||
let notify_back =
|
let notify_back =
|
||||||
|
|
@ -455,7 +486,8 @@ module Make (IO : IO) = struct
|
||||||
~workDoneToken ~partialResultToken ~notify_back ~server_request
|
~workDoneToken ~partialResultToken ~notify_back ~server_request
|
||||||
()
|
()
|
||||||
in
|
in
|
||||||
self#on_req_symbol ~notify_back ~id ~uri:d.uri ~workDoneToken
|
lift_ok
|
||||||
|
@@ self#on_req_symbol ~notify_back ~id ~uri:d.uri ~workDoneToken
|
||||||
~partialResultToken ()
|
~partialResultToken ()
|
||||||
| Lsp.Client_request.CodeAction a ->
|
| Lsp.Client_request.CodeAction a ->
|
||||||
let notify_back =
|
let notify_back =
|
||||||
|
|
@ -464,14 +496,15 @@ module Make (IO : IO) = struct
|
||||||
~partialResultToken:a.partialResultToken ~notify_back
|
~partialResultToken:a.partialResultToken ~notify_back
|
||||||
~server_request ()
|
~server_request ()
|
||||||
in
|
in
|
||||||
self#on_req_code_action ~notify_back ~id a
|
lift_ok @@ self#on_req_code_action ~notify_back ~id a
|
||||||
| Lsp.Client_request.InlayHint p ->
|
| Lsp.Client_request.InlayHint p ->
|
||||||
let notify_back : notify_back =
|
let notify_back : notify_back =
|
||||||
new notify_back
|
new notify_back
|
||||||
~workDoneToken:p.workDoneToken ~partialResultToken:None
|
~workDoneToken:p.workDoneToken ~partialResultToken:None
|
||||||
~notify_back ~server_request ()
|
~notify_back ~server_request ()
|
||||||
in
|
in
|
||||||
self#on_req_inlay_hint ~notify_back ~id ~uri:p.textDocument.uri
|
lift_ok
|
||||||
|
@@ self#on_req_inlay_hint ~notify_back ~id ~uri:p.textDocument.uri
|
||||||
~range:p.range ()
|
~range:p.range ()
|
||||||
| Lsp.Client_request.CodeActionResolve _
|
| Lsp.Client_request.CodeActionResolve _
|
||||||
| Lsp.Client_request.LinkedEditingRange _
|
| Lsp.Client_request.LinkedEditingRange _
|
||||||
|
|
@ -512,14 +545,15 @@ module Make (IO : IO) = struct
|
||||||
~workDoneToken:None ~partialResultToken:None ~notify_back
|
~workDoneToken:None ~partialResultToken:None ~notify_back
|
||||||
~server_request ()
|
~server_request ()
|
||||||
in
|
in
|
||||||
self#on_request_unhandled ~notify_back ~id r
|
lift_ok @@ self#on_request_unhandled ~notify_back ~id r
|
||||||
| Lsp.Client_request.UnknownRequest r ->
|
| Lsp.Client_request.UnknownRequest r ->
|
||||||
let notify_back =
|
let notify_back =
|
||||||
new notify_back
|
new notify_back
|
||||||
~workDoneToken:None ~partialResultToken:None ~notify_back
|
~workDoneToken:None ~partialResultToken:None ~notify_back
|
||||||
~server_request ()
|
~server_request ()
|
||||||
in
|
in
|
||||||
self#on_unknown_request ~notify_back ~server_request ~id r.meth
|
lift_ok
|
||||||
|
@@ self#on_unknown_request ~notify_back ~server_request ~id r.meth
|
||||||
r.params
|
r.params
|
||||||
|
|
||||||
method virtual on_notif_doc_did_open
|
method virtual on_notif_doc_did_open
|
||||||
|
|
@ -559,6 +593,21 @@ module Make (IO : IO) = struct
|
||||||
let@ _sp =
|
let@ _sp =
|
||||||
Trace.with_span ~__FILE__ ~__LINE__ "linol.on-notification"
|
Trace.with_span ~__FILE__ ~__LINE__ "linol.on-notification"
|
||||||
in
|
in
|
||||||
|
|
||||||
|
(* handler to catch all errors *)
|
||||||
|
let try_catch : (unit -> unit IO.t) -> unit IO.t =
|
||||||
|
fun f ->
|
||||||
|
IO.catch f (fun exn bt ->
|
||||||
|
let msg =
|
||||||
|
spf "LSP notification handler failed with %s\n%s"
|
||||||
|
(Printexc.to_string exn)
|
||||||
|
(Printexc.raw_backtrace_to_string bt)
|
||||||
|
in
|
||||||
|
Log.err (fun k -> k "%s" msg);
|
||||||
|
IO.return ())
|
||||||
|
in
|
||||||
|
|
||||||
|
try_catch @@ fun () ->
|
||||||
let open Lsp.Types in
|
let open Lsp.Types in
|
||||||
match n with
|
match n with
|
||||||
| Lsp.Client_notification.TextDocumentDidOpen
|
| Lsp.Client_notification.TextDocumentDidOpen
|
||||||
|
|
@ -654,8 +703,8 @@ module Make (IO : IO) = struct
|
||||||
| Lsp.Client_notification.DidSaveTextDocument params ->
|
| Lsp.Client_notification.DidSaveTextDocument params ->
|
||||||
let notify_back =
|
let notify_back =
|
||||||
new notify_back
|
new notify_back
|
||||||
~workDoneToken:None ~partialResultToken:None ~uri:params.textDocument.uri
|
~workDoneToken:None ~partialResultToken:None
|
||||||
~notify_back ~server_request ()
|
~uri:params.textDocument.uri ~notify_back ~server_request ()
|
||||||
in
|
in
|
||||||
|
|
||||||
async self (fun () ->
|
async self (fun () ->
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,6 @@ module type IO = sig
|
||||||
val read_line : in_channel -> string t
|
val read_line : in_channel -> string t
|
||||||
val write : out_channel -> bytes -> int -> int -> unit t
|
val write : out_channel -> bytes -> int -> int -> unit t
|
||||||
val write_string : out_channel -> string -> unit t
|
val write_string : out_channel -> string -> unit t
|
||||||
val fail : exn -> unit t
|
val fail : exn -> Printexc.raw_backtrace -> unit t
|
||||||
val catch : (unit -> 'a t) -> (exn -> 'a t) -> 'a t
|
val catch : (unit -> 'a t) -> (exn -> Printexc.raw_backtrace -> 'a t) -> 'a t
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue