From 8c4ca8041151708c5751576e3d402777e60e5ce7 Mon Sep 17 00:00:00 2001 From: Anton Sorokin Date: Fri, 7 Jul 2023 20:13:17 +0300 Subject: [PATCH] [#20] Handle messages with null value for "params" field Problem: If an LSP client sends a request with "params":null instead of omitting the params field or smth like "params":{}, decoding error appears. Solution: Replace `null` value for "params" to `{}` --- src/jsonrpc2.ml | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/jsonrpc2.ml b/src/jsonrpc2.ml index ceae39e4..927dc4d8 100644 --- a/src/jsonrpc2.ml +++ b/src/jsonrpc2.ml @@ -227,6 +227,21 @@ module Make (IO : IO) : S with module IO = IO = struct list) : unit IO.t = IO.failwith "Unhandled: jsonrpc batch call" + (* As in [https://github.com/c-cube/linol/issues/20], + Jsonrpc expect "params" to be object or array, + and if the key "params" is present but the value is `Null the [Packet.t_of_yojson] + is failing with "invalid structured value" *) + let fix_null_in_params (j : J.t) : J.t = + let open J.Util in + match j with + | `Assoc assoc as t when t |> member "params" |> J.equal `Null -> + let f = function + | "params", `Null -> "params", `Assoc [] + | x -> x + in + `Assoc (List.map f assoc) + | _ -> j + (* read a full message *) let read_msg (self : t) : (Jsonrpc.Packet.t, exn) result IO.t = let rec read_headers acc = @@ -269,11 +284,12 @@ module Make (IO : IO) : S with module IO = IO = struct let*? () = try_ @@ fun () -> IO.read self.ic buf 0 n in (* log_lsp_ "got bytes %S" (Bytes.unsafe_to_string buf); *) let*? j = - try_ @@ fun () -> - IO.return @@ J.from_string (Bytes.unsafe_to_string buf) + Fun.id @@ try_ + @@ fun () -> IO.return @@ J.from_string (Bytes.unsafe_to_string buf) in Log.debug (fun k -> k "got json %s" (J.to_string j)); - (match Jsonrpc.Packet.t_of_yojson j with + + (match Jsonrpc.Packet.t_of_yojson @@ fix_null_in_params j with | m -> IO.return @@ Ok m | exception exn -> Log.err (fun k ->