From e09e72da795b803eb803dc4a5343d38cbb0531bd Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Tue, 19 Sep 2023 10:06:59 +0300 Subject: [PATCH 001/140] Initial experiments with LSP. Signed-off-by: Karolis Petrauskas --- Makefile | 3 + dune-project | 6 +- lsp/bin/dune | 5 ++ lsp/bin/tlapm_lsp.ml | 34 ++++++++++ lsp/bin/tlapm_lsp.mli | 0 lsp/lib/dune | 4 ++ lsp/lib/tlapm_lsp_lib.ml | 0 lsp/lib/tlapm_lsp_lib.mli | 0 lsp/lib/tlapm_lsp_poc.ml | 132 ++++++++++++++++++++++++++++++++++++++ tlapm.opam | 1 + 10 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 lsp/bin/dune create mode 100644 lsp/bin/tlapm_lsp.ml create mode 100644 lsp/bin/tlapm_lsp.mli create mode 100644 lsp/lib/dune create mode 100644 lsp/lib/tlapm_lsp_lib.ml create mode 100644 lsp/lib/tlapm_lsp_lib.mli create mode 100644 lsp/lib/tlapm_lsp_poc.ml diff --git a/Makefile b/Makefile index 402f5f26..21e364ee 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,9 @@ all: build opam-deps: opam install ./ --deps-only --yes --working-dir +opam-deps-opt: + opam install eio_main fiber lsp --yes --working-dir # TODO: Remove fiber. + opam-deps-dev: opam install ocamlformat ocaml-lsp-server diff --git a/dune-project b/dune-project index c0503ecb..b132ad7b 100644 --- a/dune-project +++ b/dune-project @@ -41,4 +41,8 @@ dune-build-info sexplib ppx_inline_test - ppx_assert)) + ppx_assert) + (depopts + lsp ; https://github.com/ocaml/ocaml-lsp + fiber ; TODO: Do we need it for lsp? Probably not. + eio_main)) ; https://github.com/ocaml-multicore/eio, only available on OCaml version >= 5. diff --git a/lsp/bin/dune b/lsp/bin/dune new file mode 100644 index 00000000..1473487d --- /dev/null +++ b/lsp/bin/dune @@ -0,0 +1,5 @@ +(executable + (name tlapm_lsp) + (public_name tlapm_lsp) + (optional) ; Only build, if eio is available, which is only the case for ocaml > 5. + (libraries tlapm_lsp_lib eio_main)) diff --git a/lsp/bin/tlapm_lsp.ml b/lsp/bin/tlapm_lsp.ml new file mode 100644 index 00000000..833e96f6 --- /dev/null +++ b/lsp/bin/tlapm_lsp.ml @@ -0,0 +1,34 @@ +module Tlapm_lsp_lib = Tlapm_lsp_lib + +module LspServer = struct + + let err_handler = + Eio.traceln "Error handling connection: %a" Fmt.exn + + let req_handler flow _addr = + Eio.traceln "Server: got connection from client"; + let x = Eio.Buf_read.of_flow flow ~max_size:100 in + let ml = Eio.Buf_read.line x in + let mf = Eio.Buf_read.take 10 x in + Eio.Flow.copy_string (Printf.sprintf "Hello from server: line=%s - fixed(10)=%S\n" ml mf) flow + + let switch (net: 'a Eio.Net.ty Eio.Std.r) port stop_promise sw = + Eio.traceln "Switch started"; + let addr = (`Tcp (Eio.Net.Ipaddr.V4.loopback, port)) in + let sock = Eio.Net.listen net ~sw ~reuse_addr:true ~backlog:5 addr in + let stopResult = Eio.Net.run_server sock req_handler ~on_error:err_handler ?stop:(Some stop_promise) in + Eio.traceln "StopResult=%s" stopResult + + let run env stop_promise = + let net = (Eio.Stdenv.net env) in + let port = 8080 in + Eio.Switch.run @@ switch net port stop_promise + +end + +let () = + Eio_main.run @@ fun env -> + let (stop_promise, stop_resolver) = Eio.Std.Promise.create () in + let handle_signal (_signum : int) = Eio.Std.Promise.resolve stop_resolver "Stopping on SigINT" in + let () = Sys.set_signal Sys.sigint (Signal_handle handle_signal) in + LspServer.run env stop_promise diff --git a/lsp/bin/tlapm_lsp.mli b/lsp/bin/tlapm_lsp.mli new file mode 100644 index 00000000..e69de29b diff --git a/lsp/lib/dune b/lsp/lib/dune new file mode 100644 index 00000000..0f8a81dc --- /dev/null +++ b/lsp/lib/dune @@ -0,0 +1,4 @@ +(library + (name tlapm_lsp_lib) + (optional) ; Only build, if eio is available, which is only the case for ocaml > 5. + (libraries tlapm_lib lsp eio_main fiber)) ; TODO: Remove fiber. \ No newline at end of file diff --git a/lsp/lib/tlapm_lsp_lib.ml b/lsp/lib/tlapm_lsp_lib.ml new file mode 100644 index 00000000..e69de29b diff --git a/lsp/lib/tlapm_lsp_lib.mli b/lsp/lib/tlapm_lsp_lib.mli new file mode 100644 index 00000000..e69de29b diff --git a/lsp/lib/tlapm_lsp_poc.ml b/lsp/lib/tlapm_lsp_poc.ml new file mode 100644 index 00000000..b53106a2 --- /dev/null +++ b/lsp/lib/tlapm_lsp_poc.ml @@ -0,0 +1,132 @@ + +let _ = Lsp.Cli.args + +(* ================================= START Of Experiment on LSP IO ===================== *) + +module MyInitialPoC = struct + type myIoCh = string + + module MyIo = struct + type 'a t = myIoCh + let return = failwith "todo" + let raise = failwith "todo" + module O = struct + let ( let+ ) _a _b = failwith "todo" + let ( let* ) _a _b = failwith "todo" + end + end + + module MyChan = struct + type output = myIoCh + type input = myIoCh + let read_line : input -> string option MyIo.t = + failwith "todo" + let read_exactly : input -> int -> string option MyIo.t = + failwith "todo" + let write : output -> string list -> unit MyIo.t = + failwith "todo" + end + + module MyLspIo = Lsp.Io.Make (MyIo) (MyChan) + + let _r = MyLspIo.read "myIoCh" + let _w p = MyLspIo.write "myIoCh" p + +end + + +let _myTextDocument = + let tdi = Lsp.Types.TextDocumentItem.create ~languageId:"lang" ~text:"text" ~uri:(Lsp.Uri.of_path "...........") ~version:12 in + let p = Lsp.Types.DidOpenTextDocumentParams.create ~textDocument:tdi in + Lsp.Text_document.make ~position_encoding:`UTF8 p + + + +(* ================================= END Of Experiment on LSP ===================== *) + +module MyFibExperiment = struct + + module MyIo = struct + include Fiber + let raise exn = raise exn + end + + module MyChan = struct + type input = string Queue.t + type output = string Queue.t + + let read_line (_ic : input) : string option MyIo.t = failwith "todo" + (* let+ res = Lio.Reader.read_line ic in + match res with + | Ok s -> Some s + | Error (`Partial_eof _) -> None *) + + let read_exactly (_ic : input) (_len : int) : string option MyIo.t = failwith "todo" + (* let+ res = Lio.Reader.read_exactly ic len in + match res with + | Ok s -> Some s + | Error (`Partial_eof _) -> None *) + + let write (_oc : output) (_strings : string list) : unit MyIo.t = failwith "todo" + (* Fiber.of_thunk (fun () -> + List.iter strings ~f:(Lio.Writer.add_string oc); + Fiber.return ()) *) + + end + + module MyLspIo = Lsp.Io.Make (MyIo) (MyChan) + + (** State of the IO consists of input and output queues. *) + type t = { + ic : string Queue.t; + oc : string Queue.t; + } + + (** Here we have read/write functions, they should be called by the environment, I guess. *) + let _r {ic; _} = MyLspIo.read ic + let _w {oc; _} p = MyLspIo.write oc p + +end + + + + +(* module Channel = struct + type t = + | Stdio + | Pipe of string + | Socket of int +end *) + +(* let stream_of_channel : Lsp.Cli.Channel.t -> _ = function + | Stdio -> + let* stdin = Fiber.O.Stdin in + let+ stdout = Fiber.O.Stdout in + (stdin, stdout) + | Pipe path -> + if Sys.win32 then ( + Format.eprintf "windows pipes are not supported"; + exit 1) + else + let _sockaddr = Unix.ADDR_UNIX path in + (Fiber.O.Stdin, Fiber.O.Stdout) + | Socket port -> + let _sockaddr = Unix.ADDR_INET (Unix.inet_addr_loopback, port) in + (Fiber.O.Stdin, Fiber.O.Stdout) *) + +(* let stream_of_channel : Lsp.Cli.Channel.t -> _ = function + | Stdio -> + let* stdin = Lev_fiber.Io.stdin in + let+ stdout = Lev_fiber.Io.stdout in + (stdin, stdout) + | Pipe path -> + if Sys.win32 then ( + Format.eprintf "windows pipes are not supported"; + exit 1) + else + let sockaddr = Unix.ADDR_UNIX path in + socket sockaddr + | Socket port -> + let sockaddr = Unix.ADDR_INET (Unix.inet_addr_loopback, port) in + socket sockaddr *) + diff --git a/tlapm.opam b/tlapm.opam index b83e8eed..7b1eb473 100644 --- a/tlapm.opam +++ b/tlapm.opam @@ -34,6 +34,7 @@ depends: [ "ppx_assert" "odoc" {with-doc} ] +depopts: ["lsp" "fiber" "eio_main"] dev-repo: "git+https://github.com/tlaplus/tlapm.git" build: [ # This is to override the build step, add the invocation of `Makefile.post-install`. ["dune" "subst"] {dev} From fc0cd1324240d8f2e4772c44b4311380314ca88f Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Tue, 19 Sep 2023 23:03:10 +0300 Subject: [PATCH 002/140] Empty LSP server works. Signed-off-by: Karolis Petrauskas --- lsp/bin/tlapm_lsp.ml | 30 +++++++-- lsp/lib/tlapm_lsp_lib.ml | 55 ++++++++++++++++ lsp/lib/tlapm_lsp_lib.mli | 10 +++ lsp/lib/tlapm_lsp_poc.ml | 132 -------------------------------------- 4 files changed, 91 insertions(+), 136 deletions(-) delete mode 100644 lsp/lib/tlapm_lsp_poc.ml diff --git a/lsp/bin/tlapm_lsp.ml b/lsp/bin/tlapm_lsp.ml index 833e96f6..3bb714d6 100644 --- a/lsp/bin/tlapm_lsp.ml +++ b/lsp/bin/tlapm_lsp.ml @@ -2,15 +2,37 @@ module Tlapm_lsp_lib = Tlapm_lsp_lib module LspServer = struct + let lsp_packet_handler (packet : Jsonrpc.Packet.t) write_fun = + Eio.traceln "Got LSP Packet"; + write_fun packet (* // TODO: That's just echo. *) + + let rec lsp_stream_handler buf_r buf_w = + let open Tlapm_lsp_lib.EioLspParser in + let write_fun out_packet = + match write buf_w out_packet with + | IoOk () -> + Eio.Buf_write.flush buf_w + | IoErr exn -> + Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) + in + match read buf_r with + | IoOk (Some packet) -> + lsp_packet_handler packet write_fun; + lsp_stream_handler buf_r buf_w + | IoOk None -> + Eio.traceln "No packet was read." + | IoErr exn -> + Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) + + let err_handler = Eio.traceln "Error handling connection: %a" Fmt.exn let req_handler flow _addr = Eio.traceln "Server: got connection from client"; - let x = Eio.Buf_read.of_flow flow ~max_size:100 in - let ml = Eio.Buf_read.line x in - let mf = Eio.Buf_read.take 10 x in - Eio.Flow.copy_string (Printf.sprintf "Hello from server: line=%s - fixed(10)=%S\n" ml mf) flow + let buf_r = Eio.Buf_read.of_flow flow ~max_size:1024 in + Eio.Buf_write.with_flow flow @@ fun buf_w -> + lsp_stream_handler buf_r buf_w let switch (net: 'a Eio.Net.ty Eio.Std.r) port stop_promise sw = Eio.traceln "Switch started"; diff --git a/lsp/lib/tlapm_lsp_lib.ml b/lsp/lib/tlapm_lsp_lib.ml index e69de29b..b049c1c1 100644 --- a/lsp/lib/tlapm_lsp_lib.ml +++ b/lsp/lib/tlapm_lsp_lib.ml @@ -0,0 +1,55 @@ + +module type EioLspParser = sig + type 'a io_res = + | IoOk of 'a + | IoErr of exn + + val read : Eio.Buf_read.t -> Jsonrpc.Packet.t option io_res + val write : Eio.Buf_write.t -> Jsonrpc.Packet.t -> unit io_res +end + +(** Here we construct an LSP protocol parser on top of Eio flows. *) +module EioLspParser : EioLspParser = struct + type 'a io_res = + | IoOk of 'a + | IoErr of exn + + module IoState = struct + type 'a t = 'a io_res + let return x = IoOk x + let raise exn = IoErr exn + module O = struct + let ( let+ ) st f = + match st with + | IoOk a -> IoOk (f a) + | IoErr exn -> IoErr exn + let ( let* ) st f = + match st with + | IoOk a -> f a + | IoErr exn -> IoErr exn + end + end + + module IoChan = struct + type output = Eio.Buf_write.t + type input = Eio.Buf_read.t + let read_line (buf : input): string option IoState.t = + let line = Eio.Buf_read.line buf in + IoOk (Some line) + let read_exactly (buf : input) (n : int) : string option IoState.t = + let data = Eio.Buf_read.take n buf in + IoOk (Some data) + let rec write (buf : output) (lines : string list) : unit IoState.t = + match lines with + | [] -> + IoOk () + | line :: tail -> + let () = Eio.Buf_write.string buf line in + write buf tail + end + + module LspIo = Lsp.Io.Make (IoState) (IoChan) + + let read = LspIo.read + let write = LspIo.write +end diff --git a/lsp/lib/tlapm_lsp_lib.mli b/lsp/lib/tlapm_lsp_lib.mli index e69de29b..f2874dd0 100644 --- a/lsp/lib/tlapm_lsp_lib.mli +++ b/lsp/lib/tlapm_lsp_lib.mli @@ -0,0 +1,10 @@ +module type EioLspParser = sig + type 'a io_res = + | IoOk of 'a + | IoErr of exn + + val read : Eio.Buf_read.t -> Jsonrpc.Packet.t option io_res + val write : Eio.Buf_write.t -> Jsonrpc.Packet.t -> unit io_res +end + +module EioLspParser : EioLspParser diff --git a/lsp/lib/tlapm_lsp_poc.ml b/lsp/lib/tlapm_lsp_poc.ml deleted file mode 100644 index b53106a2..00000000 --- a/lsp/lib/tlapm_lsp_poc.ml +++ /dev/null @@ -1,132 +0,0 @@ - -let _ = Lsp.Cli.args - -(* ================================= START Of Experiment on LSP IO ===================== *) - -module MyInitialPoC = struct - type myIoCh = string - - module MyIo = struct - type 'a t = myIoCh - let return = failwith "todo" - let raise = failwith "todo" - module O = struct - let ( let+ ) _a _b = failwith "todo" - let ( let* ) _a _b = failwith "todo" - end - end - - module MyChan = struct - type output = myIoCh - type input = myIoCh - let read_line : input -> string option MyIo.t = - failwith "todo" - let read_exactly : input -> int -> string option MyIo.t = - failwith "todo" - let write : output -> string list -> unit MyIo.t = - failwith "todo" - end - - module MyLspIo = Lsp.Io.Make (MyIo) (MyChan) - - let _r = MyLspIo.read "myIoCh" - let _w p = MyLspIo.write "myIoCh" p - -end - - -let _myTextDocument = - let tdi = Lsp.Types.TextDocumentItem.create ~languageId:"lang" ~text:"text" ~uri:(Lsp.Uri.of_path "...........") ~version:12 in - let p = Lsp.Types.DidOpenTextDocumentParams.create ~textDocument:tdi in - Lsp.Text_document.make ~position_encoding:`UTF8 p - - - -(* ================================= END Of Experiment on LSP ===================== *) - -module MyFibExperiment = struct - - module MyIo = struct - include Fiber - let raise exn = raise exn - end - - module MyChan = struct - type input = string Queue.t - type output = string Queue.t - - let read_line (_ic : input) : string option MyIo.t = failwith "todo" - (* let+ res = Lio.Reader.read_line ic in - match res with - | Ok s -> Some s - | Error (`Partial_eof _) -> None *) - - let read_exactly (_ic : input) (_len : int) : string option MyIo.t = failwith "todo" - (* let+ res = Lio.Reader.read_exactly ic len in - match res with - | Ok s -> Some s - | Error (`Partial_eof _) -> None *) - - let write (_oc : output) (_strings : string list) : unit MyIo.t = failwith "todo" - (* Fiber.of_thunk (fun () -> - List.iter strings ~f:(Lio.Writer.add_string oc); - Fiber.return ()) *) - - end - - module MyLspIo = Lsp.Io.Make (MyIo) (MyChan) - - (** State of the IO consists of input and output queues. *) - type t = { - ic : string Queue.t; - oc : string Queue.t; - } - - (** Here we have read/write functions, they should be called by the environment, I guess. *) - let _r {ic; _} = MyLspIo.read ic - let _w {oc; _} p = MyLspIo.write oc p - -end - - - - -(* module Channel = struct - type t = - | Stdio - | Pipe of string - | Socket of int -end *) - -(* let stream_of_channel : Lsp.Cli.Channel.t -> _ = function - | Stdio -> - let* stdin = Fiber.O.Stdin in - let+ stdout = Fiber.O.Stdout in - (stdin, stdout) - | Pipe path -> - if Sys.win32 then ( - Format.eprintf "windows pipes are not supported"; - exit 1) - else - let _sockaddr = Unix.ADDR_UNIX path in - (Fiber.O.Stdin, Fiber.O.Stdout) - | Socket port -> - let _sockaddr = Unix.ADDR_INET (Unix.inet_addr_loopback, port) in - (Fiber.O.Stdin, Fiber.O.Stdout) *) - -(* let stream_of_channel : Lsp.Cli.Channel.t -> _ = function - | Stdio -> - let* stdin = Lev_fiber.Io.stdin in - let+ stdout = Lev_fiber.Io.stdout in - (stdin, stdout) - | Pipe path -> - if Sys.win32 then ( - Format.eprintf "windows pipes are not supported"; - exit 1) - else - let sockaddr = Unix.ADDR_UNIX path in - socket sockaddr - | Socket port -> - let sockaddr = Unix.ADDR_INET (Unix.inet_addr_loopback, port) in - socket sockaddr *) - From 6d06443c22c605c2916a3e864ed03a4de70b2949 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Tue, 19 Sep 2023 23:34:32 +0300 Subject: [PATCH 003/140] Some code reorg. Signed-off-by: Karolis Petrauskas --- lsp/bin/tlapm_lsp.ml | 53 +++--------------------------------- lsp/lib/tlapm_lsp_lib.ml | 57 +++++++++++++++++++++++++++++++++++---- lsp/lib/tlapm_lsp_lib.mli | 13 +++------ 3 files changed, 58 insertions(+), 65 deletions(-) diff --git a/lsp/bin/tlapm_lsp.ml b/lsp/bin/tlapm_lsp.ml index 3bb714d6..78b9eb59 100644 --- a/lsp/bin/tlapm_lsp.ml +++ b/lsp/bin/tlapm_lsp.ml @@ -1,56 +1,9 @@ -module Tlapm_lsp_lib = Tlapm_lsp_lib - -module LspServer = struct - - let lsp_packet_handler (packet : Jsonrpc.Packet.t) write_fun = - Eio.traceln "Got LSP Packet"; - write_fun packet (* // TODO: That's just echo. *) - - let rec lsp_stream_handler buf_r buf_w = - let open Tlapm_lsp_lib.EioLspParser in - let write_fun out_packet = - match write buf_w out_packet with - | IoOk () -> - Eio.Buf_write.flush buf_w - | IoErr exn -> - Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) - in - match read buf_r with - | IoOk (Some packet) -> - lsp_packet_handler packet write_fun; - lsp_stream_handler buf_r buf_w - | IoOk None -> - Eio.traceln "No packet was read." - | IoErr exn -> - Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) - - - let err_handler = - Eio.traceln "Error handling connection: %a" Fmt.exn - - let req_handler flow _addr = - Eio.traceln "Server: got connection from client"; - let buf_r = Eio.Buf_read.of_flow flow ~max_size:1024 in - Eio.Buf_write.with_flow flow @@ fun buf_w -> - lsp_stream_handler buf_r buf_w - - let switch (net: 'a Eio.Net.ty Eio.Std.r) port stop_promise sw = - Eio.traceln "Switch started"; - let addr = (`Tcp (Eio.Net.Ipaddr.V4.loopback, port)) in - let sock = Eio.Net.listen net ~sw ~reuse_addr:true ~backlog:5 addr in - let stopResult = Eio.Net.run_server sock req_handler ~on_error:err_handler ?stop:(Some stop_promise) in - Eio.traceln "StopResult=%s" stopResult - - let run env stop_promise = - let net = (Eio.Stdenv.net env) in - let port = 8080 in - Eio.Switch.run @@ switch net port stop_promise - -end +module EioLspServer = Tlapm_lsp_lib.EioLspServer +(** The main entry point. *) let () = Eio_main.run @@ fun env -> let (stop_promise, stop_resolver) = Eio.Std.Promise.create () in let handle_signal (_signum : int) = Eio.Std.Promise.resolve stop_resolver "Stopping on SigINT" in let () = Sys.set_signal Sys.sigint (Signal_handle handle_signal) in - LspServer.run env stop_promise + EioLspServer.run env stop_promise diff --git a/lsp/lib/tlapm_lsp_lib.ml b/lsp/lib/tlapm_lsp_lib.ml index b049c1c1..37b383a7 100644 --- a/lsp/lib/tlapm_lsp_lib.ml +++ b/lsp/lib/tlapm_lsp_lib.ml @@ -1,15 +1,13 @@ -module type EioLspParser = sig +(** Here we construct a decoder/encoder for the LSP protocol on top of Eio flows. *) +module EioLspCodec : sig type 'a io_res = | IoOk of 'a | IoErr of exn val read : Eio.Buf_read.t -> Jsonrpc.Packet.t option io_res val write : Eio.Buf_write.t -> Jsonrpc.Packet.t -> unit io_res -end - -(** Here we construct an LSP protocol parser on top of Eio flows. *) -module EioLspParser : EioLspParser = struct +end = struct type 'a io_res = | IoOk of 'a | IoErr of exn @@ -53,3 +51,52 @@ module EioLspParser : EioLspParser = struct let read = LspIo.read let write = LspIo.write end + +(** Here we serve the LSP RPC over TCP. *) +module EioLspServer = struct + + (* // TODO: curl -vvv -X POST -H 'Content-Type: application/vscode-jsonrpc; charset=utf-8' -d '{"jsonrpc": "2.0", "id": 1, "method": "textDocument/completion", "params": { }}' http://localhost:8080/ *) + let lsp_packet_handler (packet : Jsonrpc.Packet.t) write_fun = + Eio.traceln "Got LSP Packet"; + write_fun packet (* // TODO: That's just echo. *) + + let rec lsp_stream_handler buf_r buf_w = + let open EioLspCodec in + let write_fun out_packet = + match write buf_w out_packet with + | IoOk () -> + Eio.Buf_write.flush buf_w + | IoErr exn -> + Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) + in + match read buf_r with + | IoOk (Some packet) -> + lsp_packet_handler packet write_fun; + lsp_stream_handler buf_r buf_w + | IoOk None -> + Eio.traceln "No packet was read." + | IoErr exn -> + Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) + + let err_handler = + Eio.traceln "Error handling connection: %a" Fmt.exn + + let req_handler flow _addr = + Eio.traceln "Server: got connection from client"; + let buf_r = Eio.Buf_read.of_flow flow ~max_size:1024 in + Eio.Buf_write.with_flow flow @@ fun buf_w -> + lsp_stream_handler buf_r buf_w + + let switch (net: 'a Eio.Net.ty Eio.Std.r) port stop_promise sw = + Eio.traceln "Switch started"; + let addr = (`Tcp (Eio.Net.Ipaddr.V4.loopback, port)) in + let sock = Eio.Net.listen net ~sw ~reuse_addr:true ~backlog:5 addr in + let stopResult = Eio.Net.run_server sock req_handler ~on_error:err_handler ?stop:(Some stop_promise) in + Eio.traceln "StopResult=%s" stopResult + + let run env stop_promise = + let net = (Eio.Stdenv.net env) in + let port = 8080 in + Eio.Switch.run @@ switch net port stop_promise + +end diff --git a/lsp/lib/tlapm_lsp_lib.mli b/lsp/lib/tlapm_lsp_lib.mli index f2874dd0..4c0489ae 100644 --- a/lsp/lib/tlapm_lsp_lib.mli +++ b/lsp/lib/tlapm_lsp_lib.mli @@ -1,10 +1,3 @@ -module type EioLspParser = sig - type 'a io_res = - | IoOk of 'a - | IoErr of exn - - val read : Eio.Buf_read.t -> Jsonrpc.Packet.t option io_res - val write : Eio.Buf_write.t -> Jsonrpc.Packet.t -> unit io_res -end - -module EioLspParser : EioLspParser +module EioLspServer : sig + val run : Eio_unix.Stdenv.base -> string Eio.Std.Promise.t -> unit +end \ No newline at end of file From c5e54d402074808c0a0dfe2fa1e6626ff2053091 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Tue, 19 Sep 2023 23:51:46 +0300 Subject: [PATCH 004/140] Use the code formatter. Signed-off-by: Karolis Petrauskas --- .ocamlformat | 2 ++ Makefile | 5 ++- dune-project | 1 - lsp/bin/tlapm_lsp.ml | 12 ++++--- lsp/lib/dune | 2 +- lsp/lib/tlapm_lsp_lib.ml | 68 ++++++++++++++++++--------------------- lsp/lib/tlapm_lsp_lib.mli | 2 +- tlapm.opam | 2 +- 8 files changed, 48 insertions(+), 46 deletions(-) create mode 100644 .ocamlformat diff --git a/.ocamlformat b/.ocamlformat new file mode 100644 index 00000000..0e0b64be --- /dev/null +++ b/.ocamlformat @@ -0,0 +1,2 @@ +version=0.26.0 +profile=default diff --git a/Makefile b/Makefile index 21e364ee..c94d54f9 100644 --- a/Makefile +++ b/Makefile @@ -21,7 +21,10 @@ opam-deps: opam install ./ --deps-only --yes --working-dir opam-deps-opt: - opam install eio_main fiber lsp --yes --working-dir # TODO: Remove fiber. + opam install eio_main lsp --yes --working-dir + +opan-deps-dev: + opam install ocamlformat opam-deps-dev: opam install ocamlformat ocaml-lsp-server diff --git a/dune-project b/dune-project index b132ad7b..b3f9c8c5 100644 --- a/dune-project +++ b/dune-project @@ -44,5 +44,4 @@ ppx_assert) (depopts lsp ; https://github.com/ocaml/ocaml-lsp - fiber ; TODO: Do we need it for lsp? Probably not. eio_main)) ; https://github.com/ocaml-multicore/eio, only available on OCaml version >= 5. diff --git a/lsp/bin/tlapm_lsp.ml b/lsp/bin/tlapm_lsp.ml index 78b9eb59..7ded53a2 100644 --- a/lsp/bin/tlapm_lsp.ml +++ b/lsp/bin/tlapm_lsp.ml @@ -2,8 +2,12 @@ module EioLspServer = Tlapm_lsp_lib.EioLspServer (** The main entry point. *) let () = - Eio_main.run @@ fun env -> - let (stop_promise, stop_resolver) = Eio.Std.Promise.create () in - let handle_signal (_signum : int) = Eio.Std.Promise.resolve stop_resolver "Stopping on SigINT" in - let () = Sys.set_signal Sys.sigint (Signal_handle handle_signal) in + let main env = + let stop_promise, stop_resolver = Eio.Std.Promise.create () in + let handle_signal (_signum : int) = + Eio.Std.Promise.resolve stop_resolver "Stopping on SigINT" + in + Sys.set_signal Sys.sigint (Signal_handle handle_signal); EioLspServer.run env stop_promise + in + Eio_main.run main diff --git a/lsp/lib/dune b/lsp/lib/dune index 0f8a81dc..3fba6eaf 100644 --- a/lsp/lib/dune +++ b/lsp/lib/dune @@ -1,4 +1,4 @@ (library (name tlapm_lsp_lib) (optional) ; Only build, if eio is available, which is only the case for ocaml > 5. - (libraries tlapm_lib lsp eio_main fiber)) ; TODO: Remove fiber. \ No newline at end of file + (libraries tlapm_lib lsp eio_main)) diff --git a/lsp/lib/tlapm_lsp_lib.ml b/lsp/lib/tlapm_lsp_lib.ml index 37b383a7..14426193 100644 --- a/lsp/lib/tlapm_lsp_lib.ml +++ b/lsp/lib/tlapm_lsp_lib.ml @@ -1,47 +1,42 @@ - (** Here we construct a decoder/encoder for the LSP protocol on top of Eio flows. *) module EioLspCodec : sig - type 'a io_res = - | IoOk of 'a - | IoErr of exn + type 'a io_res = IoOk of 'a | IoErr of exn val read : Eio.Buf_read.t -> Jsonrpc.Packet.t option io_res val write : Eio.Buf_write.t -> Jsonrpc.Packet.t -> unit io_res end = struct - type 'a io_res = - | IoOk of 'a - | IoErr of exn + type 'a io_res = IoOk of 'a | IoErr of exn module IoState = struct type 'a t = 'a io_res + let return x = IoOk x let raise exn = IoErr exn + module O = struct let ( let+ ) st f = - match st with - | IoOk a -> IoOk (f a) - | IoErr exn -> IoErr exn - let ( let* ) st f = - match st with - | IoOk a -> f a - | IoErr exn -> IoErr exn + match st with IoOk a -> IoOk (f a) | IoErr exn -> IoErr exn + + let ( let* ) st f = match st with IoOk a -> f a | IoErr exn -> IoErr exn end end module IoChan = struct type output = Eio.Buf_write.t type input = Eio.Buf_read.t - let read_line (buf : input): string option IoState.t = + + let read_line (buf : input) : string option IoState.t = let line = Eio.Buf_read.line buf in IoOk (Some line) + let read_exactly (buf : input) (n : int) : string option IoState.t = let data = Eio.Buf_read.take n buf in IoOk (Some data) + let rec write (buf : output) (lines : string list) : unit IoState.t = match lines with - | [] -> - IoOk () - | line :: tail -> + | [] -> IoOk () + | line :: tail -> let () = Eio.Buf_write.string buf line in write buf tail end @@ -53,8 +48,9 @@ end = struct end (** Here we serve the LSP RPC over TCP. *) -module EioLspServer = struct - +module EioLspServer : sig + val run : Eio_unix.Stdenv.base -> string Eio.Std.Promise.t -> unit +end = struct (* // TODO: curl -vvv -X POST -H 'Content-Type: application/vscode-jsonrpc; charset=utf-8' -d '{"jsonrpc": "2.0", "id": 1, "method": "textDocument/completion", "params": { }}' http://localhost:8080/ *) let lsp_packet_handler (packet : Jsonrpc.Packet.t) write_fun = Eio.traceln "Got LSP Packet"; @@ -64,39 +60,37 @@ module EioLspServer = struct let open EioLspCodec in let write_fun out_packet = match write buf_w out_packet with - | IoOk () -> - Eio.Buf_write.flush buf_w + | IoOk () -> Eio.Buf_write.flush buf_w | IoErr exn -> - Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) - in + Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) + in match read buf_r with - | IoOk (Some packet) -> + | IoOk (Some packet) -> lsp_packet_handler packet write_fun; lsp_stream_handler buf_r buf_w - | IoOk None -> - Eio.traceln "No packet was read." - | IoErr exn -> + | IoOk None -> Eio.traceln "No packet was read." + | IoErr exn -> Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) - let err_handler = - Eio.traceln "Error handling connection: %a" Fmt.exn + let err_handler = Eio.traceln "Error handling connection: %a" Fmt.exn let req_handler flow _addr = Eio.traceln "Server: got connection from client"; let buf_r = Eio.Buf_read.of_flow flow ~max_size:1024 in - Eio.Buf_write.with_flow flow @@ fun buf_w -> - lsp_stream_handler buf_r buf_w + Eio.Buf_write.with_flow flow @@ fun buf_w -> lsp_stream_handler buf_r buf_w - let switch (net: 'a Eio.Net.ty Eio.Std.r) port stop_promise sw = + let switch (net : 'a Eio.Net.ty Eio.Std.r) port stop_promise sw = Eio.traceln "Switch started"; - let addr = (`Tcp (Eio.Net.Ipaddr.V4.loopback, port)) in + let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, port) in let sock = Eio.Net.listen net ~sw ~reuse_addr:true ~backlog:5 addr in - let stopResult = Eio.Net.run_server sock req_handler ~on_error:err_handler ?stop:(Some stop_promise) in + let stopResult = + Eio.Net.run_server sock req_handler ~on_error:err_handler + ?stop:(Some stop_promise) + in Eio.traceln "StopResult=%s" stopResult let run env stop_promise = - let net = (Eio.Stdenv.net env) in + let net = Eio.Stdenv.net env in let port = 8080 in Eio.Switch.run @@ switch net port stop_promise - end diff --git a/lsp/lib/tlapm_lsp_lib.mli b/lsp/lib/tlapm_lsp_lib.mli index 4c0489ae..ca97c6d2 100644 --- a/lsp/lib/tlapm_lsp_lib.mli +++ b/lsp/lib/tlapm_lsp_lib.mli @@ -1,3 +1,3 @@ module EioLspServer : sig val run : Eio_unix.Stdenv.base -> string Eio.Std.Promise.t -> unit -end \ No newline at end of file +end diff --git a/tlapm.opam b/tlapm.opam index 7b1eb473..2ef7e694 100644 --- a/tlapm.opam +++ b/tlapm.opam @@ -34,7 +34,7 @@ depends: [ "ppx_assert" "odoc" {with-doc} ] -depopts: ["lsp" "fiber" "eio_main"] +depopts: ["lsp" "eio_main"] dev-repo: "git+https://github.com/tlaplus/tlapm.git" build: [ # This is to override the build step, add the invocation of `Makefile.post-install`. ["dune" "subst"] {dev} From e71f9364a83204db079547f47f4bcf9c63b9a799 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Wed, 20 Sep 2023 01:02:18 +0300 Subject: [PATCH 005/140] Improving it. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_lib.ml | 54 +++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/lsp/lib/tlapm_lsp_lib.ml b/lsp/lib/tlapm_lsp_lib.ml index 14426193..edede7a7 100644 --- a/lsp/lib/tlapm_lsp_lib.ml +++ b/lsp/lib/tlapm_lsp_lib.ml @@ -1,23 +1,19 @@ (** Here we construct a decoder/encoder for the LSP protocol on top of Eio flows. *) module EioLspCodec : sig - type 'a io_res = IoOk of 'a | IoErr of exn - - val read : Eio.Buf_read.t -> Jsonrpc.Packet.t option io_res - val write : Eio.Buf_write.t -> Jsonrpc.Packet.t -> unit io_res + val read : Eio.Buf_read.t -> (Jsonrpc.Packet.t option, exn) result + val write : Eio.Buf_write.t -> Jsonrpc.Packet.t -> (unit, exn) result end = struct - type 'a io_res = IoOk of 'a | IoErr of exn - module IoState = struct - type 'a t = 'a io_res + type 'a t = ('a, exn) result - let return x = IoOk x - let raise exn = IoErr exn + let return x = Ok x + let raise exn = Error exn module O = struct let ( let+ ) st f = - match st with IoOk a -> IoOk (f a) | IoErr exn -> IoErr exn + match st with Ok a -> Ok (f a) | Error exn -> Error exn - let ( let* ) st f = match st with IoOk a -> f a | IoErr exn -> IoErr exn + let ( let* ) st f = match st with Ok a -> f a | Error exn -> Error exn end end @@ -27,15 +23,15 @@ end = struct let read_line (buf : input) : string option IoState.t = let line = Eio.Buf_read.line buf in - IoOk (Some line) + Ok (Some line) let read_exactly (buf : input) (n : int) : string option IoState.t = let data = Eio.Buf_read.take n buf in - IoOk (Some data) + Ok (Some data) let rec write (buf : output) (lines : string list) : unit IoState.t = match lines with - | [] -> IoOk () + | [] -> Ok () | line :: tail -> let () = Eio.Buf_write.string buf line in write buf tail @@ -54,22 +50,40 @@ end = struct (* // TODO: curl -vvv -X POST -H 'Content-Type: application/vscode-jsonrpc; charset=utf-8' -d '{"jsonrpc": "2.0", "id": 1, "method": "textDocument/completion", "params": { }}' http://localhost:8080/ *) let lsp_packet_handler (packet : Jsonrpc.Packet.t) write_fun = Eio.traceln "Got LSP Packet"; - write_fun packet (* // TODO: That's just echo. *) + let jsonrpc_req_handler jsonrpc_req = + match Lsp.Client_request.of_jsonrpc jsonrpc_req with + | Ok (E (Initialize _params)) -> () (* TODO: Handle all the cases. *) + | _ -> () + in + let jsonrpc_notif_handler jsonrpc_notif = + match Lsp.Client_notification.of_jsonrpc jsonrpc_notif with (* TODO: Handle all the cases. *) + | Ok Initialized -> () + | Ok (TextDocumentDidOpen _params) -> () + | Ok (UnknownNotification _params) -> + write_fun packet (* // TODO: That's just echo. *) + | _ -> () + in + match packet with + | Notification x -> jsonrpc_notif_handler x + | Request jsonrpc_req -> jsonrpc_req_handler jsonrpc_req + | Response _ -> () (* // TODO: Handle it. *) + | Batch_call _ -> () (* // TODO: Handle it. *) + | Batch_response _ -> () let rec lsp_stream_handler buf_r buf_w = let open EioLspCodec in let write_fun out_packet = match write buf_w out_packet with - | IoOk () -> Eio.Buf_write.flush buf_w - | IoErr exn -> + | Ok () -> Eio.Buf_write.flush buf_w + | Error exn -> Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) in match read buf_r with - | IoOk (Some packet) -> + | Ok (Some packet) -> lsp_packet_handler packet write_fun; lsp_stream_handler buf_r buf_w - | IoOk None -> Eio.traceln "No packet was read." - | IoErr exn -> + | Ok None -> Eio.traceln "No packet was read." + | Error exn -> Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) let err_handler = Eio.traceln "Error handling connection: %a" Fmt.exn From 705f1ccfad906db1a9915faf596e0c6dcd9377a0 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Wed, 20 Sep 2023 22:24:10 +0300 Subject: [PATCH 006/140] CLI added, some refactorings, 2 transports. Signed-off-by: Karolis Petrauskas --- dune-project | 1 + lsp/README.md | 14 +++++ lsp/bin/dune | 2 +- lsp/bin/tlapm_lsp.ml | 57 +++++++++++++++-- lsp/lib/tlapm_lsp_codec.ml | 36 +++++++++++ lsp/lib/tlapm_lsp_codec.mli | 7 +++ lsp/lib/tlapm_lsp_lib.ml | 111 +--------------------------------- lsp/lib/tlapm_lsp_lib.mli | 7 ++- lsp/lib/tlapm_lsp_packets.ml | 26 ++++++++ lsp/lib/tlapm_lsp_packets.mli | 4 ++ lsp/lib/tlapm_lsp_server.ml | 53 ++++++++++++++++ lsp/lib/tlapm_lsp_server.mli | 9 +++ tlapm.opam | 1 + 13 files changed, 211 insertions(+), 117 deletions(-) create mode 100644 lsp/README.md create mode 100644 lsp/lib/tlapm_lsp_codec.ml create mode 100644 lsp/lib/tlapm_lsp_codec.mli create mode 100644 lsp/lib/tlapm_lsp_packets.ml create mode 100644 lsp/lib/tlapm_lsp_packets.mli create mode 100644 lsp/lib/tlapm_lsp_server.ml create mode 100644 lsp/lib/tlapm_lsp_server.mli diff --git a/dune-project b/dune-project index b3f9c8c5..8ec6e3c1 100644 --- a/dune-project +++ b/dune-project @@ -40,6 +40,7 @@ dune-site dune-build-info sexplib + cmdliner ppx_inline_test ppx_assert) (depopts diff --git a/lsp/README.md b/lsp/README.md new file mode 100644 index 00000000..360781cb --- /dev/null +++ b/lsp/README.md @@ -0,0 +1,14 @@ +# LSP interface to the TLAPS + +The `tlapm_lsp` works as an adapter between the `tlapm` and code editors, e.g., VSCode. +It is responsible for: + - Parsing the document structure to locate features related to proofs, e.g.: + - proof obligation by cursor position, possibly collecting all the subtree of obligations. + - TODO: Folding of proofs. + - Running the `tlapm` on specific obligations and reporting the results. + - TODO: Proof re-numbering. + - TODO: Proof decomposition. + - TODO: Easier experimentation on missing facts. + +The test folder contains a VSCode extension / LSP client. It is meant only for testing, +the real integration should be done in the TLA+ VSCode extension. diff --git a/lsp/bin/dune b/lsp/bin/dune index 1473487d..4ad22e42 100644 --- a/lsp/bin/dune +++ b/lsp/bin/dune @@ -2,4 +2,4 @@ (name tlapm_lsp) (public_name tlapm_lsp) (optional) ; Only build, if eio is available, which is only the case for ocaml > 5. - (libraries tlapm_lsp_lib eio_main)) + (libraries tlapm_lsp_lib eio_main cmdliner)) diff --git a/lsp/bin/tlapm_lsp.ml b/lsp/bin/tlapm_lsp.ml index 7ded53a2..97eeb38c 100644 --- a/lsp/bin/tlapm_lsp.ml +++ b/lsp/bin/tlapm_lsp.ml @@ -1,13 +1,62 @@ -module EioLspServer = Tlapm_lsp_lib.EioLspServer +open Cmdliner -(** The main entry point. *) -let () = +type cli_args = { tr_stdio : bool; tr_socket : int option } + +let transport_of_args args = + let open Tlapm_lsp_lib.Server in + match args with + | { tr_stdio = true; tr_socket = None; _ } -> Ok Stdio + | { tr_stdio = false; tr_socket = Some port; _ } -> Ok (Socket port) + | _ -> Error "Exactly one of transports has to be specified." + +let run_with_transport transport = let main env = let stop_promise, stop_resolver = Eio.Std.Promise.create () in let handle_signal (_signum : int) = Eio.Std.Promise.resolve stop_resolver "Stopping on SigINT" in Sys.set_signal Sys.sigint (Signal_handle handle_signal); - EioLspServer.run env stop_promise + Tlapm_lsp_lib.Server.run transport env stop_promise in Eio_main.run main + +module Cli = struct + let run_with_args args = + match transport_of_args args with + | Ok transport -> `Ok (run_with_transport transport) + | Error err -> `Error (false, err) + + let arg_stdio = + let doc = "Run LSP over StdIO." in + let info = Arg.info [ "stdio" ] ~docv:"BOOL" ~doc in + Arg.value (Arg.flag info) + + let arg_socket = + let doc = "Run LSP over TCP, use the specified port." in + let info = Arg.info [ "socket"; "port" ] ~docv:"NUM" ~doc in + Arg.value (Arg.opt (Arg.some Arg.int) None info) + + let term () = + let combine tr_stdio tr_socket = + let args = { tr_stdio; tr_socket } in + run_with_args args + in + Term.(const combine $ arg_stdio $ arg_socket) + + let name = "tlapm_lsp" + let doc = "LSP interface for TLAPS." + + let man = + [ + `S Manpage.s_description; + `P "tlapm_lsp allows LSP based IDEs to access the prover functions."; + `S Manpage.s_see_also; + `P "The TLAPM code repository: https://github.com/tlaplus/tlapm"; + ] + + let main () = + let info = Cmd.info ~doc ~man name in + Cmd.v info (Term.ret (term ())) |> Cmd.eval |> Stdlib.exit +end + +let () = Cli.main () diff --git a/lsp/lib/tlapm_lsp_codec.ml b/lsp/lib/tlapm_lsp_codec.ml new file mode 100644 index 00000000..16dd62e9 --- /dev/null +++ b/lsp/lib/tlapm_lsp_codec.ml @@ -0,0 +1,36 @@ +module IoState = struct + type 'a t = ('a, exn) result + + let return x = Ok x + let raise exn = Error exn + + module O = struct + let ( let+ ) st f = Result.map f st + let ( let* ) st f = Result.bind st f + end +end + +module IoChan = struct + type output = Eio.Buf_write.t + type input = Eio.Buf_read.t + + let read_line (buf : input) : string option IoState.t = + let line = Eio.Buf_read.line buf in + Ok (Some line) + + let read_exactly (buf : input) (n : int) : string option IoState.t = + let data = Eio.Buf_read.take n buf in + Ok (Some data) + + let rec write (buf : output) (lines : string list) : unit IoState.t = + match lines with + | [] -> Ok () + | line :: tail -> + let () = Eio.Buf_write.string buf line in + write buf tail +end + +module LspIo = Lsp.Io.Make (IoState) (IoChan) + +let read = LspIo.read +let write = LspIo.write diff --git a/lsp/lib/tlapm_lsp_codec.mli b/lsp/lib/tlapm_lsp_codec.mli new file mode 100644 index 00000000..d2bfe6e1 --- /dev/null +++ b/lsp/lib/tlapm_lsp_codec.mli @@ -0,0 +1,7 @@ +(** +Here we construct a decoder/encoder for the LSP protocol on top of Eio flows. +We use the lsp module from the ocaml-lsp server and configure it to run over Eio. +*) + +val read : Eio.Buf_read.t -> (Jsonrpc.Packet.t option, exn) result +val write : Eio.Buf_write.t -> Jsonrpc.Packet.t -> (unit, exn) result diff --git a/lsp/lib/tlapm_lsp_lib.ml b/lsp/lib/tlapm_lsp_lib.ml index edede7a7..17c4016b 100644 --- a/lsp/lib/tlapm_lsp_lib.ml +++ b/lsp/lib/tlapm_lsp_lib.ml @@ -1,110 +1 @@ -(** Here we construct a decoder/encoder for the LSP protocol on top of Eio flows. *) -module EioLspCodec : sig - val read : Eio.Buf_read.t -> (Jsonrpc.Packet.t option, exn) result - val write : Eio.Buf_write.t -> Jsonrpc.Packet.t -> (unit, exn) result -end = struct - module IoState = struct - type 'a t = ('a, exn) result - - let return x = Ok x - let raise exn = Error exn - - module O = struct - let ( let+ ) st f = - match st with Ok a -> Ok (f a) | Error exn -> Error exn - - let ( let* ) st f = match st with Ok a -> f a | Error exn -> Error exn - end - end - - module IoChan = struct - type output = Eio.Buf_write.t - type input = Eio.Buf_read.t - - let read_line (buf : input) : string option IoState.t = - let line = Eio.Buf_read.line buf in - Ok (Some line) - - let read_exactly (buf : input) (n : int) : string option IoState.t = - let data = Eio.Buf_read.take n buf in - Ok (Some data) - - let rec write (buf : output) (lines : string list) : unit IoState.t = - match lines with - | [] -> Ok () - | line :: tail -> - let () = Eio.Buf_write.string buf line in - write buf tail - end - - module LspIo = Lsp.Io.Make (IoState) (IoChan) - - let read = LspIo.read - let write = LspIo.write -end - -(** Here we serve the LSP RPC over TCP. *) -module EioLspServer : sig - val run : Eio_unix.Stdenv.base -> string Eio.Std.Promise.t -> unit -end = struct - (* // TODO: curl -vvv -X POST -H 'Content-Type: application/vscode-jsonrpc; charset=utf-8' -d '{"jsonrpc": "2.0", "id": 1, "method": "textDocument/completion", "params": { }}' http://localhost:8080/ *) - let lsp_packet_handler (packet : Jsonrpc.Packet.t) write_fun = - Eio.traceln "Got LSP Packet"; - let jsonrpc_req_handler jsonrpc_req = - match Lsp.Client_request.of_jsonrpc jsonrpc_req with - | Ok (E (Initialize _params)) -> () (* TODO: Handle all the cases. *) - | _ -> () - in - let jsonrpc_notif_handler jsonrpc_notif = - match Lsp.Client_notification.of_jsonrpc jsonrpc_notif with (* TODO: Handle all the cases. *) - | Ok Initialized -> () - | Ok (TextDocumentDidOpen _params) -> () - | Ok (UnknownNotification _params) -> - write_fun packet (* // TODO: That's just echo. *) - | _ -> () - in - match packet with - | Notification x -> jsonrpc_notif_handler x - | Request jsonrpc_req -> jsonrpc_req_handler jsonrpc_req - | Response _ -> () (* // TODO: Handle it. *) - | Batch_call _ -> () (* // TODO: Handle it. *) - | Batch_response _ -> () - - let rec lsp_stream_handler buf_r buf_w = - let open EioLspCodec in - let write_fun out_packet = - match write buf_w out_packet with - | Ok () -> Eio.Buf_write.flush buf_w - | Error exn -> - Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) - in - match read buf_r with - | Ok (Some packet) -> - lsp_packet_handler packet write_fun; - lsp_stream_handler buf_r buf_w - | Ok None -> Eio.traceln "No packet was read." - | Error exn -> - Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) - - let err_handler = Eio.traceln "Error handling connection: %a" Fmt.exn - - let req_handler flow _addr = - Eio.traceln "Server: got connection from client"; - let buf_r = Eio.Buf_read.of_flow flow ~max_size:1024 in - Eio.Buf_write.with_flow flow @@ fun buf_w -> lsp_stream_handler buf_r buf_w - - let switch (net : 'a Eio.Net.ty Eio.Std.r) port stop_promise sw = - Eio.traceln "Switch started"; - let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, port) in - let sock = Eio.Net.listen net ~sw ~reuse_addr:true ~backlog:5 addr in - let stopResult = - Eio.Net.run_server sock req_handler ~on_error:err_handler - ?stop:(Some stop_promise) - in - Eio.traceln "StopResult=%s" stopResult - - let run env stop_promise = - let net = Eio.Stdenv.net env in - let port = 8080 in - Eio.Switch.run @@ switch net port stop_promise -end +module Server = Tlapm_lsp_server diff --git a/lsp/lib/tlapm_lsp_lib.mli b/lsp/lib/tlapm_lsp_lib.mli index ca97c6d2..cdda796d 100644 --- a/lsp/lib/tlapm_lsp_lib.mli +++ b/lsp/lib/tlapm_lsp_lib.mli @@ -1,3 +1,6 @@ -module EioLspServer : sig - val run : Eio_unix.Stdenv.base -> string Eio.Std.Promise.t -> unit +module Server : sig + type transport = Stdio | Socket of int + + val run : + transport -> Eio_unix.Stdenv.base -> string Eio.Std.Promise.t -> unit end diff --git a/lsp/lib/tlapm_lsp_packets.ml b/lsp/lib/tlapm_lsp_packets.ml new file mode 100644 index 00000000..f2a82a3f --- /dev/null +++ b/lsp/lib/tlapm_lsp_packets.ml @@ -0,0 +1,26 @@ +(* // TODO: curl -vvv -X POST -H 'Content-Type: application/vscode-jsonrpc; charset=utf-8' -d '{"jsonrpc": "2.0", "id": 1, "method": "textDocument/completion", "params": { }}' http://localhost:8080/ *) + +let handle_jsonrpc_notif jsonrpc_notif _writer = + match Lsp.Client_notification.of_jsonrpc jsonrpc_notif with + (* TODO: Handle all the cases. *) + | Ok Initialized -> () + | Ok (TextDocumentDidOpen _params) -> () + | Ok (UnknownNotification _params) -> + () + (* writer packet *) + (* // TODO: That's just echo. *) + | _ -> () + +let handle_jsonrpc_request jsonrpc_req _writer = + match Lsp.Client_request.of_jsonrpc jsonrpc_req with + | Ok (E (Initialize _params)) -> () (* TODO: Handle all the cases. *) + | _ -> () + +let handle_jsonrpc_packet (packet : Jsonrpc.Packet.t) writer = + Eio.traceln "Got LSP Packet"; + match packet with + | Notification jsonrpc_notif -> handle_jsonrpc_notif jsonrpc_notif writer + | Request jsonrpc_req -> handle_jsonrpc_request jsonrpc_req writer + | Response _ -> () (* // TODO: Handle it. *) + | Batch_call _ -> () (* // TODO: Handle it. *) + | Batch_response _ -> () diff --git a/lsp/lib/tlapm_lsp_packets.mli b/lsp/lib/tlapm_lsp_packets.mli new file mode 100644 index 00000000..3ff1dd2d --- /dev/null +++ b/lsp/lib/tlapm_lsp_packets.mli @@ -0,0 +1,4 @@ +(** Here we have all the TLAPM specific LSP action handlers. *) + +val handle_jsonrpc_packet : + Jsonrpc.Packet.t -> (Jsonrpc.Packet.t -> unit) -> unit diff --git a/lsp/lib/tlapm_lsp_server.ml b/lsp/lib/tlapm_lsp_server.ml new file mode 100644 index 00000000..50ae4e95 --- /dev/null +++ b/lsp/lib/tlapm_lsp_server.ml @@ -0,0 +1,53 @@ +let max_size = 50 * 1024 * 1024 +(* 50 MB should be enough. *) + +type transport = Stdio | Socket of int + +let rec lsp_stream_handler buf_r buf_w = + let open Tlapm_lsp_codec in + let writer out_packet = + match write buf_w out_packet with + | Ok () -> Eio.Buf_write.flush buf_w + | Error exn -> + Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) + in + match read buf_r with + | Ok (Some packet) -> + Tlapm_lsp_packets.handle_jsonrpc_packet packet writer; + lsp_stream_handler buf_r buf_w + | Ok None -> Eio.traceln "No packet was read." + | Error exn -> + Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) + +let err_handler = Eio.traceln "Error handling connection: %a" Fmt.exn + +let req_handler flow _addr = + Eio.traceln "Server: got connection from client"; + let buf_r = Eio.Buf_read.of_flow flow ~max_size in + Eio.Buf_write.with_flow flow @@ fun buf_w -> lsp_stream_handler buf_r buf_w + +let switch (net : 'a Eio.Net.ty Eio.Std.r) port stop_promise sw = + Eio.traceln "Switch started"; + let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, port) in + let sock = Eio.Net.listen net ~sw ~reuse_addr:true ~backlog:5 addr in + let stopResult = + Eio.Net.run_server sock req_handler ~on_error:err_handler + ?stop:(Some stop_promise) + in + Eio.traceln "StopResult=%s" stopResult + +let run_on_stdio env = + let switch_fun _sw = + let buf_r = Eio.Buf_read.of_flow (Eio.Stdenv.stdin env) ~max_size in + Eio.Buf_write.with_flow (Eio.Stdenv.stdout env) (lsp_stream_handler buf_r) + in + Eio.Switch.run switch_fun + +let run_on_socket port env stop_promise = + let net = Eio.Stdenv.net env in + Eio.Switch.run @@ switch net port stop_promise + +let run transport env stop_promise = + match transport with + | Stdio -> run_on_stdio env + | Socket port -> run_on_socket port env stop_promise diff --git a/lsp/lib/tlapm_lsp_server.mli b/lsp/lib/tlapm_lsp_server.mli new file mode 100644 index 00000000..f04b35d2 --- /dev/null +++ b/lsp/lib/tlapm_lsp_server.mli @@ -0,0 +1,9 @@ +type transport = Stdio | Socket of int + +(** +Here we serve the LSP RPC over TCP. +This module contains only the generic server-related functions, +the tlapm-specifics is moved to tlapm_lsp_packets. +*) + +val run : transport -> Eio_unix.Stdenv.base -> string Eio.Std.Promise.t -> unit diff --git a/tlapm.opam b/tlapm.opam index 2ef7e694..eee6ea74 100644 --- a/tlapm.opam +++ b/tlapm.opam @@ -30,6 +30,7 @@ depends: [ "dune-site" "dune-build-info" "sexplib" + "cmdliner" "ppx_inline_test" "ppx_assert" "odoc" {with-doc} From 7b6735fb16a1b3e019be2f2b467a967b92b12aca Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Wed, 20 Sep 2023 23:56:29 +0300 Subject: [PATCH 007/140] IO Tracing added. Signed-off-by: Karolis Petrauskas --- lsp/bin/tlapm_lsp.ml | 33 +++++++-------- lsp/lib/tlapm_lsp_codec.ml | 19 ++++++--- lsp/lib/tlapm_lsp_codec.mli | 8 +++- lsp/lib/tlapm_lsp_lib.mli | 6 ++- lsp/lib/tlapm_lsp_server.ml | 82 +++++++++++++++++++++++------------- lsp/lib/tlapm_lsp_server.mli | 3 +- 6 files changed, 95 insertions(+), 56 deletions(-) diff --git a/lsp/bin/tlapm_lsp.ml b/lsp/bin/tlapm_lsp.ml index 97eeb38c..695d0cf9 100644 --- a/lsp/bin/tlapm_lsp.ml +++ b/lsp/bin/tlapm_lsp.ml @@ -1,31 +1,24 @@ open Cmdliner -type cli_args = { tr_stdio : bool; tr_socket : int option } - -let transport_of_args args = +let transport_of_args tr_stdio tr_socket = let open Tlapm_lsp_lib.Server in - match args with - | { tr_stdio = true; tr_socket = None; _ } -> Ok Stdio - | { tr_stdio = false; tr_socket = Some port; _ } -> Ok (Socket port) + match (tr_stdio, tr_socket) with + | true, None -> Ok Stdio + | false, Some port -> Ok (Socket port) | _ -> Error "Exactly one of transports has to be specified." -let run_with_transport transport = +let run transport trace = let main env = let stop_promise, stop_resolver = Eio.Std.Promise.create () in let handle_signal (_signum : int) = Eio.Std.Promise.resolve stop_resolver "Stopping on SigINT" in Sys.set_signal Sys.sigint (Signal_handle handle_signal); - Tlapm_lsp_lib.Server.run transport env stop_promise + Tlapm_lsp_lib.Server.run transport trace env stop_promise in Eio_main.run main module Cli = struct - let run_with_args args = - match transport_of_args args with - | Ok transport -> `Ok (run_with_transport transport) - | Error err -> `Error (false, err) - let arg_stdio = let doc = "Run LSP over StdIO." in let info = Arg.info [ "stdio" ] ~docv:"BOOL" ~doc in @@ -36,12 +29,18 @@ module Cli = struct let info = Arg.info [ "socket"; "port" ] ~docv:"NUM" ~doc in Arg.value (Arg.opt (Arg.some Arg.int) None info) + let arg_trace = + let doc = "Trace protocol's IO to the StdErr." in + let info = Arg.info [ "trace" ] ~docv:"BOOL" ~doc in + Arg.value (Arg.flag info) + let term () = - let combine tr_stdio tr_socket = - let args = { tr_stdio; tr_socket } in - run_with_args args + let combine tr_stdio tr_socket trace = + match transport_of_args tr_stdio tr_socket with + | Ok transport -> `Ok (run transport trace) + | Error err -> `Error (false, err) in - Term.(const combine $ arg_stdio $ arg_socket) + Term.(const combine $ arg_stdio $ arg_socket $ arg_trace) let name = "tlapm_lsp" let doc = "LSP interface for TLAPS." diff --git a/lsp/lib/tlapm_lsp_codec.ml b/lsp/lib/tlapm_lsp_codec.ml index 16dd62e9..70492f57 100644 --- a/lsp/lib/tlapm_lsp_codec.ml +++ b/lsp/lib/tlapm_lsp_codec.ml @@ -1,3 +1,7 @@ +type trace_fun = string -> unit +type input_chan = Eio.Buf_read.t * trace_fun +type output_chan = Eio.Buf_write.t * trace_fun + module IoState = struct type 'a t = ('a, exn) result @@ -11,23 +15,26 @@ module IoState = struct end module IoChan = struct - type output = Eio.Buf_write.t - type input = Eio.Buf_read.t + type input = input_chan + type output = output_chan - let read_line (buf : input) : string option IoState.t = + let read_line ((buf, trace) : input) : string option IoState.t = let line = Eio.Buf_read.line buf in + let () = trace line in Ok (Some line) - let read_exactly (buf : input) (n : int) : string option IoState.t = + let read_exactly ((buf, trace) : input) (n : int) : string option IoState.t = let data = Eio.Buf_read.take n buf in + let () = trace data in Ok (Some data) - let rec write (buf : output) (lines : string list) : unit IoState.t = + let rec write ((buf, trace) : output) (lines : string list) : unit IoState.t = match lines with | [] -> Ok () | line :: tail -> + let () = trace line in let () = Eio.Buf_write.string buf line in - write buf tail + write (buf, trace) tail end module LspIo = Lsp.Io.Make (IoState) (IoChan) diff --git a/lsp/lib/tlapm_lsp_codec.mli b/lsp/lib/tlapm_lsp_codec.mli index d2bfe6e1..fc169e38 100644 --- a/lsp/lib/tlapm_lsp_codec.mli +++ b/lsp/lib/tlapm_lsp_codec.mli @@ -3,5 +3,9 @@ Here we construct a decoder/encoder for the LSP protocol on top of Eio flows. We use the lsp module from the ocaml-lsp server and configure it to run over Eio. *) -val read : Eio.Buf_read.t -> (Jsonrpc.Packet.t option, exn) result -val write : Eio.Buf_write.t -> Jsonrpc.Packet.t -> (unit, exn) result +type trace_fun = string -> unit +type input_chan = Eio.Buf_read.t * trace_fun +type output_chan = Eio.Buf_write.t * trace_fun + +val read : input_chan -> (Jsonrpc.Packet.t option, exn) result +val write : output_chan -> Jsonrpc.Packet.t -> (unit, exn) result diff --git a/lsp/lib/tlapm_lsp_lib.mli b/lsp/lib/tlapm_lsp_lib.mli index cdda796d..63420190 100644 --- a/lsp/lib/tlapm_lsp_lib.mli +++ b/lsp/lib/tlapm_lsp_lib.mli @@ -2,5 +2,9 @@ module Server : sig type transport = Stdio | Socket of int val run : - transport -> Eio_unix.Stdenv.base -> string Eio.Std.Promise.t -> unit + transport -> + bool -> + Eio_unix.Stdenv.base -> + string Eio.Std.Promise.t -> + unit end diff --git a/lsp/lib/tlapm_lsp_server.ml b/lsp/lib/tlapm_lsp_server.ml index 50ae4e95..2e7a2675 100644 --- a/lsp/lib/tlapm_lsp_server.ml +++ b/lsp/lib/tlapm_lsp_server.ml @@ -3,51 +3,75 @@ let max_size = 50 * 1024 * 1024 type transport = Stdio | Socket of int -let rec lsp_stream_handler buf_r buf_w = +(** Passed to the IO codec to log the traffic, if needed. *) +let trace_fun trace direction = + match (trace, direction) with + | true, `Input -> fun str -> Eio.traceln "[I] %s" str + | true, `Output -> fun str -> Eio.traceln "[O] %s" str + | false, _ -> fun _ -> () + +(** Process an LSP packet stream. *) +let rec lsp_stream_handler input_chan output_chan = let open Tlapm_lsp_codec in let writer out_packet = - match write buf_w out_packet with + let buf_w, _ = output_chan in + match write output_chan out_packet with | Ok () -> Eio.Buf_write.flush buf_w | Error exn -> Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) in - match read buf_r with + match read input_chan with | Ok (Some packet) -> Tlapm_lsp_packets.handle_jsonrpc_packet packet writer; - lsp_stream_handler buf_r buf_w + lsp_stream_handler input_chan output_chan | Ok None -> Eio.traceln "No packet was read." | Error exn -> Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) let err_handler = Eio.traceln "Error handling connection: %a" Fmt.exn -let req_handler flow _addr = - Eio.traceln "Server: got connection from client"; - let buf_r = Eio.Buf_read.of_flow flow ~max_size in - Eio.Buf_write.with_flow flow @@ fun buf_w -> lsp_stream_handler buf_r buf_w - -let switch (net : 'a Eio.Net.ty Eio.Std.r) port stop_promise sw = - Eio.traceln "Switch started"; - let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, port) in - let sock = Eio.Net.listen net ~sw ~reuse_addr:true ~backlog:5 addr in - let stopResult = - Eio.Net.run_server sock req_handler ~on_error:err_handler - ?stop:(Some stop_promise) +(** Configures the IO for the given input/output flows. *) +let flow_handler trace input_flow output_flow = + let buf_r = Eio.Buf_read.of_flow input_flow ~max_size in + let write_fun buf_w = + let input_chan = (buf_r, trace_fun trace `Input) in + let output_chan = (buf_w, trace_fun trace `Output) in + lsp_stream_handler input_chan output_chan in - Eio.traceln "StopResult=%s" stopResult + Eio.Buf_write.with_flow output_flow write_fun -let run_on_stdio env = - let switch_fun _sw = - let buf_r = Eio.Buf_read.of_flow (Eio.Stdenv.stdin env) ~max_size in - Eio.Buf_write.with_flow (Eio.Stdenv.stdout env) (lsp_stream_handler buf_r) - in - Eio.Switch.run switch_fun +(** StdIO specifics. *) +module OnStdio = struct + let run trace env = + let switch_fun _sw = + flow_handler trace (Eio.Stdenv.stdin env) (Eio.Stdenv.stdout env) + in + Eio.Switch.run switch_fun +end + +(** Socket-specifics. *) +module OnSocket = struct + let req_handler trace flow _addr = + Eio.traceln "Server: got connection from client"; + flow_handler trace flow flow + + let switch (net : 'a Eio.Net.ty Eio.Std.r) port trace stop_promise sw = + Eio.traceln "Socket switch started"; + let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, port) in + let sock = Eio.Net.listen net ~sw ~reuse_addr:true ~backlog:5 addr in + let stopResult = + Eio.Net.run_server sock (req_handler trace) ~on_error:err_handler + ?stop:(Some stop_promise) + in + Eio.traceln "StopResult=%s" stopResult -let run_on_socket port env stop_promise = - let net = Eio.Stdenv.net env in - Eio.Switch.run @@ switch net port stop_promise + let run port trace env stop_promise = + let net = Eio.Stdenv.net env in + Eio.Switch.run @@ switch net port trace stop_promise +end -let run transport env stop_promise = +(** Entry point. *) +let run transport trace env stop_promise = match transport with - | Stdio -> run_on_stdio env - | Socket port -> run_on_socket port env stop_promise + | Stdio -> OnStdio.run trace env + | Socket port -> OnSocket.run port trace env stop_promise diff --git a/lsp/lib/tlapm_lsp_server.mli b/lsp/lib/tlapm_lsp_server.mli index f04b35d2..c2ab3b4d 100644 --- a/lsp/lib/tlapm_lsp_server.mli +++ b/lsp/lib/tlapm_lsp_server.mli @@ -6,4 +6,5 @@ This module contains only the generic server-related functions, the tlapm-specifics is moved to tlapm_lsp_packets. *) -val run : transport -> Eio_unix.Stdenv.base -> string Eio.Std.Promise.t -> unit +val run : + transport -> bool -> Eio_unix.Stdenv.base -> string Eio.Std.Promise.t -> unit From 67b1629119d82d480e09c618aec9d0bdc2a7b085 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sat, 23 Sep 2023 02:11:14 +0300 Subject: [PATCH 008/140] Some LSP communication works already. Signed-off-by: Karolis Petrauskas --- lsp/lib/dune | 2 +- lsp/lib/tlapm_lsp_packets.ml | 56 +- lsp/test/tlapm-lsp-test/.eslintrc.json | 24 + lsp/test/tlapm-lsp-test/.gitignore | 3 + .../tlapm-lsp-test/.vscode/extensions.json | 7 + lsp/test/tlapm-lsp-test/.vscode/launch.json | 34 + lsp/test/tlapm-lsp-test/.vscode/settings.json | 11 + lsp/test/tlapm-lsp-test/.vscode/tasks.json | 20 + lsp/test/tlapm-lsp-test/.vscodeignore | 10 + lsp/test/tlapm-lsp-test/CHANGELOG.md | 9 + lsp/test/tlapm-lsp-test/README.md | 71 + lsp/test/tlapm-lsp-test/package-lock.json | 4582 +++++++++++++++++ lsp/test/tlapm-lsp-test/package.json | 47 + lsp/test/tlapm-lsp-test/src/extension.ts | 42 + lsp/test/tlapm-lsp-test/src/test/runTest.ts | 23 + .../src/test/suite/extension.test.ts | 15 + .../tlapm-lsp-test/src/test/suite/index.ts | 40 + lsp/test/tlapm-lsp-test/tsconfig.json | 17 + .../vsc-extension-quickstart.md | 42 + 19 files changed, 5051 insertions(+), 4 deletions(-) create mode 100644 lsp/test/tlapm-lsp-test/.eslintrc.json create mode 100644 lsp/test/tlapm-lsp-test/.gitignore create mode 100644 lsp/test/tlapm-lsp-test/.vscode/extensions.json create mode 100644 lsp/test/tlapm-lsp-test/.vscode/launch.json create mode 100644 lsp/test/tlapm-lsp-test/.vscode/settings.json create mode 100644 lsp/test/tlapm-lsp-test/.vscode/tasks.json create mode 100644 lsp/test/tlapm-lsp-test/.vscodeignore create mode 100644 lsp/test/tlapm-lsp-test/CHANGELOG.md create mode 100644 lsp/test/tlapm-lsp-test/README.md create mode 100644 lsp/test/tlapm-lsp-test/package-lock.json create mode 100644 lsp/test/tlapm-lsp-test/package.json create mode 100644 lsp/test/tlapm-lsp-test/src/extension.ts create mode 100644 lsp/test/tlapm-lsp-test/src/test/runTest.ts create mode 100644 lsp/test/tlapm-lsp-test/src/test/suite/extension.test.ts create mode 100644 lsp/test/tlapm-lsp-test/src/test/suite/index.ts create mode 100644 lsp/test/tlapm-lsp-test/tsconfig.json create mode 100644 lsp/test/tlapm-lsp-test/vsc-extension-quickstart.md diff --git a/lsp/lib/dune b/lsp/lib/dune index 3fba6eaf..858307cd 100644 --- a/lsp/lib/dune +++ b/lsp/lib/dune @@ -1,4 +1,4 @@ (library (name tlapm_lsp_lib) (optional) ; Only build, if eio is available, which is only the case for ocaml > 5. - (libraries tlapm_lib lsp eio_main)) + (libraries tlapm_lib lsp eio_main dune-build-info)) diff --git a/lsp/lib/tlapm_lsp_packets.ml b/lsp/lib/tlapm_lsp_packets.ml index f2a82a3f..24d88ec8 100644 --- a/lsp/lib/tlapm_lsp_packets.ml +++ b/lsp/lib/tlapm_lsp_packets.ml @@ -4,16 +4,66 @@ let handle_jsonrpc_notif jsonrpc_notif _writer = match Lsp.Client_notification.of_jsonrpc jsonrpc_notif with (* TODO: Handle all the cases. *) | Ok Initialized -> () - | Ok (TextDocumentDidOpen _params) -> () + | Ok (TextDocumentDidOpen params) -> + let uri = params.textDocument.uri in + let text = params.textDocument.text in + Eio.traceln "DOCUMENT[OP]: %s => %s" + (Lsp.Types.DocumentUri.to_string uri) + text + | Ok (TextDocumentDidChange params) -> + let uri = params.textDocument.uri in + let changes = params.contentChanges in + let rec trec (items : Lsp.Types.TextDocumentContentChangeEvent.t list) = + match items with + | [] -> () + | doc :: tail -> + let text = doc.text in + Eio.traceln "DOCUMENT[CH]: %s => %s" + (Lsp.Types.DocumentUri.to_string uri) + text; + trec tail + in + trec changes + | Ok (TextDocumentDidClose _params) -> () | Ok (UnknownNotification _params) -> () (* writer packet *) (* // TODO: That's just echo. *) | _ -> () -let handle_jsonrpc_request jsonrpc_req _writer = +(* // TODO: Handle all the cases. *) +let handle_jsonrpc_request (jsonrpc_req : Jsonrpc.Request.t) writer : unit = + let print_ci (params : Lsp.Types.InitializeParams.t) = + match params.clientInfo with + | None -> () + | Some ci -> + let ci_version = match ci.version with None -> "?" | Some v -> v in + Eio.traceln "Client INFO, name=%s, version=%s" ci.name ci_version + in match Lsp.Client_request.of_jsonrpc jsonrpc_req with - | Ok (E (Initialize _params)) -> () (* TODO: Handle all the cases. *) + | Ok (E (Initialize (params : Lsp.Types.InitializeParams.t))) -> + print_ci params; + let open Lsp.Types in + let capabilities = + ServerCapabilities.create + ~textDocumentSync:(`TextDocumentSyncKind TextDocumentSyncKind.Full) () + in + let server_version = + match Build_info.V1.version () with + | None -> "development" + | Some v -> Build_info.V1.Version.to_string v + in + let serverInfo = + InitializeResult.create_serverInfo ~name:"tlapm-lsp" + ~version:server_version () + in + let respInfo = InitializeResult.create ~capabilities ~serverInfo () in + let response = + Jsonrpc.Response.ok jsonrpc_req.id + (InitializeResult.yojson_of_t respInfo) + in + let packet = Jsonrpc.Packet.Response response in + writer packet | _ -> () let handle_jsonrpc_packet (packet : Jsonrpc.Packet.t) writer = diff --git a/lsp/test/tlapm-lsp-test/.eslintrc.json b/lsp/test/tlapm-lsp-test/.eslintrc.json new file mode 100644 index 00000000..f9b22b79 --- /dev/null +++ b/lsp/test/tlapm-lsp-test/.eslintrc.json @@ -0,0 +1,24 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module" + }, + "plugins": [ + "@typescript-eslint" + ], + "rules": { + "@typescript-eslint/naming-convention": "warn", + "@typescript-eslint/semi": "warn", + "curly": "warn", + "eqeqeq": "warn", + "no-throw-literal": "warn", + "semi": "off" + }, + "ignorePatterns": [ + "out", + "dist", + "**/*.d.ts" + ] +} diff --git a/lsp/test/tlapm-lsp-test/.gitignore b/lsp/test/tlapm-lsp-test/.gitignore new file mode 100644 index 00000000..a73617e3 --- /dev/null +++ b/lsp/test/tlapm-lsp-test/.gitignore @@ -0,0 +1,3 @@ +out +node_modules +.vscode-test diff --git a/lsp/test/tlapm-lsp-test/.vscode/extensions.json b/lsp/test/tlapm-lsp-test/.vscode/extensions.json new file mode 100644 index 00000000..3ac9aeb6 --- /dev/null +++ b/lsp/test/tlapm-lsp-test/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "dbaeumer.vscode-eslint" + ] +} diff --git a/lsp/test/tlapm-lsp-test/.vscode/launch.json b/lsp/test/tlapm-lsp-test/.vscode/launch.json new file mode 100644 index 00000000..670d6e66 --- /dev/null +++ b/lsp/test/tlapm-lsp-test/.vscode/launch.json @@ -0,0 +1,34 @@ +// A launch configuration that compiles the extension and then opens it inside a new window +// Use IntelliSense to learn about possible attributes. +// Hover to view descriptions of existing attributes. +// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "outFiles": [ + "${workspaceFolder}/out/**/*.js" + ], + "preLaunchTask": "${defaultBuildTask}" + }, + { + "name": "Extension Tests", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}", + "--extensionTestsPath=${workspaceFolder}/out/test/suite/index" + ], + "outFiles": [ + "${workspaceFolder}/out/test/**/*.js" + ], + "preLaunchTask": "${defaultBuildTask}" + } + ] +} diff --git a/lsp/test/tlapm-lsp-test/.vscode/settings.json b/lsp/test/tlapm-lsp-test/.vscode/settings.json new file mode 100644 index 00000000..30bf8c2d --- /dev/null +++ b/lsp/test/tlapm-lsp-test/.vscode/settings.json @@ -0,0 +1,11 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.exclude": { + "out": false // set this to true to hide the "out" folder with the compiled JS files + }, + "search.exclude": { + "out": true // set this to false to include "out" folder in search results + }, + // Turn off tsc task auto detection since we have the necessary tasks as npm scripts + "typescript.tsc.autoDetect": "off" +} \ No newline at end of file diff --git a/lsp/test/tlapm-lsp-test/.vscode/tasks.json b/lsp/test/tlapm-lsp-test/.vscode/tasks.json new file mode 100644 index 00000000..3b17e53b --- /dev/null +++ b/lsp/test/tlapm-lsp-test/.vscode/tasks.json @@ -0,0 +1,20 @@ +// See https://go.microsoft.com/fwlink/?LinkId=733558 +// for the documentation about the tasks.json format +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "watch", + "problemMatcher": "$tsc-watch", + "isBackground": true, + "presentation": { + "reveal": "never" + }, + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} diff --git a/lsp/test/tlapm-lsp-test/.vscodeignore b/lsp/test/tlapm-lsp-test/.vscodeignore new file mode 100644 index 00000000..38999676 --- /dev/null +++ b/lsp/test/tlapm-lsp-test/.vscodeignore @@ -0,0 +1,10 @@ +.vscode/** +.vscode-test/** +src/** +.gitignore +.yarnrc +vsc-extension-quickstart.md +**/tsconfig.json +**/.eslintrc.json +**/*.map +**/*.ts diff --git a/lsp/test/tlapm-lsp-test/CHANGELOG.md b/lsp/test/tlapm-lsp-test/CHANGELOG.md new file mode 100644 index 00000000..5e47de9d --- /dev/null +++ b/lsp/test/tlapm-lsp-test/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change Log + +All notable changes to the "tlapm-lsp-test" extension will be documented in this file. + +Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file. + +## [Unreleased] + +- Initial release \ No newline at end of file diff --git a/lsp/test/tlapm-lsp-test/README.md b/lsp/test/tlapm-lsp-test/README.md new file mode 100644 index 00000000..6223a8c9 --- /dev/null +++ b/lsp/test/tlapm-lsp-test/README.md @@ -0,0 +1,71 @@ +# tlapm-lsp-test README + +This is the README for your extension "tlapm-lsp-test". After writing up a brief description, we recommend including the following sections. + +## Features + +Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file. + +For example if there is an image subfolder under your extension project workspace: + +\!\[feature X\]\(images/feature-x.png\) + +> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow. + +## Requirements + +If you have any requirements or dependencies, add a section describing those and how to install and configure them. + +## Extension Settings + +Include if your extension adds any VS Code settings through the `contributes.configuration` extension point. + +For example: + +This extension contributes the following settings: + +* `myExtension.enable`: Enable/disable this extension. +* `myExtension.thing`: Set to `blah` to do something. + +## Known Issues + +Calling out known issues can help limit users opening duplicate issues against your extension. + +## Release Notes + +Users appreciate release notes as you update your extension. + +### 1.0.0 + +Initial release of ... + +### 1.0.1 + +Fixed issue #. + +### 1.1.0 + +Added features X, Y, and Z. + +--- + +## Following extension guidelines + +Ensure that you've read through the extensions guidelines and follow the best practices for creating your extension. + +* [Extension Guidelines](https://code.visualstudio.com/api/references/extension-guidelines) + +## Working with Markdown + +You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts: + +* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux). +* Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux). +* Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets. + +## For more information + +* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) +* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) + +**Enjoy!** diff --git a/lsp/test/tlapm-lsp-test/package-lock.json b/lsp/test/tlapm-lsp-test/package-lock.json new file mode 100644 index 00000000..199e284a --- /dev/null +++ b/lsp/test/tlapm-lsp-test/package-lock.json @@ -0,0 +1,4582 @@ +{ + "name": "tlapm-lsp-test", + "version": "0.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "tlapm-lsp-test", + "version": "0.0.1", + "dependencies": { + "vscode-languageclient": "^9.0.0" + }, + "devDependencies": { + "@types/mocha": "^10.0.1", + "@types/node": "16.x", + "@types/vscode": "^1.82.0", + "@typescript-eslint/eslint-plugin": "^6.4.1", + "@typescript-eslint/parser": "^6.4.1", + "@vscode/test-electron": "^2.3.4", + "eslint": "^8.47.0", + "glob": "^10.3.3", + "mocha": "^10.2.0", + "typescript": "^5.1.6" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz", + "integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", + "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", + "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", + "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "dev": true + }, + "node_modules/@types/node": { + "version": "16.18.53", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.53.tgz", + "integrity": "sha512-vVmHeo4tpF8zsknALU90Hh24VueYdu45ZlXzYWFbom61YR4avJqTFDC3QlWzjuTdAv6/3xHaxiO9NrtVZXrkmw==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.2.tgz", + "integrity": "sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==", + "dev": true + }, + "node_modules/@types/vscode": { + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.82.0.tgz", + "integrity": "sha512-VSHV+VnpF8DEm8LNrn8OJ8VuUNcBzN3tMvKrNpbhhfuVjFm82+6v44AbDhLvVFgCzn6vs94EJNTp7w8S6+Q1Rw==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz", + "integrity": "sha512-ooaHxlmSgZTM6CHYAFRlifqh1OAr3PAQEwi7lhYhaegbnXrnh7CDcHmc3+ihhbQC7H0i4JF0psI5ehzkF6Yl6Q==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/type-utils": "6.7.2", + "@typescript-eslint/utils": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz", + "integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", + "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.2.tgz", + "integrity": "sha512-36F4fOYIROYRl0qj95dYKx6kybddLtsbmPIYNK0OBeXv2j9L5nZ17j9jmfy+bIDHKQgn2EZX+cofsqi8NPATBQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/utils": "6.7.2", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", + "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", + "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz", + "integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", + "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.7.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vscode/test-electron": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.4.tgz", + "integrity": "sha512-eWzIqXMhvlcoXfEFNWrVu/yYT5w6De+WZXR/bafUQhAp8+8GkQo95Oe14phwiRUPv8L+geAKl/QM2+PoT3YW3g==", + "dev": true, + "dependencies": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "jszip": "^3.10.1", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", + "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.49.0", + "@humanwhocodes/config-array": "^0.11.11", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", + "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "dev": true, + "dependencies": { + "flatted": "^3.2.7", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "10.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.5.tgz", + "integrity": "sha512-bYUpUD7XDEHI4Q2O5a7PXGvyw4deKR70kHiDxzQbe925wbZknhOzUt2xBgTkYL6RBcVeXYuD9iNYeqoWbBZQnA==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "13.22.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz", + "integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.3.tgz", + "integrity": "sha512-R2bUw+kVZFS/h1AZqBKrSgDmdmjApzgY0AlCPumopFiAlbUxE2gf+SCuBzQ0cP5hHmUmFYF5yw55T97Th5Kstg==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/keyv": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", + "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mocha": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "dev": true, + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.0.tgz", + "integrity": "sha512-EXP4vhSlEj0DtyxrcWVp5aiFrY0WczKSnKSyrMmSbU7qhASPhM+pfcUzY/z8TQCfOhKvq39fidbdTbq9LnBi7g==", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.4" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageclient/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/vscode-languageclient/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.4.tgz", + "integrity": "sha512-IpaHLPft+UBWf4dOIH15YEgydTbXGz52EMU2h16SfFpYu/yOQt3pY14049mtpJu+4CBHn+hq7S67e7O0AwpRqQ==", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.4" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.4.tgz", + "integrity": "sha512-9YXi5pA3XF2V+NUQg6g+lulNS0ncRCKASYdK3Cs7kiH9sVFXWq27prjkC/B8M/xJLRPPRSPCHVMuBTgRNFh2sQ==" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz", + "integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + } + }, + "@eslint/js": { + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", + "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", + "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", + "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "dev": true + }, + "@types/mocha": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", + "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "dev": true + }, + "@types/node": { + "version": "16.18.53", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.53.tgz", + "integrity": "sha512-vVmHeo4tpF8zsknALU90Hh24VueYdu45ZlXzYWFbom61YR4avJqTFDC3QlWzjuTdAv6/3xHaxiO9NrtVZXrkmw==", + "dev": true + }, + "@types/semver": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.2.tgz", + "integrity": "sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw==", + "dev": true + }, + "@types/vscode": { + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.82.0.tgz", + "integrity": "sha512-VSHV+VnpF8DEm8LNrn8OJ8VuUNcBzN3tMvKrNpbhhfuVjFm82+6v44AbDhLvVFgCzn6vs94EJNTp7w8S6+Q1Rw==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz", + "integrity": "sha512-ooaHxlmSgZTM6CHYAFRlifqh1OAr3PAQEwi7lhYhaegbnXrnh7CDcHmc3+ihhbQC7H0i4JF0psI5ehzkF6Yl6Q==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/type-utils": "6.7.2", + "@typescript-eslint/utils": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/parser": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.2.tgz", + "integrity": "sha512-KA3E4ox0ws+SPyxQf9iSI25R6b4Ne78ORhNHeVKrPQnoYsb9UhieoiRoJgrzgEeKGOXhcY1i8YtOeCHHTDa6Fw==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.2.tgz", + "integrity": "sha512-bgi6plgyZjEqapr7u2mhxGR6E8WCzKNUFWNh6fkpVe9+yzRZeYtDTbsIBzKbcxI+r1qVWt6VIoMSNZ4r2A+6Yw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2" + } + }, + "@typescript-eslint/type-utils": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.2.tgz", + "integrity": "sha512-36F4fOYIROYRl0qj95dYKx6kybddLtsbmPIYNK0OBeXv2j9L5nZ17j9jmfy+bIDHKQgn2EZX+cofsqi8NPATBQ==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "6.7.2", + "@typescript-eslint/utils": "6.7.2", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/types": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.2.tgz", + "integrity": "sha512-flJYwMYgnUNDAN9/GAI3l8+wTmvTYdv64fcH8aoJK76Y+1FCZ08RtI5zDerM/FYT5DMkAc+19E4aLmd5KqdFyg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.2.tgz", + "integrity": "sha512-kiJKVMLkoSciGyFU0TOY0fRxnp9qq1AzVOHNeN1+B9erKFCJ4Z8WdjAkKQPP+b1pWStGFqezMLltxO+308dJTQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/visitor-keys": "6.7.2", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.2.tgz", + "integrity": "sha512-ZCcBJug/TS6fXRTsoTkgnsvyWSiXwMNiPzBUani7hDidBdj1779qwM1FIAmpH4lvlOZNF3EScsxxuGifjpLSWQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.7.2", + "@typescript-eslint/types": "6.7.2", + "@typescript-eslint/typescript-estree": "6.7.2", + "semver": "^7.5.4" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.2.tgz", + "integrity": "sha512-uVw9VIMFBUTz8rIeaUT3fFe8xIUx8r4ywAdlQv1ifH+6acn/XF8Y6rwJ7XNmkNMDrTW+7+vxFFPIF40nJCVsMQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.7.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "@vscode/test-electron": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.4.tgz", + "integrity": "sha512-eWzIqXMhvlcoXfEFNWrVu/yYT5w6De+WZXR/bafUQhAp8+8GkQo95Oe14phwiRUPv8L+geAKl/QM2+PoT3YW3g==", + "dev": true, + "requires": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "jszip": "^3.10.1", + "semver": "^7.5.2" + } + }, + "acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.49.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", + "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.49.0", + "@humanwhocodes/config-array": "^0.11.11", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + } + }, + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "flat-cache": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", + "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "dev": true, + "requires": { + "flatted": "^3.2.7", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "10.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.5.tgz", + "integrity": "sha512-bYUpUD7XDEHI4Q2O5a7PXGvyw4deKR70kHiDxzQbe925wbZknhOzUt2xBgTkYL6RBcVeXYuD9iNYeqoWbBZQnA==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.22.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz", + "integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "jackspeak": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.3.tgz", + "integrity": "sha512-R2bUw+kVZFS/h1AZqBKrSgDmdmjApzgY0AlCPumopFiAlbUxE2gf+SCuBzQ0cP5hHmUmFYF5yw55T97Th5Kstg==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "keyv": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "requires": { + "immediate": "~3.0.5" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "lru-cache": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minipass": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", + "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", + "dev": true + }, + "mocha": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", + "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", + "dev": true, + "requires": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "minimatch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + } + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "ts-api-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", + "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "dev": true, + "requires": {} + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typescript": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", + "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==" + }, + "vscode-languageclient": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.0.tgz", + "integrity": "sha512-EXP4vhSlEj0DtyxrcWVp5aiFrY0WczKSnKSyrMmSbU7qhASPhM+pfcUzY/z8TQCfOhKvq39fidbdTbq9LnBi7g==", + "requires": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.4" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "vscode-languageserver-protocol": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.4.tgz", + "integrity": "sha512-IpaHLPft+UBWf4dOIH15YEgydTbXGz52EMU2h16SfFpYu/yOQt3pY14049mtpJu+4CBHn+hq7S67e7O0AwpRqQ==", + "requires": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.4" + } + }, + "vscode-languageserver-types": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.4.tgz", + "integrity": "sha512-9YXi5pA3XF2V+NUQg6g+lulNS0ncRCKASYdK3Cs7kiH9sVFXWq27prjkC/B8M/xJLRPPRSPCHVMuBTgRNFh2sQ==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + }, + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/lsp/test/tlapm-lsp-test/package.json b/lsp/test/tlapm-lsp-test/package.json new file mode 100644 index 00000000..9a798592 --- /dev/null +++ b/lsp/test/tlapm-lsp-test/package.json @@ -0,0 +1,47 @@ +{ + "name": "tlapm-lsp-test", + "displayName": "tlapm-lsp-test", + "description": "Only for testing TLAPM LSP", + "version": "0.0.1", + "engines": { + "vscode": "^1.82.0" + }, + "categories": [ + "Other" + ], + "activationEvents": [ + "onLanguage:tlaplus" + ], + "main": "./out/extension.js", + "contributes": { + "commands": [ + { + "command": "tlapm-lsp-test.helloWorld", + "title": "Hello World" + } + ] + }, + "scripts": { + "vscode:prepublish": "npm run compile", + "compile": "tsc -p ./", + "watch": "tsc -watch -p ./", + "pretest": "npm run compile && npm run lint", + "lint": "eslint src --ext ts", + "test": "node ./out/test/runTest.js" + }, + "dependencies": { + "vscode-languageclient": "^9.0.0" + }, + "devDependencies": { + "@types/vscode": "^1.82.0", + "@types/mocha": "^10.0.1", + "@types/node": "16.x", + "@typescript-eslint/eslint-plugin": "^6.4.1", + "@typescript-eslint/parser": "^6.4.1", + "eslint": "^8.47.0", + "glob": "^10.3.3", + "mocha": "^10.2.0", + "typescript": "^5.1.6", + "@vscode/test-electron": "^2.3.4" + } +} diff --git a/lsp/test/tlapm-lsp-test/src/extension.ts b/lsp/test/tlapm-lsp-test/src/extension.ts new file mode 100644 index 00000000..70d3a704 --- /dev/null +++ b/lsp/test/tlapm-lsp-test/src/extension.ts @@ -0,0 +1,42 @@ +import * as path from 'path'; +import * as vscode from 'vscode'; +import { Executable, LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node'; + +let client: LanguageClient; + +export function activate(context: vscode.ExtensionContext) { + console.log('Congratulations, your extension "tlapm-lsp-test" is now active!'); + context.subscriptions.push(vscode.commands.registerCommand('tlapm-lsp-test.helloWorld', () => { + vscode.window.showInformationMessage('Key there from tlapm-lsp-test!'); + })); + + const serverPath = '/home/karolis/CODE/pub/tlapm-lsp/_build/default/lsp/bin/tlapm_lsp.exe'; + let serverOptions: Executable = { + command: serverPath + ' --trace 2>/tmp/lsp-log-tlapm', + transport: TransportKind.stdio, + args: [], + // args: [ + // '--stdio', + // // '--trace', + // ], + options: { shell: true } // TODO: Remove. + }; + let clientOptions: LanguageClientOptions = { + documentSelector: [{ scheme: 'file', language: 'tlaplus' }], + }; + client = new LanguageClient( + 'tlapm-lsp-example', + 'TLAPM LSP Example', + serverOptions, + clientOptions, + true, + ); + client.start(); +} + +export function deactivate() { + if (!client) { + return undefined; + } + return client.stop(); +} diff --git a/lsp/test/tlapm-lsp-test/src/test/runTest.ts b/lsp/test/tlapm-lsp-test/src/test/runTest.ts new file mode 100644 index 00000000..93a4441d --- /dev/null +++ b/lsp/test/tlapm-lsp-test/src/test/runTest.ts @@ -0,0 +1,23 @@ +import * as path from 'path'; + +import { runTests } from '@vscode/test-electron'; + +async function main() { + try { + // The folder containing the Extension Manifest package.json + // Passed to `--extensionDevelopmentPath` + const extensionDevelopmentPath = path.resolve(__dirname, '../../'); + + // The path to test runner + // Passed to --extensionTestsPath + const extensionTestsPath = path.resolve(__dirname, './suite/index'); + + // Download VS Code, unzip it and run the integration test + await runTests({ extensionDevelopmentPath, extensionTestsPath }); + } catch (err) { + console.error('Failed to run tests', err); + process.exit(1); + } +} + +main(); diff --git a/lsp/test/tlapm-lsp-test/src/test/suite/extension.test.ts b/lsp/test/tlapm-lsp-test/src/test/suite/extension.test.ts new file mode 100644 index 00000000..4ca0ab41 --- /dev/null +++ b/lsp/test/tlapm-lsp-test/src/test/suite/extension.test.ts @@ -0,0 +1,15 @@ +import * as assert from 'assert'; + +// You can import and use all API from the 'vscode' module +// as well as import your extension to test it +import * as vscode from 'vscode'; +// import * as myExtension from '../../extension'; + +suite('Extension Test Suite', () => { + vscode.window.showInformationMessage('Start all tests.'); + + test('Sample test', () => { + assert.strictEqual(-1, [1, 2, 3].indexOf(5)); + assert.strictEqual(-1, [1, 2, 3].indexOf(0)); + }); +}); diff --git a/lsp/test/tlapm-lsp-test/src/test/suite/index.ts b/lsp/test/tlapm-lsp-test/src/test/suite/index.ts new file mode 100644 index 00000000..bcf91732 --- /dev/null +++ b/lsp/test/tlapm-lsp-test/src/test/suite/index.ts @@ -0,0 +1,40 @@ +import * as path from 'path'; +import * as Mocha from 'mocha'; +import * as glob from 'glob'; + +export function run(): Promise { + // Create the mocha test + const mocha = new Mocha({ + ui: 'tdd', + color: true + }); + + const testsRoot = path.resolve(__dirname, '..'); + + return new Promise((c, e) => { + const testFiles = new glob.Glob("**/**.test.js", { cwd: testsRoot }); + const testFileStream = testFiles.stream(); + + testFileStream.on("data", (file) => { + mocha.addFile(path.resolve(testsRoot, file)); + }); + testFileStream.on("error", (err) => { + e(err); + }); + testFileStream.on("end", () => { + try { + // Run the mocha test + mocha.run(failures => { + if (failures > 0) { + e(new Error(`${failures} tests failed.`)); + } else { + c(); + } + }); + } catch (err) { + console.error(err); + e(err); + } + }); + }); +} diff --git a/lsp/test/tlapm-lsp-test/tsconfig.json b/lsp/test/tlapm-lsp-test/tsconfig.json new file mode 100644 index 00000000..315af7ec --- /dev/null +++ b/lsp/test/tlapm-lsp-test/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "ES2020", + "outDir": "out", + "lib": [ + "ES2020" + ], + "sourceMap": true, + "rootDir": "src", + "strict": true /* enable all strict type-checking options */ + /* Additional Checks */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + } +} diff --git a/lsp/test/tlapm-lsp-test/vsc-extension-quickstart.md b/lsp/test/tlapm-lsp-test/vsc-extension-quickstart.md new file mode 100644 index 00000000..04a57fc6 --- /dev/null +++ b/lsp/test/tlapm-lsp-test/vsc-extension-quickstart.md @@ -0,0 +1,42 @@ +# Welcome to your VS Code Extension + +## What's in the folder + +* This folder contains all of the files necessary for your extension. +* `package.json` - this is the manifest file in which you declare your extension and command. + * The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin. +* `src/extension.ts` - this is the main file where you will provide the implementation of your command. + * The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`. + * We pass the function containing the implementation of the command as the second parameter to `registerCommand`. + +## Get up and running straight away + +* Press `F5` to open a new window with your extension loaded. +* Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`. +* Set breakpoints in your code inside `src/extension.ts` to debug your extension. +* Find output from your extension in the debug console. + +## Make changes + +* You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`. +* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. + +## Explore the API + +* You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`. + +## Run tests + +* Open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Extension Tests`. +* Press `F5` to run the tests in a new window with your extension loaded. +* See the output of the test result in the debug console. +* Make changes to `src/test/suite/extension.test.ts` or create new test files inside the `test/suite` folder. + * The provided test runner will only consider files matching the name pattern `**.test.ts`. + * You can create folders inside the `test` folder to structure your tests any way you want. + +## Go further + +* [Follow UX guidelines](https://code.visualstudio.com/api/ux-guidelines/overview) to create extensions that seamlessly integrate with VS Code's native interface and patterns. + * Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension). + * [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VS Code extension marketplace. + * Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration). From 6b905626af827076a96c1c3389948285302cea10 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sat, 23 Sep 2023 14:32:42 +0300 Subject: [PATCH 009/140] Option to redirect stderr to a file. Signed-off-by: Karolis Petrauskas --- lsp/bin/tlapm_lsp.ml | 53 +++++++++++++++++++++++++++++----------- lsp/lib/tlapm_lsp_doc.ml | 3 +++ 2 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 lsp/lib/tlapm_lsp_doc.ml diff --git a/lsp/bin/tlapm_lsp.ml b/lsp/bin/tlapm_lsp.ml index 695d0cf9..b05d8efa 100644 --- a/lsp/bin/tlapm_lsp.ml +++ b/lsp/bin/tlapm_lsp.ml @@ -7,16 +7,36 @@ let transport_of_args tr_stdio tr_socket = | false, Some port -> Ok (Socket port) | _ -> Error "Exactly one of transports has to be specified." -let run transport trace = - let main env = - let stop_promise, stop_resolver = Eio.Std.Promise.create () in - let handle_signal (_signum : int) = - Eio.Std.Promise.resolve stop_resolver "Stopping on SigINT" +let run transport log_to log_io = + let main_fun (env : Eio_unix.Stdenv.base) = + let main_switch _sw = + let stop_promise, stop_resolver = Eio.Std.Promise.create () in + let handle_signal (_signum : int) = + Eio.Std.Promise.resolve stop_resolver "Stopping on SigINT" + in + Sys.set_signal Sys.sigint (Signal_handle handle_signal); + Tlapm_lsp_lib.Server.run transport log_io env stop_promise in - Sys.set_signal Sys.sigint (Signal_handle handle_signal); - Tlapm_lsp_lib.Server.run transport trace env stop_promise + let with_log_stderr () = Eio.Switch.run main_switch in + let with_log_file log_file = + let with_log_chan log_chan = + let my_traceln = + { Eio.Debug.traceln = (fun ?__POS__:_ fmt -> Fmt.epr (fmt ^^ "@.")) } + in + let debug = Eio.Stdenv.debug env in + Eio.Fiber.with_binding debug#traceln my_traceln (fun _ -> + Format.pp_set_formatter_out_channel Format.err_formatter log_chan; + Eio.Switch.run main_switch) + in + Out_channel.with_open_gen + [ Open_append; Open_wronly; Open_creat ] + 0o644 log_file with_log_chan + in + match log_to with + | None -> with_log_stderr () + | Some log_file -> with_log_file log_file in - Eio_main.run main + Eio_main.run main_fun module Cli = struct let arg_stdio = @@ -29,18 +49,23 @@ module Cli = struct let info = Arg.info [ "socket"; "port" ] ~docv:"NUM" ~doc in Arg.value (Arg.opt (Arg.some Arg.int) None info) - let arg_trace = - let doc = "Trace protocol's IO to the StdErr." in - let info = Arg.info [ "trace" ] ~docv:"BOOL" ~doc in + let arg_log_to = + let doc = "Log all to the specified file instead of StdErr." in + let info = Arg.info [ "log-to" ] ~docv:"FILE" ~doc in + Arg.value (Arg.opt (Arg.some Arg.string) None info) + + let arg_log_io = + let doc = "Log protocol's IO." in + let info = Arg.info [ "log-io" ] ~docv:"BOOL" ~doc in Arg.value (Arg.flag info) let term () = - let combine tr_stdio tr_socket trace = + let combine tr_stdio tr_socket log_to log_io = match transport_of_args tr_stdio tr_socket with - | Ok transport -> `Ok (run transport trace) + | Ok transport -> `Ok (run transport log_to log_io) | Error err -> `Error (false, err) in - Term.(const combine $ arg_stdio $ arg_socket $ arg_trace) + Term.(const combine $ arg_stdio $ arg_socket $ arg_log_to $ arg_log_io) let name = "tlapm_lsp" let doc = "LSP interface for TLAPS." diff --git a/lsp/lib/tlapm_lsp_doc.ml b/lsp/lib/tlapm_lsp_doc.ml new file mode 100644 index 00000000..12dc6514 --- /dev/null +++ b/lsp/lib/tlapm_lsp_doc.ml @@ -0,0 +1,3 @@ +module Doc = struct + (* // TODO: Implement. *) +end From 637f37d5baba0e2b9389f110830c231b36b05baa Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sat, 23 Sep 2023 14:58:03 +0300 Subject: [PATCH 010/140] Use logging to a file rom the ts code. Signed-off-by: Karolis Petrauskas --- lsp/test/tlapm-lsp-test/src/extension.ts | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/lsp/test/tlapm-lsp-test/src/extension.ts b/lsp/test/tlapm-lsp-test/src/extension.ts index 70d3a704..b34b85f7 100644 --- a/lsp/test/tlapm-lsp-test/src/extension.ts +++ b/lsp/test/tlapm-lsp-test/src/extension.ts @@ -1,4 +1,3 @@ -import * as path from 'path'; import * as vscode from 'vscode'; import { Executable, LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node'; @@ -10,18 +9,14 @@ export function activate(context: vscode.ExtensionContext) { vscode.window.showInformationMessage('Key there from tlapm-lsp-test!'); })); - const serverPath = '/home/karolis/CODE/pub/tlapm-lsp/_build/default/lsp/bin/tlapm_lsp.exe'; - let serverOptions: Executable = { - command: serverPath + ' --trace 2>/tmp/lsp-log-tlapm', + const serverPath = context.asAbsolutePath('../../../_build/default/lsp/bin/tlapm_lsp.exe'); + const logPath = context.asAbsolutePath('tlapm_lsp.log'); + const serverOptions: Executable = { + command: serverPath, transport: TransportKind.stdio, - args: [], - // args: [ - // '--stdio', - // // '--trace', - // ], - options: { shell: true } // TODO: Remove. + args: ['--log-io', '--log-to=' + logPath], }; - let clientOptions: LanguageClientOptions = { + const clientOptions: LanguageClientOptions = { documentSelector: [{ scheme: 'file', language: 'tlaplus' }], }; client = new LanguageClient( From 687f5a49b7f33c6cff93e6772f60ea7b925365fa Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sat, 23 Sep 2023 23:48:38 +0300 Subject: [PATCH 011/140] Docs store. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_doc.ml | 3 --- lsp/lib/tlapm_lsp_docs.ml | 25 +++++++++++++++++++++++++ lsp/lib/tlapm_lsp_docs.mli | 19 +++++++++++++++++++ 3 files changed, 44 insertions(+), 3 deletions(-) delete mode 100644 lsp/lib/tlapm_lsp_doc.ml create mode 100644 lsp/lib/tlapm_lsp_docs.ml create mode 100644 lsp/lib/tlapm_lsp_docs.mli diff --git a/lsp/lib/tlapm_lsp_doc.ml b/lsp/lib/tlapm_lsp_doc.ml deleted file mode 100644 index 12dc6514..00000000 --- a/lsp/lib/tlapm_lsp_doc.ml +++ /dev/null @@ -1,3 +0,0 @@ -module Doc = struct - (* // TODO: Implement. *) -end diff --git a/lsp/lib/tlapm_lsp_docs.ml b/lsp/lib/tlapm_lsp_docs.ml new file mode 100644 index 00000000..dbdf3c69 --- /dev/null +++ b/lsp/lib/tlapm_lsp_docs.ml @@ -0,0 +1,25 @@ +module Docs = Map.Make (Lsp.Types.DocumentUri) + +type tv = { text : string; version : int; in_use : bool } +type td = { versions : tv list } +type tk = Lsp.Types.DocumentUri.t +type t = td Docs.t + +let empty = Docs.empty + +let add docs uri vsn txt = + let rev = { text = txt; version = vsn; in_use = false } in + let drop_unused = List.filter (fun dd -> dd.in_use) in + let upd = function + | None -> Some { versions = [ rev ] } + | Some d -> Some { versions = rev :: drop_unused d.versions } + in + Docs.update uri upd docs + +let rem docs uri = Docs.remove uri docs + +let get_opt docs uri = + match Docs.find_opt uri docs with + | None -> None + | Some { versions = [] } -> None + | Some { versions = v :: _ } -> Some (v.text, v.version) diff --git a/lsp/lib/tlapm_lsp_docs.mli b/lsp/lib/tlapm_lsp_docs.mli new file mode 100644 index 00000000..07d429ba --- /dev/null +++ b/lsp/lib/tlapm_lsp_docs.mli @@ -0,0 +1,19 @@ +(** Here we maintain a list of documents and their revisions. *) + +type t +(** A document store type. *) + +type tk = Lsp.Types.DocumentUri.t +(** Key type to identify documents. *) + +val empty : t +(** Create new empty document store. *) + +val add : t -> tk -> int -> string -> t +(** Either add document or its revision. Forgets all previous unused revisions. *) + +val rem : t -> tk -> t +(** Remove a document with all its revisions. *) + +val get_opt : t -> tk -> (string * int) option +(** Lookup document's last revision. *) From a6ddb4fd4eb26b98cd1c270333f6b61eb6c7cd66 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sat, 23 Sep 2023 23:48:51 +0300 Subject: [PATCH 012/140] Some experiments on test cases. Signed-off-by: Karolis Petrauskas --- lsp/test/tlapm-lsp-test/src/extension.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lsp/test/tlapm-lsp-test/src/extension.ts b/lsp/test/tlapm-lsp-test/src/extension.ts index b34b85f7..a3e71564 100644 --- a/lsp/test/tlapm-lsp-test/src/extension.ts +++ b/lsp/test/tlapm-lsp-test/src/extension.ts @@ -9,6 +9,8 @@ export function activate(context: vscode.ExtensionContext) { vscode.window.showInformationMessage('Key there from tlapm-lsp-test!'); })); + pocTestCases(); + const serverPath = context.asAbsolutePath('../../../_build/default/lsp/bin/tlapm_lsp.exe'); const logPath = context.asAbsolutePath('tlapm_lsp.log'); const serverOptions: Executable = { @@ -35,3 +37,13 @@ export function deactivate() { } return client.stop(); } + +function pocTestCases() { + const poController = vscode.tests.createTestController( + 'tlapm_proof_obligations', + 'TLA Proof Obligations' + ); + const poExampleItem = poController.createTestItem("some", "My Proof Obligation", undefined); + poExampleItem.range = new vscode.Range(new vscode.Position(1, 3), new vscode.Position(1, 7)); + poController.items.add(poExampleItem); +} From ff2d50b269d80528c88783bfb383f939ea8a93e9 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sun, 24 Sep 2023 10:52:17 +0300 Subject: [PATCH 013/140] Handle some LSP packets. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_packets.ml | 152 +++++++++++++++++++++------------- lsp/lib/tlapm_lsp_packets.mli | 5 +- lsp/lib/tlapm_lsp_server.ml | 8 +- 3 files changed, 101 insertions(+), 64 deletions(-) diff --git a/lsp/lib/tlapm_lsp_packets.ml b/lsp/lib/tlapm_lsp_packets.ml index 24d88ec8..4ae88b28 100644 --- a/lsp/lib/tlapm_lsp_packets.ml +++ b/lsp/lib/tlapm_lsp_packets.ml @@ -1,76 +1,110 @@ -(* // TODO: curl -vvv -X POST -H 'Content-Type: application/vscode-jsonrpc; charset=utf-8' -d '{"jsonrpc": "2.0", "id": 1, "method": "textDocument/completion", "params": { }}' http://localhost:8080/ *) - -let handle_jsonrpc_notif jsonrpc_notif _writer = +(** Dispatch notification packets. *) +let handle_jsonrpc_notif jsonrpc_notif _writer docs = + let open Lsp.Types in match Lsp.Client_notification.of_jsonrpc jsonrpc_notif with - (* TODO: Handle all the cases. *) - | Ok Initialized -> () + | Ok Initialized -> docs | Ok (TextDocumentDidOpen params) -> let uri = params.textDocument.uri in + let vsn = params.textDocument.version in let text = params.textDocument.text in - Eio.traceln "DOCUMENT[OP]: %s => %s" - (Lsp.Types.DocumentUri.to_string uri) - text - | Ok (TextDocumentDidChange params) -> + Eio.traceln "DOCUMENT[OP]: %s => %s" (DocumentUri.to_string uri) text; + Tlapm_lsp_docs.add docs uri vsn text + | Ok (TextDocumentDidChange params) -> ( let uri = params.textDocument.uri in - let changes = params.contentChanges in - let rec trec (items : Lsp.Types.TextDocumentContentChangeEvent.t list) = - match items with - | [] -> () - | doc :: tail -> - let text = doc.text in - Eio.traceln "DOCUMENT[CH]: %s => %s" - (Lsp.Types.DocumentUri.to_string uri) - text; - trec tail - in - trec changes - | Ok (TextDocumentDidClose _params) -> () + let vsn = params.textDocument.version in + match params.contentChanges with + | [ { text; range = None; rangeLength = None } ] -> + Eio.traceln "DOCUMENT[CH]: %s => %s" (DocumentUri.to_string uri) text; + Tlapm_lsp_docs.add docs uri vsn text + | _ -> failwith "incremental changes not supported") + | Ok (TextDocumentDidClose params) -> + let uri = params.textDocument.uri in + Tlapm_lsp_docs.rem docs uri + | Ok (DidSaveTextDocument params) -> + let uri = params.textDocument.uri in + Eio.traceln "DOCUMENT[SAVE]: %s" (DocumentUri.to_string uri); + docs | Ok (UnknownNotification _params) -> - () - (* writer packet *) - (* // TODO: That's just echo. *) - | _ -> () + Eio.traceln "Unknown notification: %s" jsonrpc_notif.method_; + docs + | Ok _unsupported -> + Eio.traceln "Unsupported notification: %s" jsonrpc_notif.method_; + docs + | Error error -> + Eio.traceln "Failed to decode notification: %s - %s" jsonrpc_notif.method_ + error; + docs -(* // TODO: Handle all the cases. *) -let handle_jsonrpc_request (jsonrpc_req : Jsonrpc.Request.t) writer : unit = - let print_ci (params : Lsp.Types.InitializeParams.t) = +let handle_jsonrpc_req_initialize (jsonrpc_req : Jsonrpc.Request.t) params + writer docs = + let open Lsp.Types in + let print_ci (params : InitializeParams.t) = match params.clientInfo with | None -> () | Some ci -> let ci_version = match ci.version with None -> "?" | Some v -> v in Eio.traceln "Client INFO, name=%s, version=%s" ci.name ci_version in + print_ci params; + let capabilities = + ServerCapabilities.create + ~textDocumentSync:(`TextDocumentSyncKind TextDocumentSyncKind.Full) () + in + let server_version = + match Build_info.V1.version () with + | None -> "development" + | Some v -> Build_info.V1.Version.to_string v + in + let serverInfo = + InitializeResult.create_serverInfo ~name:"tlapm-lsp" ~version:server_version + () + in + let respInfo = InitializeResult.create ~capabilities ~serverInfo () in + let response = + Jsonrpc.Response.ok jsonrpc_req.id (InitializeResult.yojson_of_t respInfo) + in + let packet = Jsonrpc.Packet.Response response in + let () = writer packet in + docs + +let handle_jsonrpc_req_unknown (jsonrpc_req : Jsonrpc.Request.t) writer docs = + Eio.traceln "Received unknown JsonRPC request, method=%s" jsonrpc_req.method_; + let open Jsonrpc in + let error = + Response.Error.make ~code:Response.Error.Code.MethodNotFound + ~message:"method not supported" () + in + let response = Response.error jsonrpc_req.id error in + let packet = Jsonrpc.Packet.Response response in + let () = writer packet in + docs + +(** Dispatch request packets. *) +let handle_jsonrpc_request (jsonrpc_req : Jsonrpc.Request.t) writer docs = + let open Lsp.Types in match Lsp.Client_request.of_jsonrpc jsonrpc_req with - | Ok (E (Initialize (params : Lsp.Types.InitializeParams.t))) -> - print_ci params; - let open Lsp.Types in - let capabilities = - ServerCapabilities.create - ~textDocumentSync:(`TextDocumentSyncKind TextDocumentSyncKind.Full) () - in - let server_version = - match Build_info.V1.version () with - | None -> "development" - | Some v -> Build_info.V1.Version.to_string v - in - let serverInfo = - InitializeResult.create_serverInfo ~name:"tlapm-lsp" - ~version:server_version () - in - let respInfo = InitializeResult.create ~capabilities ~serverInfo () in - let response = - Jsonrpc.Response.ok jsonrpc_req.id - (InitializeResult.yojson_of_t respInfo) - in - let packet = Jsonrpc.Packet.Response response in - writer packet - | _ -> () + | Ok (E (Initialize (params : InitializeParams.t))) -> + handle_jsonrpc_req_initialize jsonrpc_req params writer docs + | _ -> handle_jsonrpc_req_unknown jsonrpc_req writer docs + +(* Dispatch client responses to our requests. *) +let handle_jsonrpc_response _jsonrpc_resp docs = docs -let handle_jsonrpc_packet (packet : Jsonrpc.Packet.t) writer = +let handle_jsonrpc_packet (packet : Jsonrpc.Packet.t) writer docs = Eio.traceln "Got LSP Packet"; match packet with - | Notification jsonrpc_notif -> handle_jsonrpc_notif jsonrpc_notif writer - | Request jsonrpc_req -> handle_jsonrpc_request jsonrpc_req writer - | Response _ -> () (* // TODO: Handle it. *) - | Batch_call _ -> () (* // TODO: Handle it. *) - | Batch_response _ -> () + | Notification notif -> handle_jsonrpc_notif notif writer docs + | Request req -> handle_jsonrpc_request req writer docs + | Response resp -> handle_jsonrpc_response resp docs + | Batch_call sub_packets -> + let fold_fun docs_acc sub_pkg = + match sub_pkg with + | `Notification notif -> handle_jsonrpc_notif notif writer docs_acc + | `Request req -> handle_jsonrpc_request req writer docs_acc + in + List.fold_left fold_fun docs sub_packets + | Batch_response sub_responses -> + let fold_fun docs_acc sub_resp = + handle_jsonrpc_response sub_resp docs_acc + in + List.fold_left fold_fun docs sub_responses diff --git a/lsp/lib/tlapm_lsp_packets.mli b/lsp/lib/tlapm_lsp_packets.mli index 3ff1dd2d..56d03ec7 100644 --- a/lsp/lib/tlapm_lsp_packets.mli +++ b/lsp/lib/tlapm_lsp_packets.mli @@ -1,4 +1,7 @@ (** Here we have all the TLAPM specific LSP action handlers. *) val handle_jsonrpc_packet : - Jsonrpc.Packet.t -> (Jsonrpc.Packet.t -> unit) -> unit + Jsonrpc.Packet.t -> + (Jsonrpc.Packet.t -> unit) -> + Tlapm_lsp_docs.t -> + Tlapm_lsp_docs.t diff --git a/lsp/lib/tlapm_lsp_server.ml b/lsp/lib/tlapm_lsp_server.ml index 2e7a2675..c5485054 100644 --- a/lsp/lib/tlapm_lsp_server.ml +++ b/lsp/lib/tlapm_lsp_server.ml @@ -11,7 +11,7 @@ let trace_fun trace direction = | false, _ -> fun _ -> () (** Process an LSP packet stream. *) -let rec lsp_stream_handler input_chan output_chan = +let rec lsp_stream_handler input_chan output_chan docs = let open Tlapm_lsp_codec in let writer out_packet = let buf_w, _ = output_chan in @@ -22,8 +22,8 @@ let rec lsp_stream_handler input_chan output_chan = in match read input_chan with | Ok (Some packet) -> - Tlapm_lsp_packets.handle_jsonrpc_packet packet writer; - lsp_stream_handler input_chan output_chan + let docs' = Tlapm_lsp_packets.handle_jsonrpc_packet packet writer docs in + lsp_stream_handler input_chan output_chan docs' | Ok None -> Eio.traceln "No packet was read." | Error exn -> Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) @@ -36,7 +36,7 @@ let flow_handler trace input_flow output_flow = let write_fun buf_w = let input_chan = (buf_r, trace_fun trace `Input) in let output_chan = (buf_w, trace_fun trace `Output) in - lsp_stream_handler input_chan output_chan + lsp_stream_handler input_chan output_chan Tlapm_lsp_docs.empty in Eio.Buf_write.with_flow output_flow write_fun From cc08f1daced1a06c091ad59e2c4f7fdc51457e42 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sun, 24 Sep 2023 11:22:57 +0300 Subject: [PATCH 014/140] Attempt to reuse the original traceln function. Signed-off-by: Karolis Petrauskas --- lsp/bin/tlapm_lsp.ml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lsp/bin/tlapm_lsp.ml b/lsp/bin/tlapm_lsp.ml index b05d8efa..b64e1b33 100644 --- a/lsp/bin/tlapm_lsp.ml +++ b/lsp/bin/tlapm_lsp.ml @@ -22,6 +22,16 @@ let run transport log_to log_io = let with_log_chan log_chan = let my_traceln = { Eio.Debug.traceln = (fun ?__POS__:_ fmt -> Fmt.epr (fmt ^^ "@.")) } + (* TODO: Try to reuse the original traceln function. Types don't match in the following. + let x = Eio.traceln in + { + Eio.Debug.traceln = + (fun ?__POS__:pos fmt -> + let f = Fmt.epr fmt in + match pos with + | None -> x (Fmt.epr fmt) + | Some p -> x ?__POS__:p f); + } *) in let debug = Eio.Stdenv.debug env in Eio.Fiber.with_binding debug#traceln my_traceln (fun _ -> From fd022eee5f5ce09ad095127f0429cac3194f1865 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sun, 24 Sep 2023 12:10:13 +0300 Subject: [PATCH 015/140] Track connection state. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_packets.ml | 87 ++++++++++++++++++++++------------- lsp/lib/tlapm_lsp_packets.mli | 4 +- lsp/lib/tlapm_lsp_server.ml | 10 ++-- lsp/lib/tlapm_lsp_state.ml | 29 ++++++++++++ lsp/lib/tlapm_lsp_state.mli | 12 +++++ 5 files changed, 103 insertions(+), 39 deletions(-) create mode 100644 lsp/lib/tlapm_lsp_state.ml create mode 100644 lsp/lib/tlapm_lsp_state.mli diff --git a/lsp/lib/tlapm_lsp_packets.ml b/lsp/lib/tlapm_lsp_packets.ml index 4ae88b28..c65cb7b8 100644 --- a/lsp/lib/tlapm_lsp_packets.ml +++ b/lsp/lib/tlapm_lsp_packets.ml @@ -1,49 +1,66 @@ (** Dispatch notification packets. *) -let handle_jsonrpc_notif jsonrpc_notif _writer docs = +let handle_jsonrpc_notif jsonrpc_notif _writer state = let open Lsp.Types in match Lsp.Client_notification.of_jsonrpc jsonrpc_notif with - | Ok Initialized -> docs + | Ok Initialized -> + Eio.traceln "CONN: Initialized"; + Tlapm_lsp_state.ready state | Ok (TextDocumentDidOpen params) -> let uri = params.textDocument.uri in let vsn = params.textDocument.version in let text = params.textDocument.text in - Eio.traceln "DOCUMENT[OP]: %s => %s" (DocumentUri.to_string uri) text; - Tlapm_lsp_docs.add docs uri vsn text + Eio.traceln "DOCUMENT[Open]: %s => %s" (DocumentUri.to_string uri) text; + Tlapm_lsp_state.handle_if_ready_silent state (fun docs -> + Tlapm_lsp_docs.add docs uri vsn text) | Ok (TextDocumentDidChange params) -> ( let uri = params.textDocument.uri in let vsn = params.textDocument.version in match params.contentChanges with | [ { text; range = None; rangeLength = None } ] -> - Eio.traceln "DOCUMENT[CH]: %s => %s" (DocumentUri.to_string uri) text; - Tlapm_lsp_docs.add docs uri vsn text + Eio.traceln "DOCUMENT[Change]: %s => %s" + (DocumentUri.to_string uri) + text; + Tlapm_lsp_state.handle_if_ready_silent state (fun docs -> + Tlapm_lsp_docs.add docs uri vsn text) | _ -> failwith "incremental changes not supported") | Ok (TextDocumentDidClose params) -> let uri = params.textDocument.uri in - Tlapm_lsp_docs.rem docs uri + Tlapm_lsp_state.handle_if_ready_silent state (fun docs -> + Tlapm_lsp_docs.rem docs uri) | Ok (DidSaveTextDocument params) -> let uri = params.textDocument.uri in - Eio.traceln "DOCUMENT[SAVE]: %s" (DocumentUri.to_string uri); - docs + Eio.traceln "DOCUMENT[Save]: %s" (DocumentUri.to_string uri); + state + | Ok (SetTrace params) -> + let level = + match params.value with + | Compact -> "Compact" + | Off -> "Off" + | Messages -> "Messages" + | Verbose -> "Verbose" + in + Eio.traceln "CONN: Set trace: %s -- ignored" level; + state | Ok (UnknownNotification _params) -> Eio.traceln "Unknown notification: %s" jsonrpc_notif.method_; - docs + state | Ok _unsupported -> Eio.traceln "Unsupported notification: %s" jsonrpc_notif.method_; - docs + state | Error error -> Eio.traceln "Failed to decode notification: %s - %s" jsonrpc_notif.method_ error; - docs + state let handle_jsonrpc_req_initialize (jsonrpc_req : Jsonrpc.Request.t) params - writer docs = + writer state = let open Lsp.Types in let print_ci (params : InitializeParams.t) = match params.clientInfo with | None -> () | Some ci -> let ci_version = match ci.version with None -> "?" | Some v -> v in - Eio.traceln "Client INFO, name=%s, version=%s" ci.name ci_version + Eio.traceln "CONN: Client INFO, name=%s, version=%s" ci.name ci_version in print_ci params; let capabilities = @@ -65,9 +82,13 @@ let handle_jsonrpc_req_initialize (jsonrpc_req : Jsonrpc.Request.t) params in let packet = Jsonrpc.Packet.Response response in let () = writer packet in - docs + state + +let handle_jsonrpc_req_shutdown (_jsonrpc_req : Jsonrpc.Request.t) state = + Eio.traceln "CONN: Shutdown"; + Tlapm_lsp_state.shutdown state -let handle_jsonrpc_req_unknown (jsonrpc_req : Jsonrpc.Request.t) writer docs = +let handle_jsonrpc_req_unknown (jsonrpc_req : Jsonrpc.Request.t) writer state = Eio.traceln "Received unknown JsonRPC request, method=%s" jsonrpc_req.method_; let open Jsonrpc in let error = @@ -77,34 +98,34 @@ let handle_jsonrpc_req_unknown (jsonrpc_req : Jsonrpc.Request.t) writer docs = let response = Response.error jsonrpc_req.id error in let packet = Jsonrpc.Packet.Response response in let () = writer packet in - docs + state (** Dispatch request packets. *) -let handle_jsonrpc_request (jsonrpc_req : Jsonrpc.Request.t) writer docs = +let handle_jsonrpc_request (jsonrpc_req : Jsonrpc.Request.t) writer state = let open Lsp.Types in match Lsp.Client_request.of_jsonrpc jsonrpc_req with | Ok (E (Initialize (params : InitializeParams.t))) -> - handle_jsonrpc_req_initialize jsonrpc_req params writer docs - | _ -> handle_jsonrpc_req_unknown jsonrpc_req writer docs + handle_jsonrpc_req_initialize jsonrpc_req params writer state + | Ok (E Shutdown) -> handle_jsonrpc_req_shutdown jsonrpc_req state + | _ -> handle_jsonrpc_req_unknown jsonrpc_req writer state (* Dispatch client responses to our requests. *) -let handle_jsonrpc_response _jsonrpc_resp docs = docs +let handle_jsonrpc_response _jsonrpc_resp state = state -let handle_jsonrpc_packet (packet : Jsonrpc.Packet.t) writer docs = - Eio.traceln "Got LSP Packet"; +let handle_jsonrpc_packet (packet : Jsonrpc.Packet.t) writer state = match packet with - | Notification notif -> handle_jsonrpc_notif notif writer docs - | Request req -> handle_jsonrpc_request req writer docs - | Response resp -> handle_jsonrpc_response resp docs + | Notification notif -> handle_jsonrpc_notif notif writer state + | Request req -> handle_jsonrpc_request req writer state + | Response resp -> handle_jsonrpc_response resp state | Batch_call sub_packets -> - let fold_fun docs_acc sub_pkg = + let fold_fun state_acc sub_pkg = match sub_pkg with - | `Notification notif -> handle_jsonrpc_notif notif writer docs_acc - | `Request req -> handle_jsonrpc_request req writer docs_acc + | `Notification notif -> handle_jsonrpc_notif notif writer state_acc + | `Request req -> handle_jsonrpc_request req writer state_acc in - List.fold_left fold_fun docs sub_packets + List.fold_left fold_fun state sub_packets | Batch_response sub_responses -> - let fold_fun docs_acc sub_resp = - handle_jsonrpc_response sub_resp docs_acc + let fold_fun state_acc sub_resp = + handle_jsonrpc_response sub_resp state_acc in - List.fold_left fold_fun docs sub_responses + List.fold_left fold_fun state sub_responses diff --git a/lsp/lib/tlapm_lsp_packets.mli b/lsp/lib/tlapm_lsp_packets.mli index 56d03ec7..1a0a76bf 100644 --- a/lsp/lib/tlapm_lsp_packets.mli +++ b/lsp/lib/tlapm_lsp_packets.mli @@ -3,5 +3,5 @@ val handle_jsonrpc_packet : Jsonrpc.Packet.t -> (Jsonrpc.Packet.t -> unit) -> - Tlapm_lsp_docs.t -> - Tlapm_lsp_docs.t + Tlapm_lsp_state.t -> + Tlapm_lsp_state.t diff --git a/lsp/lib/tlapm_lsp_server.ml b/lsp/lib/tlapm_lsp_server.ml index c5485054..af97641e 100644 --- a/lsp/lib/tlapm_lsp_server.ml +++ b/lsp/lib/tlapm_lsp_server.ml @@ -11,7 +11,7 @@ let trace_fun trace direction = | false, _ -> fun _ -> () (** Process an LSP packet stream. *) -let rec lsp_stream_handler input_chan output_chan docs = +let rec lsp_stream_handler input_chan output_chan state = let open Tlapm_lsp_codec in let writer out_packet = let buf_w, _ = output_chan in @@ -22,8 +22,10 @@ let rec lsp_stream_handler input_chan output_chan docs = in match read input_chan with | Ok (Some packet) -> - let docs' = Tlapm_lsp_packets.handle_jsonrpc_packet packet writer docs in - lsp_stream_handler input_chan output_chan docs' + let state' = + Tlapm_lsp_packets.handle_jsonrpc_packet packet writer state + in + lsp_stream_handler input_chan output_chan state' | Ok None -> Eio.traceln "No packet was read." | Error exn -> Eio.traceln "IO Error reading packet: %s" (Printexc.to_string exn) @@ -36,7 +38,7 @@ let flow_handler trace input_flow output_flow = let write_fun buf_w = let input_chan = (buf_r, trace_fun trace `Input) in let output_chan = (buf_w, trace_fun trace `Output) in - lsp_stream_handler input_chan output_chan Tlapm_lsp_docs.empty + lsp_stream_handler input_chan output_chan Tlapm_lsp_state.empty in Eio.Buf_write.with_flow output_flow write_fun diff --git a/lsp/lib/tlapm_lsp_state.ml b/lsp/lib/tlapm_lsp_state.ml new file mode 100644 index 00000000..505ec9fc --- /dev/null +++ b/lsp/lib/tlapm_lsp_state.ml @@ -0,0 +1,29 @@ +type mode = Initializing | Ready | Shutdown +type t = { mode : mode; docs : Tlapm_lsp_docs.t } + +let empty = { mode = Initializing; docs = Tlapm_lsp_docs.empty } + +let ready st = + match st.mode with + | Initializing -> { st with mode = Ready } + | Ready -> st + | Shutdown -> st + +let shutdown st = + match st.mode with + | Initializing -> { st with mode = Shutdown } + | Ready -> { st with mode = Shutdown } + | Shutdown -> st + +let handle_if_ready st f = + match st.mode with + | Initializing -> Error "initializing" + | Ready -> Ok { st with docs = f st.docs } + | Shutdown -> Error "going to shutdown" + +let handle_if_ready_silent st f = + match handle_if_ready st f with + | Ok st' -> st' + | Error err -> + Eio.traceln "Ignoring request: %s" err; + st diff --git a/lsp/lib/tlapm_lsp_state.mli b/lsp/lib/tlapm_lsp_state.mli new file mode 100644 index 00000000..ddf9cead --- /dev/null +++ b/lsp/lib/tlapm_lsp_state.mli @@ -0,0 +1,12 @@ +(** State of a single session/connection with the LSP client. *) + +type t + +val empty : t +val ready : t -> t +val shutdown : t -> t + +val handle_if_ready : + t -> (Tlapm_lsp_docs.t -> Tlapm_lsp_docs.t) -> (t, string) result + +val handle_if_ready_silent : t -> (Tlapm_lsp_docs.t -> Tlapm_lsp_docs.t) -> t From 79eadbab61f815740cf4cc935a783c0fa7122fcf Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sun, 24 Sep 2023 13:21:57 +0300 Subject: [PATCH 016/140] Support prover-info cmd. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_packets.ml | 35 ++++++++++++++++++++---- lsp/test/tlapm-lsp-test/package.json | 11 ++++++-- lsp/test/tlapm-lsp-test/src/extension.ts | 3 -- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/lsp/lib/tlapm_lsp_packets.ml b/lsp/lib/tlapm_lsp_packets.ml index c65cb7b8..f5f1c34a 100644 --- a/lsp/lib/tlapm_lsp_packets.ml +++ b/lsp/lib/tlapm_lsp_packets.ml @@ -63,9 +63,15 @@ let handle_jsonrpc_req_initialize (jsonrpc_req : Jsonrpc.Request.t) params Eio.traceln "CONN: Client INFO, name=%s, version=%s" ci.name ci_version in print_ci params; + let supported_commands = [ "tlapm-lsp-test.prover-info" ] in let capabilities = ServerCapabilities.create - ~textDocumentSync:(`TextDocumentSyncKind TextDocumentSyncKind.Full) () + ~textDocumentSync:(`TextDocumentSyncKind TextDocumentSyncKind.Full) + ~executeCommandProvider: + (* TODO: workDoneProgress:false *) + (ExecuteCommandOptions.create ~commands:supported_commands + ~workDoneProgress:false ()) + () in let server_version = match Build_info.V1.version () with @@ -88,26 +94,45 @@ let handle_jsonrpc_req_shutdown (_jsonrpc_req : Jsonrpc.Request.t) state = Eio.traceln "CONN: Shutdown"; Tlapm_lsp_state.shutdown state -let handle_jsonrpc_req_unknown (jsonrpc_req : Jsonrpc.Request.t) writer state = +let handle_jsonrpc_req_unknown (jsonrpc_req : Jsonrpc.Request.t) message writer + state = Eio.traceln "Received unknown JsonRPC request, method=%s" jsonrpc_req.method_; let open Jsonrpc in let error = - Response.Error.make ~code:Response.Error.Code.MethodNotFound - ~message:"method not supported" () + Response.Error.make ~code:Response.Error.Code.MethodNotFound ~message () in let response = Response.error jsonrpc_req.id error in let packet = Jsonrpc.Packet.Response response in let () = writer packet in state +(* {"jsonrpc":"2.0","id":1,"method":"workspace/executeCommand","params":{"command":"tlapm-lsp-test.prover-info","arguments":[]}} *) +let handle_jsonrpc_req_exec_cmd (jsonrpc_req : Jsonrpc.Request.t) + (params : Lsp.Types.ExecuteCommandParams.t) writer state = + let open Jsonrpc in + match params.command with + | "tlapm-lsp-test.prover-info" -> + Eio.traceln "COMMAND: prover-info"; + let response = Response.ok jsonrpc_req.id (`String "OK") in + let packet = Jsonrpc.Packet.Response response in + let () = writer packet in + state + | unknown -> + handle_jsonrpc_req_unknown jsonrpc_req + (Printf.sprintf "command unknown: %s" unknown) + writer state + (** Dispatch request packets. *) let handle_jsonrpc_request (jsonrpc_req : Jsonrpc.Request.t) writer state = let open Lsp.Types in match Lsp.Client_request.of_jsonrpc jsonrpc_req with | Ok (E (Initialize (params : InitializeParams.t))) -> handle_jsonrpc_req_initialize jsonrpc_req params writer state + | Ok (E (ExecuteCommand params)) -> + handle_jsonrpc_req_exec_cmd jsonrpc_req params writer state | Ok (E Shutdown) -> handle_jsonrpc_req_shutdown jsonrpc_req state - | _ -> handle_jsonrpc_req_unknown jsonrpc_req writer state + | _ -> + handle_jsonrpc_req_unknown jsonrpc_req "method not supported" writer state (* Dispatch client responses to our requests. *) let handle_jsonrpc_response _jsonrpc_resp state = state diff --git a/lsp/test/tlapm-lsp-test/package.json b/lsp/test/tlapm-lsp-test/package.json index 9a798592..1474f1cf 100644 --- a/lsp/test/tlapm-lsp-test/package.json +++ b/lsp/test/tlapm-lsp-test/package.json @@ -14,10 +14,17 @@ ], "main": "./out/extension.js", "contributes": { + "keybindings":[ + { + "command": "tlapm-lsp-test.prover-info", + "key": "ctrl+g ctrl+g" + } + ], "commands": [ { - "command": "tlapm-lsp-test.helloWorld", - "title": "Hello World" + "command": "tlapm-lsp-test.prover-info", + "title": "TLAPM: Prover info", + "when": "editorLangId == tlaplus" } ] }, diff --git a/lsp/test/tlapm-lsp-test/src/extension.ts b/lsp/test/tlapm-lsp-test/src/extension.ts index a3e71564..7b36af48 100644 --- a/lsp/test/tlapm-lsp-test/src/extension.ts +++ b/lsp/test/tlapm-lsp-test/src/extension.ts @@ -5,9 +5,6 @@ let client: LanguageClient; export function activate(context: vscode.ExtensionContext) { console.log('Congratulations, your extension "tlapm-lsp-test" is now active!'); - context.subscriptions.push(vscode.commands.registerCommand('tlapm-lsp-test.helloWorld', () => { - vscode.window.showInformationMessage('Key there from tlapm-lsp-test!'); - })); pocTestCases(); From d6c7131cf5f5a07203f042d2636081b25fc12a12 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sun, 24 Sep 2023 18:51:52 +0300 Subject: [PATCH 017/140] Cleanup. Signed-off-by: Karolis Petrauskas --- lsp/README.md | 1 - lsp/test/tlapm-lsp-test/README.md | 83 +++++-------------------------- 2 files changed, 12 insertions(+), 72 deletions(-) diff --git a/lsp/README.md b/lsp/README.md index 360781cb..33446894 100644 --- a/lsp/README.md +++ b/lsp/README.md @@ -4,7 +4,6 @@ The `tlapm_lsp` works as an adapter between the `tlapm` and code editors, e.g., It is responsible for: - Parsing the document structure to locate features related to proofs, e.g.: - proof obligation by cursor position, possibly collecting all the subtree of obligations. - - TODO: Folding of proofs. - Running the `tlapm` on specific obligations and reporting the results. - TODO: Proof re-numbering. - TODO: Proof decomposition. diff --git a/lsp/test/tlapm-lsp-test/README.md b/lsp/test/tlapm-lsp-test/README.md index 6223a8c9..42a7820a 100644 --- a/lsp/test/tlapm-lsp-test/README.md +++ b/lsp/test/tlapm-lsp-test/README.md @@ -1,71 +1,12 @@ -# tlapm-lsp-test README - -This is the README for your extension "tlapm-lsp-test". After writing up a brief description, we recommend including the following sections. - -## Features - -Describe specific features of your extension including screenshots of your extension in action. Image paths are relative to this README file. - -For example if there is an image subfolder under your extension project workspace: - -\!\[feature X\]\(images/feature-x.png\) - -> Tip: Many popular extensions utilize animations. This is an excellent way to show off your extension! We recommend short, focused animations that are easy to follow. - -## Requirements - -If you have any requirements or dependencies, add a section describing those and how to install and configure them. - -## Extension Settings - -Include if your extension adds any VS Code settings through the `contributes.configuration` extension point. - -For example: - -This extension contributes the following settings: - -* `myExtension.enable`: Enable/disable this extension. -* `myExtension.thing`: Set to `blah` to do something. - -## Known Issues - -Calling out known issues can help limit users opening duplicate issues against your extension. - -## Release Notes - -Users appreciate release notes as you update your extension. - -### 1.0.0 - -Initial release of ... - -### 1.0.1 - -Fixed issue #. - -### 1.1.0 - -Added features X, Y, and Z. - ---- - -## Following extension guidelines - -Ensure that you've read through the extensions guidelines and follow the best practices for creating your extension. - -* [Extension Guidelines](https://code.visualstudio.com/api/references/extension-guidelines) - -## Working with Markdown - -You can author your README using Visual Studio Code. Here are some useful editor keyboard shortcuts: - -* Split the editor (`Cmd+\` on macOS or `Ctrl+\` on Windows and Linux). -* Toggle preview (`Shift+Cmd+V` on macOS or `Shift+Ctrl+V` on Windows and Linux). -* Press `Ctrl+Space` (Windows, Linux, macOS) to see a list of Markdown snippets. - -## For more information - -* [Visual Studio Code's Markdown Support](http://code.visualstudio.com/docs/languages/markdown) -* [Markdown Syntax Reference](https://help.github.com/articles/markdown-basics/) - -**Enjoy!** +# Test TLAPM plugin + +It is here only to test some `tlapm_lsp` functions. +The real plugin should be part of the TLA+ vscode extension. + +To use this plugin: + - Assuming `lsp/test/tlapm-lsp-test` as the current directory. + - Build the backend with `make -C ../../../` + - Open `.` in the VSCode, e.g. `code .` + - Press `F5` (Run -> Run and debug), + - New window has this plugin launched. + - Backend log is in the file `./tlapm_lsp.log`. From bbbc308806f559540bd7f21edf871eedd792f09a Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sun, 24 Sep 2023 18:51:59 +0300 Subject: [PATCH 018/140] Cleanup. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_packets.ml | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/lsp/lib/tlapm_lsp_packets.ml b/lsp/lib/tlapm_lsp_packets.ml index f5f1c34a..3de82efa 100644 --- a/lsp/lib/tlapm_lsp_packets.ml +++ b/lsp/lib/tlapm_lsp_packets.ml @@ -1,3 +1,18 @@ +(** Helper to send responses to requests. *) +let reply_ok (jsonrpc_req : Jsonrpc.Request.t) writer payload = + let open Jsonrpc in + let response = Response.ok jsonrpc_req.id payload in + let packet = Packet.Response response in + writer packet + +(** Helper to send responses to requests. *) +let reply_error (jsonrpc_req : Jsonrpc.Request.t) writer code message = + let open Jsonrpc in + let error = Response.Error.make ~code ~message () in + let response = Response.error jsonrpc_req.id error in + let packet = Jsonrpc.Packet.Response response in + writer packet + (** Dispatch notification packets. *) let handle_jsonrpc_notif jsonrpc_notif _writer state = let open Lsp.Types in @@ -83,11 +98,7 @@ let handle_jsonrpc_req_initialize (jsonrpc_req : Jsonrpc.Request.t) params () in let respInfo = InitializeResult.create ~capabilities ~serverInfo () in - let response = - Jsonrpc.Response.ok jsonrpc_req.id (InitializeResult.yojson_of_t respInfo) - in - let packet = Jsonrpc.Packet.Response response in - let () = writer packet in + reply_ok jsonrpc_req writer (InitializeResult.yojson_of_t respInfo); state let handle_jsonrpc_req_shutdown (_jsonrpc_req : Jsonrpc.Request.t) state = @@ -97,25 +108,17 @@ let handle_jsonrpc_req_shutdown (_jsonrpc_req : Jsonrpc.Request.t) state = let handle_jsonrpc_req_unknown (jsonrpc_req : Jsonrpc.Request.t) message writer state = Eio.traceln "Received unknown JsonRPC request, method=%s" jsonrpc_req.method_; - let open Jsonrpc in - let error = - Response.Error.make ~code:Response.Error.Code.MethodNotFound ~message () - in - let response = Response.error jsonrpc_req.id error in - let packet = Jsonrpc.Packet.Response response in - let () = writer packet in + let open Jsonrpc.Response.Error in + reply_error jsonrpc_req writer Code.MethodNotFound message; state (* {"jsonrpc":"2.0","id":1,"method":"workspace/executeCommand","params":{"command":"tlapm-lsp-test.prover-info","arguments":[]}} *) let handle_jsonrpc_req_exec_cmd (jsonrpc_req : Jsonrpc.Request.t) (params : Lsp.Types.ExecuteCommandParams.t) writer state = - let open Jsonrpc in match params.command with | "tlapm-lsp-test.prover-info" -> Eio.traceln "COMMAND: prover-info"; - let response = Response.ok jsonrpc_req.id (`String "OK") in - let packet = Jsonrpc.Packet.Response response in - let () = writer packet in + reply_ok jsonrpc_req writer (`String "OK"); state | unknown -> handle_jsonrpc_req_unknown jsonrpc_req From 31d69e11753f1b93de74009fa7711bb7d92c909f Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sun, 24 Sep 2023 21:05:02 +0300 Subject: [PATCH 019/140] Playing with more LSP command types. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_packets.ml | 104 ++++++++++++++++++++++++++++++++--- 1 file changed, 97 insertions(+), 7 deletions(-) diff --git a/lsp/lib/tlapm_lsp_packets.ml b/lsp/lib/tlapm_lsp_packets.ml index 3de82efa..9105ab92 100644 --- a/lsp/lib/tlapm_lsp_packets.ml +++ b/lsp/lib/tlapm_lsp_packets.ml @@ -14,7 +14,7 @@ let reply_error (jsonrpc_req : Jsonrpc.Request.t) writer code message = writer packet (** Dispatch notification packets. *) -let handle_jsonrpc_notif jsonrpc_notif _writer state = +let handle_jsonrpc_notif jsonrpc_notif writer state = let open Lsp.Types in match Lsp.Client_notification.of_jsonrpc jsonrpc_notif with | Ok Initialized -> @@ -25,8 +25,30 @@ let handle_jsonrpc_notif jsonrpc_notif _writer state = let vsn = params.textDocument.version in let text = params.textDocument.text in Eio.traceln "DOCUMENT[Open]: %s => %s" (DocumentUri.to_string uri) text; - Tlapm_lsp_state.handle_if_ready_silent state (fun docs -> - Tlapm_lsp_docs.add docs uri vsn text) + let send_diags () = + let some = + Diagnostic.create ~message:"Hey from prover!" + ~range: + (Range.create + ~start:(Position.create ~line:1 ~character:3) + ~end_:(Position.create ~line:1 ~character:7)) + () + in + let dpar = + PublishDiagnosticsParams.create ~diagnostics:[ some ] ~uri + ~version:vsn () + in + let diag = Lsp.Server_notification.PublishDiagnostics dpar in + let dpkg = + Jsonrpc.Packet.Notification (Lsp.Server_notification.to_jsonrpc diag) + in + writer dpkg + in + let with_docs docs = + send_diags (); + Tlapm_lsp_docs.add docs uri vsn text + in + Tlapm_lsp_state.handle_if_ready_silent state with_docs | Ok (TextDocumentDidChange params) -> ( let uri = params.textDocument.uri in let vsn = params.textDocument.version in @@ -78,14 +100,26 @@ let handle_jsonrpc_req_initialize (jsonrpc_req : Jsonrpc.Request.t) params Eio.traceln "CONN: Client INFO, name=%s, version=%s" ci.name ci_version in print_ci params; - let supported_commands = [ "tlapm-lsp-test.prover-info" ] in + let supported_commands = + [ "tlapm-lsp-test.prover-info"; "tlapm-lsp-test.prove-step" ] + in let capabilities = ServerCapabilities.create ~textDocumentSync:(`TextDocumentSyncKind TextDocumentSyncKind.Full) ~executeCommandProvider: - (* TODO: workDoneProgress:false *) (ExecuteCommandOptions.create ~commands:supported_commands ~workDoneProgress:false ()) + ~diagnosticProvider: + (`DiagnosticOptions + (DiagnosticOptions.create ~identifier:"TLAPM" + ~interFileDependencies:false ~workspaceDiagnostics:false + ~workDoneProgress:false ())) + ~codeActionProvider: + (`CodeActionOptions + (CodeActionOptions.create ~resolveProvider:true + ~workDoneProgress:false + ~codeActionKinds:[ CodeActionKind.Other "proof-state" ] + ())) () in let server_version = @@ -107,7 +141,8 @@ let handle_jsonrpc_req_shutdown (_jsonrpc_req : Jsonrpc.Request.t) state = let handle_jsonrpc_req_unknown (jsonrpc_req : Jsonrpc.Request.t) message writer state = - Eio.traceln "Received unknown JsonRPC request, method=%s" jsonrpc_req.method_; + Eio.traceln "Received unknown JsonRPC request, method=%s, error=%s" + jsonrpc_req.method_ message; let open Jsonrpc.Response.Error in reply_error jsonrpc_req writer Code.MethodNotFound message; state @@ -120,11 +155,51 @@ let handle_jsonrpc_req_exec_cmd (jsonrpc_req : Jsonrpc.Request.t) Eio.traceln "COMMAND: prover-info"; reply_ok jsonrpc_req writer (`String "OK"); state + | "tlapm-lsp-test.prove-step" -> + (* TODO: Args are passed from the codeAction. *) + Eio.traceln "COMMAND: prove-step"; + reply_ok jsonrpc_req writer (`String "OK"); + state | unknown -> handle_jsonrpc_req_unknown jsonrpc_req (Printf.sprintf "command unknown: %s" unknown) writer state +(** +Provide code actions for a document. + - Code actions can be used for proof decomposition, probably. +*) +let handle_jsonrpc_req_code_action (jsonrpc_req : Jsonrpc.Request.t) + (_params : Lsp.Types.CodeActionParams.t) writer state = + let open Lsp.Types in + let someActionDiag = + Diagnostic.create ~message:"Hey from prover as an action!" + ~range: + (Range.create + ~start:(Position.create ~line:2 ~character:13) + ~end_:(Position.create ~line:2 ~character:17)) + () + in + let someAction = + Lsp.Types.CodeAction.create ~title:"Prover code action" + ~diagnostics:[ someActionDiag ] + ~command: + (Command.create ~command:"tlapm-lsp-test.prove-step" + ~title:"Prove it as an action!" + ~arguments:[ `String "important_arg" ] + ()) + () + in + let acts = Some [ `CodeAction someAction ] in + reply_ok jsonrpc_req writer (Lsp.Types.CodeActionResult.yojson_of_t acts); + state + +let handle_jsonrpc_req_code_action_resolve (jsonrpc_req : Jsonrpc.Request.t) + (_params : Lsp.Types.CodeAction.t) writer state = + (* TODO: Actually resolve the code actions. *) + reply_ok jsonrpc_req writer (`String "OK"); + state + (** Dispatch request packets. *) let handle_jsonrpc_request (jsonrpc_req : Jsonrpc.Request.t) writer state = let open Lsp.Types in @@ -133,9 +208,24 @@ let handle_jsonrpc_request (jsonrpc_req : Jsonrpc.Request.t) writer state = handle_jsonrpc_req_initialize jsonrpc_req params writer state | Ok (E (ExecuteCommand params)) -> handle_jsonrpc_req_exec_cmd jsonrpc_req params writer state + | Ok (E (CodeAction params)) -> + handle_jsonrpc_req_code_action jsonrpc_req params writer state + | Ok (E (CodeActionResolve params)) -> + handle_jsonrpc_req_code_action_resolve jsonrpc_req params writer state | Ok (E Shutdown) -> handle_jsonrpc_req_shutdown jsonrpc_req state - | _ -> + | Ok (E (UnknownRequest unknown)) -> ( + match unknown.meth with + | "textDocument/diagnostic" -> + (* TODO: Handle the diagnostic pull. *) + state + | _ -> + handle_jsonrpc_req_unknown jsonrpc_req "unknown method not supported" + writer state) + | Ok (E _unsupported) -> handle_jsonrpc_req_unknown jsonrpc_req "method not supported" writer state + | Error reason -> + let err_msg = Printf.sprintf "cannot decode method: %s" reason in + handle_jsonrpc_req_unknown jsonrpc_req err_msg writer state (* Dispatch client responses to our requests. *) let handle_jsonrpc_response _jsonrpc_resp state = state From ac444b2fabdb463d4bb788197340797509320194 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sun, 24 Sep 2023 21:48:32 +0300 Subject: [PATCH 020/140] Notes. Signed-off-by: Karolis Petrauskas --- lsp/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lsp/README.md b/lsp/README.md index 33446894..53c00754 100644 --- a/lsp/README.md +++ b/lsp/README.md @@ -11,3 +11,8 @@ It is responsible for: The test folder contains a VSCode extension / LSP client. It is meant only for testing, the real integration should be done in the TLA+ VSCode extension. + +See: + - Dafny plugin. It shows all the obligations as testcases. + + From a54d399bf039efd17206b983f54b1ad14bc624af Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sun, 24 Sep 2023 23:24:45 +0300 Subject: [PATCH 021/140] Prove-step now contains the cursor in the doc. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_packets.ml | 6 +++--- lsp/test/tlapm-lsp-test/package.json | 7 ++++++- lsp/test/tlapm-lsp-test/src/extension.ts | 14 +++++++++++++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lsp/lib/tlapm_lsp_packets.ml b/lsp/lib/tlapm_lsp_packets.ml index 9105ab92..d3752107 100644 --- a/lsp/lib/tlapm_lsp_packets.ml +++ b/lsp/lib/tlapm_lsp_packets.ml @@ -101,7 +101,7 @@ let handle_jsonrpc_req_initialize (jsonrpc_req : Jsonrpc.Request.t) params in print_ci params; let supported_commands = - [ "tlapm-lsp-test.prover-info"; "tlapm-lsp-test.prove-step" ] + [ "tlapm-lsp-test.prover-info"; "tlapm-lsp-test.prove-step.lsp" ] in let capabilities = ServerCapabilities.create @@ -155,7 +155,7 @@ let handle_jsonrpc_req_exec_cmd (jsonrpc_req : Jsonrpc.Request.t) Eio.traceln "COMMAND: prover-info"; reply_ok jsonrpc_req writer (`String "OK"); state - | "tlapm-lsp-test.prove-step" -> + | "tlapm-lsp-test.prove-step.lsp" -> (* TODO: Args are passed from the codeAction. *) Eio.traceln "COMMAND: prove-step"; reply_ok jsonrpc_req writer (`String "OK"); @@ -184,7 +184,7 @@ let handle_jsonrpc_req_code_action (jsonrpc_req : Jsonrpc.Request.t) Lsp.Types.CodeAction.create ~title:"Prover code action" ~diagnostics:[ someActionDiag ] ~command: - (Command.create ~command:"tlapm-lsp-test.prove-step" + (Command.create ~command:"tlapm-lsp-test.prove-step.lsp" ~title:"Prove it as an action!" ~arguments:[ `String "important_arg" ] ()) diff --git a/lsp/test/tlapm-lsp-test/package.json b/lsp/test/tlapm-lsp-test/package.json index 1474f1cf..89240664 100644 --- a/lsp/test/tlapm-lsp-test/package.json +++ b/lsp/test/tlapm-lsp-test/package.json @@ -16,7 +16,7 @@ "contributes": { "keybindings":[ { - "command": "tlapm-lsp-test.prover-info", + "command": "tlapm-lsp-test.prove-step", "key": "ctrl+g ctrl+g" } ], @@ -25,6 +25,11 @@ "command": "tlapm-lsp-test.prover-info", "title": "TLAPM: Prover info", "when": "editorLangId == tlaplus" + }, + { + "command": "tlapm-lsp-test.prove-step", + "title": "TLAPM: Prove current step", + "when": "editorLangId == tlaplus" } ] }, diff --git a/lsp/test/tlapm-lsp-test/src/extension.ts b/lsp/test/tlapm-lsp-test/src/extension.ts index 7b36af48..e1d8fc3f 100644 --- a/lsp/test/tlapm-lsp-test/src/extension.ts +++ b/lsp/test/tlapm-lsp-test/src/extension.ts @@ -1,5 +1,5 @@ import * as vscode from 'vscode'; -import { Executable, LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node'; +import { Executable, LanguageClient, LanguageClientOptions, TransportKind } from 'vscode-languageclient/node'; let client: LanguageClient; @@ -8,6 +8,18 @@ export function activate(context: vscode.ExtensionContext) { pocTestCases(); + context.subscriptions.push(vscode.commands.registerTextEditorCommand('tlapm-lsp-test.prove-step', (te, ed, args) => { + console.log("CMD: tlapm-lsp-test.prove-step invoked."); + vscode.commands.executeCommand("tlapm-lsp-test.prove-step.lsp", [ + { + uri: te.document.uri, + version: te.document.version, + cursor: te.selection.active, + selection: {from: te.selection.start, till: te.selection.end} + } + ]); + })); + const serverPath = context.asAbsolutePath('../../../_build/default/lsp/bin/tlapm_lsp.exe'); const logPath = context.asAbsolutePath('tlapm_lsp.log'); const serverOptions: Executable = { From 9bd124e1e558cea04b5c5fa9c49c94065ea3e86b Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Fri, 29 Sep 2023 10:59:51 +0300 Subject: [PATCH 022/140] Some tests. Signed-off-by: Karolis Petrauskas --- lsp/lib/dune | 6 +- lsp/lib/tlapm_lsp_docs.ml | 7 ++ lsp/lib/tlapm_lsp_docs.mli | 3 + lsp/lib/tlapm_lsp_prover.ml | 149 +++++++++++++++++++++++++++++++++++ lsp/lib/tlapm_lsp_prover.mli | 11 +++ lsp/lib/tlapm_lsp_state.ml | 29 ++++++- lsp/test/tlapm_mock.sh | 10 +++ 7 files changed, 212 insertions(+), 3 deletions(-) create mode 100644 lsp/lib/tlapm_lsp_prover.ml create mode 100644 lsp/lib/tlapm_lsp_prover.mli create mode 100755 lsp/test/tlapm_mock.sh diff --git a/lsp/lib/dune b/lsp/lib/dune index 858307cd..fcd4e5ce 100644 --- a/lsp/lib/dune +++ b/lsp/lib/dune @@ -1,4 +1,8 @@ (library (name tlapm_lsp_lib) (optional) ; Only build, if eio is available, which is only the case for ocaml > 5. - (libraries tlapm_lib lsp eio_main dune-build-info)) + (libraries tlapm_lib lsp eio_main dune-build-info) + (inline_tests + (deps "../test/tlapm_mock.sh" "../../src/tlapm.exe")) + (preprocess + (pps ppx_inline_test))) diff --git a/lsp/lib/tlapm_lsp_docs.ml b/lsp/lib/tlapm_lsp_docs.ml index dbdf3c69..d3af33c2 100644 --- a/lsp/lib/tlapm_lsp_docs.ml +++ b/lsp/lib/tlapm_lsp_docs.ml @@ -23,3 +23,10 @@ let get_opt docs uri = | None -> None | Some { versions = [] } -> None | Some { versions = v :: _ } -> Some (v.text, v.version) + +let get_vsn_opt docs uri vsn = + match Docs.find_opt uri docs with + | None -> None + | Some { versions } -> + let matching v = if v.version = vsn then Some v.text else None in + List.find_map matching versions diff --git a/lsp/lib/tlapm_lsp_docs.mli b/lsp/lib/tlapm_lsp_docs.mli index 07d429ba..d5e1e310 100644 --- a/lsp/lib/tlapm_lsp_docs.mli +++ b/lsp/lib/tlapm_lsp_docs.mli @@ -17,3 +17,6 @@ val rem : t -> tk -> t val get_opt : t -> tk -> (string * int) option (** Lookup document's last revision. *) + +val get_vsn_opt : t -> tk -> int -> string option +(** Lookup specific document revision. *) diff --git a/lsp/lib/tlapm_lsp_prover.ml b/lsp/lib/tlapm_lsp_prover.ml new file mode 100644 index 00000000..7db2cd22 --- /dev/null +++ b/lsp/lib/tlapm_lsp_prover.ml @@ -0,0 +1,149 @@ +module Docs = Tlapm_lsp_docs + +(* A megabyte is probably enough for tlapm IO. *) +let tlapm_buf_size = 1024 * 1024 + +(* Environment for the parser. Introduced mainly to make it testable. *) +module type ProverEnv = sig + val tlapm_exe : unit -> (string, string) result + val have_error : Lsp.Types.Range.t -> string -> unit +end + +(** Default implementation for ProverEnv *) +module DefaultPE : ProverEnv = struct + (* + Returns tha tlapm executable path or error, if there is no such in known places. + If installed, both files are in the same dir: + - .../bin/tlapm + - .../bin/tlapm_lsp + Otherwise, if that's development environment, the files are: + - .../src/tlapm.exe + - .../lsp/bin/tlapm_lsp.exe + And during the inline tests: + - .../src/tlapm.exe + - .../lsp/lib/.tlapm_lsp_lib.inline-tests/inline_test_runner_tlapm_lsp_lib.exe + *) + let tlapm_exe () = + let open Filename in + let this_exe = Sys.executable_name in + let this_abs = + match is_relative this_exe with + | true -> concat current_dir_name this_exe + | false -> this_exe + in + let tlapm_in_bin = concat (dirname this_abs) "tlapm" in + let tlapm_in_src = + let base_dir = dirname @@ dirname @@ dirname this_abs in + concat (concat base_dir "src") "tlapm.exe" + in + let tlapm_in_tst = + let base_dir = dirname @@ dirname @@ dirname @@ dirname this_abs in + concat (concat base_dir "src") "tlapm.exe" + in + let paths_to_check = [ tlapm_in_bin; tlapm_in_src; tlapm_in_tst ] in + match List.find_opt Sys.file_exists paths_to_check with + | Some path -> Ok path + | None -> + Error + ("tlapm not found, expected it among as: " + ^ String.concat ", " paths_to_check) + + let have_error _r _m = + (* TODO: Update the docs *) + () +end + +type t = { + sw : Eio.Switch.t; + fs : Eio__.Fs.dir_ty Eio.Path.t; + mgr : Eio_unix.Process.mgr_ty Eio.Process.mgr; + docs : Docs.t; + proc : [ `Generic | `Unix ] Eio.Process.ty Eio__.Std.r option; +} + +(** Create instance of a prover process manager. *) +let create sw fs mgr docs = { sw; fs; mgr; docs; proc = None } + +(** Cancel (all) the preceding prover instances. *) +let cancel_all st = + match st.proc with + | None -> st + | Some proc -> + Eio.Process.signal proc Sys.sigint; + ignore (Eio.Process.await proc); + { st with proc = None } + +(* TODO: Implement. *) +let start_async'' st doc_uri _doc_vsn doc_text line_from line_till executable = + let mod_path = Lsp.Types.DocumentUri.to_path doc_uri in + let mod_dir = + let open Eio.Path in + st.fs / Filename.dirname mod_path + in + let mod_name = Filename.basename mod_path in + let out_buf = Buffer.create tlapm_buf_size in + let stdin = Eio.Flow.string_source doc_text in + let stdout = Eio.Flow.buffer_sink out_buf in + let proc_args = + [ + "--toolbox"; + string_of_int line_from; + string_of_int line_till; + "--stdin"; + mod_name; + ] + (* TODO: Add support for the stdin option. *) + in + let proc = + Eio.Process.spawn st.mgr ~sw:st.sw ~executable ~cwd:mod_dir ~stdin ~stdout + proc_args + in + Eio.Fiber.fork ~sw:st.sw (fun () -> (* TODO: .. *) + ()); + { st with proc = Some proc } + +(* Run the tlapm prover, cancel the preceding one, if any. *) +let start_async' st ?(pe = (module DefaultPE : ProverEnv)) doc_uri doc_vsn + line_from line_till = + let module PE = (val pe : ProverEnv) in + match PE.tlapm_exe () with + | Ok executable -> ( + match Docs.get_vsn_opt st.docs doc_uri doc_vsn with + | Some doc_text -> + let st' = cancel_all st in + Ok + (start_async'' st' doc_uri doc_vsn doc_text line_from line_till + executable) + | None -> Error "Document not found") + | Error reason -> Error reason + +let start_async st doc_uri doc_vsn line_from line_till = + start_async' st doc_uri doc_vsn line_from line_till + +(* ********************** Test cases ********************** *) + +let%test_unit "basics" = + Eio_main.run @@ fun env -> + Eio.Switch.run @@ fun sw -> + let fs = Eio.Stdenv.fs env in + let mgr = Eio.Stdenv.process_mgr env in + let docs = Docs.empty in + let du = Lsp.Types.DocumentUri.of_path "/tmp/any-file.tla" in + let dv = 1 in + let docs = Docs.add docs du dv "any\ncontent" in + let pr = create sw fs mgr docs in + let errs = ref [] in + let pe = + (module struct + let tlapm_exe () = + let cwd = Sys.getcwd () in + Ok (Filename.concat cwd "../test/tlapm_mock.sh") + let have_error _r m = errs := m :: !errs + end : ProverEnv) + in + let _docs = + match start_async' pr ~pe du dv 3 7 with + | Ok docs -> docs + | Error e -> failwith e + in + () diff --git a/lsp/lib/tlapm_lsp_prover.mli b/lsp/lib/tlapm_lsp_prover.mli new file mode 100644 index 00000000..59e46678 --- /dev/null +++ b/lsp/lib/tlapm_lsp_prover.mli @@ -0,0 +1,11 @@ +type t + +val create : + Eio.Switch.t -> + Eio__.Fs.dir_ty Eio.Path.t -> + Eio_unix.Process.mgr_ty Eio.Process.mgr -> + Tlapm_lsp_docs.t -> + t + +val start_async : + t -> Tlapm_lsp_docs.tk -> int -> int -> int -> (t, string) result diff --git a/lsp/lib/tlapm_lsp_state.ml b/lsp/lib/tlapm_lsp_state.ml index 505ec9fc..2737caac 100644 --- a/lsp/lib/tlapm_lsp_state.ml +++ b/lsp/lib/tlapm_lsp_state.ml @@ -1,7 +1,9 @@ +module Docs = Tlapm_lsp_docs + type mode = Initializing | Ready | Shutdown -type t = { mode : mode; docs : Tlapm_lsp_docs.t } +type t = { mode : mode; docs : Docs.t } -let empty = { mode = Initializing; docs = Tlapm_lsp_docs.empty } +let empty = { mode = Initializing; docs = Docs.empty } let ready st = match st.mode with @@ -27,3 +29,26 @@ let handle_if_ready_silent st f = | Error err -> Eio.traceln "Ignoring request: %s" err; st + +(* ********************** Test cases ********************** *) + +let%test_unit "basics" = + let st = empty in + let () = + match handle_if_ready st (fun docs -> docs) with + | Ok _ -> failwith "should fail" + | Error _ -> () + in + let st = ready st in + let st = + match handle_if_ready st (fun docs -> docs) with + | Ok st -> st + | Error e -> failwith e + in + let st = shutdown st in + let () = + match handle_if_ready st (fun docs -> docs) with + | Ok _ -> failwith "should fail" + | Error _ -> () + in + () diff --git a/lsp/test/tlapm_mock.sh b/lsp/test/tlapm_mock.sh new file mode 100755 index 00000000..bbaab3d2 --- /dev/null +++ b/lsp/test/tlapm_mock.sh @@ -0,0 +1,10 @@ +#!/bin/bash +echo cmd=$0 args=$* +echo vienas +sleep 2 +echo du +sleep 3 +echo trys +sleep 4 +echo einu ieskot +exit $1 From 413bd17859e072c3925d48273900c120015becf5 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Mon, 2 Oct 2023 09:50:14 +0300 Subject: [PATCH 023/140] Some progress on the tlapm invokation. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_prover.ml | 268 ++++++++++++++++++++++++++++++++--- lsp/lib/tlapm_lsp_prover.mli | 31 ++++ lsp/test/tlapm_mock.sh | 95 +++++++++++-- 3 files changed, 365 insertions(+), 29 deletions(-) diff --git a/lsp/lib/tlapm_lsp_prover.ml b/lsp/lib/tlapm_lsp_prover.ml index 7db2cd22..254b0b99 100644 --- a/lsp/lib/tlapm_lsp_prover.ml +++ b/lsp/lib/tlapm_lsp_prover.ml @@ -1,7 +1,171 @@ module Docs = Tlapm_lsp_docs -(* A megabyte is probably enough for tlapm IO. *) -let tlapm_buf_size = 1024 * 1024 +(* ***** Types and parsers for them ***************************************** *) + +module ToolboxProtocol = struct + type tlapm_obl_state = + | ToBeProved + | BeingProved + | Normalized + | Proved + | Failed + | Interrupted + | Trivial + | Unknown of string + + let tlapm_obl_state_of_string s = + match s with + | "to be proved" -> ToBeProved + | "being proved" -> BeingProved + | "normalized" -> Normalized + | "proved" -> Proved + | "failed" -> Failed + | "interrupted" -> Interrupted + | "trivial" -> Trivial + | _ -> Unknown s + + type tlapm_loc = (int * int) * (int * int) + + let tlapm_loc_of_string_opt s = + match String.split_on_char ':' s with + | [ fl; fc; tl; tc ] -> + Some + ( (int_of_string fl, int_of_string fc), + (int_of_string tl, int_of_string tc) ) + | _ -> None + + type tlapm_msg = + | TlapmWarning of { msg : string } + | TlapmError of { url : string; msg : string } + | TlapmObligationsNumber of int + | TlapmObligation of { + id : int; + loc : tlapm_loc; + status : tlapm_obl_state; + fp : string option; + prover : string option; + meth : string option; + reason : string option; + already : bool option; + obl : string option; + } + + type parser_state = + | Empty + | Begin + | PartWarning of { msg : string option } + | PartError of { url : string option; msg : string option } + | PartObligationsNumber of int option + | PartObligation of { + id : int option; + loc : tlapm_loc option; + status : tlapm_obl_state option; + fp : string option; + prover : string option; + meth : string option; + reason : string option; + already : bool option; + obl : string option; + } + | PartUnknown + + let match_line line = + let re = Str.regexp "^@!!\\([a-z]*\\):\\(.*\\)$" in + match Str.string_match re line 0 with + | true -> + let k = Str.matched_group 1 line in + let v = Str.matched_group 2 line in + Some (k, v) + | false -> None + + let parse_start = Empty + + (* TODO: Handle multiline fields. *) + let parse_line line acc stream = + match (acc, line) with + | Empty, "@!!BEGIN" -> Begin + | Empty, _ -> Empty + | Begin, "@!!type:warning" -> PartWarning { msg = None } + | Begin, "@!!type:error" -> PartError { msg = None; url = None } + | Begin, "@!!type:obligationsnumber" -> PartObligationsNumber None + | Begin, "@!!type:obligation" -> + PartObligation + { + id = None; + loc = None; + status = None; + fp = None; + prover = None; + meth = None; + reason = None; + already = None; + obl = None; + } + | Begin, _ -> PartUnknown + | PartWarning { msg = Some msg }, "@!!END" -> + Eio.Stream.add stream (TlapmWarning { msg }); + Empty + | PartWarning w, _ -> ( + match match_line line with + | Some ("msg", v) -> PartWarning { msg = Some v } + | Some (_, _) -> PartWarning w + | None -> PartWarning w) + | PartError { msg = Some msg; url = Some url }, "@!!END" -> + Eio.Stream.add stream (TlapmError { msg; url }); + Empty + | PartError e, _ -> ( + match match_line line with + | Some ("msg", v) -> PartError { e with msg = Some v } + | Some ("url", v) -> PartError { e with url = Some v } + | Some (_, _) -> PartError e + | None -> PartError e) + | PartObligationsNumber (Some count), "@!!END" -> + Eio.Stream.add stream (TlapmObligationsNumber count); + Empty + | PartObligationsNumber e, _ -> ( + match match_line line with + | Some ("count", v) -> PartObligationsNumber (int_of_string_opt v) + | Some (_, _) -> PartObligationsNumber e + | None -> PartObligationsNumber e) + | ( PartObligation + { + id = Some id; + loc = Some loc; + status = Some status; + fp; + prover; + meth; + reason; + already; + obl; + }, + "@!!END" ) -> + Eio.Stream.add stream + (TlapmObligation + { id; loc; status; fp; prover; meth; reason; already; obl }); + Empty + | PartObligation o, _ -> ( + match match_line line with + | Some ("id", v) -> PartObligation { o with id = int_of_string_opt v } + | Some ("loc", v) -> + PartObligation { o with loc = tlapm_loc_of_string_opt v } + | Some ("status", v) -> + PartObligation + { o with status = Some (tlapm_obl_state_of_string v) } + | Some ("fp", v) -> PartObligation { o with fp = Some v } + | Some ("prover", v) -> PartObligation { o with prover = Some v } + | Some ("meth", v) -> PartObligation { o with meth = Some v } + | Some ("reason", v) -> PartObligation { o with reason = Some v } + | Some ("already", v) -> + PartObligation { o with already = bool_of_string_opt v } + | Some ("obl", v) -> PartObligation { o with obl = Some v } + | Some (_, _) -> PartObligation o + | None -> PartObligation o) + | _, "@!!END" -> Empty + | _, _ -> acc +end + +(* ***** Prover process management ****************************************** *) (* Environment for the parser. Introduced mainly to make it testable. *) module type ProverEnv = sig @@ -53,39 +217,81 @@ module DefaultPE : ProverEnv = struct () end +(* Currently forked tlapm process. *) +type tf = { + proc : [ `Generic | `Unix ] Eio.Process.ty Eio__.Std.r; + complete : unit Eio.Promise.or_exn; + cancel : unit Eio.Promise.u; +} + type t = { sw : Eio.Switch.t; fs : Eio__.Fs.dir_ty Eio.Path.t; mgr : Eio_unix.Process.mgr_ty Eio.Process.mgr; + stream : ToolboxProtocol.tlapm_msg Eio.Stream.t; docs : Docs.t; - proc : [ `Generic | `Unix ] Eio.Process.ty Eio__.Std.r option; + forked : tf option; } (** Create instance of a prover process manager. *) -let create sw fs mgr docs = { sw; fs; mgr; docs; proc = None } +let create sw fs mgr stream docs = { sw; fs; mgr; stream; docs; forked = None } (** Cancel (all) the preceding prover instances. *) let cancel_all st = - match st.proc with + match st.forked with | None -> st - | Some proc -> + | Some { proc; complete; cancel } -> Eio.Process.signal proc Sys.sigint; - ignore (Eio.Process.await proc); - { st with proc = None } + (match Eio.Process.await proc with + | `Exited x -> Eio.traceln "[TLAPM] Process exited %d" x + | `Signaled x -> + Eio.traceln "[TLAPM] Process signalled %d" x; + Eio.Promise.resolve cancel ()); + (match Eio.Promise.await complete with + | Ok () -> Eio.traceln "[TLAPM] Fiber exited" + | Error e -> + Eio.traceln "[TLAPM] Fiber failed with %s" (Printexc.to_string e)); + { st with forked = None } + +(* Start a fiber to read the tlapm stdout asynchronously. *) +let fork_read sw stream r w cancel = + let fib_read () = + Eio.Flow.close w; + let rec read_fun' br acc = + let line = Eio.Buf_read.line br in + let acc' = ToolboxProtocol.parse_line line acc stream in + if Eio.Buf_read.at_end_of_input br then () else read_fun' br acc' + in + let read_fun br = read_fun' br ToolboxProtocol.parse_start in + let read_result = + Eio.Buf_read.parse ~initial_size:5 ~max_size:200 read_fun r + in + (match read_result with + | Ok () -> Eio.traceln "TLAPM process completed." + | Error (`Msg msg) -> Eio.traceln "TLAPM process failed with: %s" msg); + Eio.Flow.close r; + Eio.traceln "TLAPM read fiber completed." + in + let fib_cancel () = Eio.Promise.await cancel in + Eio.Fiber.fork_promise ~sw @@ fun () -> + Eio.Fiber.first fib_read fib_cancel; + Eio.traceln "TLAPM main fiber completed" -(* TODO: Implement. *) -let start_async'' st doc_uri _doc_vsn doc_text line_from line_till executable = +(** Start the TLAPM process and attach the reader fiber to it. *) +let start_async_with_text st doc_uri _doc_vsn doc_text line_from line_till + executable = let mod_path = Lsp.Types.DocumentUri.to_path doc_uri in let mod_dir = let open Eio.Path in st.fs / Filename.dirname mod_path in let mod_name = Filename.basename mod_path in - let out_buf = Buffer.create tlapm_buf_size in let stdin = Eio.Flow.string_source doc_text in - let stdout = Eio.Flow.buffer_sink out_buf in + let r, w = Eio.Process.pipe st.mgr ~sw:st.sw in let proc_args = [ + (* First arg s ignored, id executable is specified. *) + "tlapm"; "--toolbox"; string_of_int line_from; string_of_int line_till; @@ -95,12 +301,13 @@ let start_async'' st doc_uri _doc_vsn doc_text line_from line_till executable = (* TODO: Add support for the stdin option. *) in let proc = - Eio.Process.spawn st.mgr ~sw:st.sw ~executable ~cwd:mod_dir ~stdin ~stdout + Eio.Process.spawn st.mgr ~sw:st.sw ~executable ~cwd:mod_dir ~stdin ~stdout:w proc_args in - Eio.Fiber.fork ~sw:st.sw (fun () -> (* TODO: .. *) - ()); - { st with proc = Some proc } + let cancel_p, cancel_r = Eio.Promise.create () in + let complete = fork_read st.sw st.stream r w cancel_p in + let forked = { proc; complete; cancel = cancel_r } in + { st with forked = Some forked } (* Run the tlapm prover, cancel the preceding one, if any. *) let start_async' st ?(pe = (module DefaultPE : ProverEnv)) doc_uri doc_vsn @@ -112,32 +319,53 @@ let start_async' st ?(pe = (module DefaultPE : ProverEnv)) doc_uri doc_vsn | Some doc_text -> let st' = cancel_all st in Ok - (start_async'' st' doc_uri doc_vsn doc_text line_from line_till - executable) + (start_async_with_text st' doc_uri doc_vsn doc_text line_from + line_till executable) | None -> Error "Document not found") | Error reason -> Error reason +(* The public version, just to avoid exposing the ProverEnv module type. *) let start_async st doc_uri doc_vsn line_from line_till = start_async' st doc_uri doc_vsn line_from line_till (* ********************** Test cases ********************** *) +let%test_unit "parse_line_warning" = + let open ToolboxProtocol in + let stream = Eio.Stream.create 10 in + let lines = + [ "@!!BEGIN"; "@!!type:obligationsnumber"; "@!!count:17"; "@!!END" ] + in + match + List.fold_left (fun acc l -> parse_line l acc stream) parse_start lines + with + | Empty -> ( + match Eio.Stream.length stream with + | 1 -> ( + match Eio.Stream.take stream with + | TlapmObligationsNumber 17 -> () + | _ -> failwith "unexpected msg") + | _ -> failwith "unexpected msg count") + | _ -> failwith "unexpected parser state" + let%test_unit "basics" = Eio_main.run @@ fun env -> Eio.Switch.run @@ fun sw -> let fs = Eio.Stdenv.fs env in let mgr = Eio.Stdenv.process_mgr env in let docs = Docs.empty in - let du = Lsp.Types.DocumentUri.of_path "/tmp/any-file.tla" in + let du = Lsp.Types.DocumentUri.of_path "TimingExit0.tla" in let dv = 1 in let docs = Docs.add docs du dv "any\ncontent" in - let pr = create sw fs mgr docs in + let stream = Eio.Stream.create 10 in + let pr = create sw fs mgr stream docs in let errs = ref [] in let pe = (module struct let tlapm_exe () = let cwd = Sys.getcwd () in Ok (Filename.concat cwd "../test/tlapm_mock.sh") + let have_error _r m = errs := m :: !errs end : ProverEnv) in diff --git a/lsp/lib/tlapm_lsp_prover.mli b/lsp/lib/tlapm_lsp_prover.mli index 59e46678..e7098d04 100644 --- a/lsp/lib/tlapm_lsp_prover.mli +++ b/lsp/lib/tlapm_lsp_prover.mli @@ -1,9 +1,40 @@ type t +module ToolboxProtocol : sig + type tlapm_obl_state = + | ToBeProved + | BeingProved + | Normalized + | Proved + | Failed + | Interrupted + | Trivial + | Unknown of string + + type tlapm_loc = (int * int) * (int * int) + + type tlapm_msg = + | TlapmWarning of { msg : string } + | TlapmError of { url : string; msg : string } + | TlapmObligationsNumber of int + | TlapmObligation of { + id : int; + loc : tlapm_loc; + status : tlapm_obl_state; + fp : string option; + prover : string option; + meth : string option; + reason : string option; + already : bool option; + obl : string option; + } +end + val create : Eio.Switch.t -> Eio__.Fs.dir_ty Eio.Path.t -> Eio_unix.Process.mgr_ty Eio.Process.mgr -> + ToolboxProtocol.tlapm_msg Eio.Stream.t -> Tlapm_lsp_docs.t -> t diff --git a/lsp/test/tlapm_mock.sh b/lsp/test/tlapm_mock.sh index bbaab3d2..2f160a22 100755 --- a/lsp/test/tlapm_mock.sh +++ b/lsp/test/tlapm_mock.sh @@ -1,10 +1,87 @@ #!/bin/bash -echo cmd=$0 args=$* -echo vienas -sleep 2 -echo du -sleep 3 -echo trys -sleep 4 -echo einu ieskot -exit $1 + +## +## That's a tlapm mock for some of the tlapm_lsp_parser test cases. +## + +if [ "$1" != "--toolbox" ] ; then + echo "ERROR: Expected --toolbox as a first argument." + exit 2 +fi + +# We differentiate the testcases by the last argument, which is usually a TLA file. +last_arg=${@: -1} +case "$last_arg" in + TimingExit0.tla) + echo Starting... + sleep 1; echo First proof done + sleep 1; echo Second proof fone + sleep 1; echo All proofs OK. + exit 0 + ;; + TimingExit1.tla) + echo Starting... + sleep 1; echo First proof done + sleep 1; echo Second proof fone + sleep 1; echo All proofs OK. + exit 1 + ;; + Empty.tla) + cat << EOF +\* TLAPM version 1.5.0 +\* launched at 2023-09-30 23:39:35 with command line: +\* tlapm --toolbox 0 0 Empty.tla + +@!!BEGIN +@!!type:obligationsnumber +@!!count:0 +@!!END + +(* created new ".tlacache/Empty.tlaps/Some.thy" *) +(* fingerprints written in ".tlacache/Empty.tlaps/fingerprints" *) +File "./Empty.tla", line 1, character 1 to line 5, character 4: +[INFO]: All 0 obligation proved. +EOF + ;; + Some.tla) +cat << EOF +\* TLAPM version 1.5.0 +\* launched at 2023-09-30 23:43:15 with command line: +\* tlapm --toolbox 0 0 Some.tla + +(* loading fingerprints in ".tlacache/Some.tlaps/fingerprints" *) +@!!BEGIN +@!!type:obligation +@!!id:1 +@!!loc:5:3:5:10 +@!!status:to be proved +@!!END + +@!!BEGIN +@!!type:obligationsnumber +@!!count:1 +@!!END + +** Unexpanded symbols: --- + +@!!BEGIN +@!!type:obligation +@!!id:1 +@!!loc:5:3:5:10 +@!!status:proved +@!!prover:smt +@!!meth:time-limit: 5; time-used: 0.0 (0%) +@!!already:false +@!!END + +(* created new ".tlacache/Some.tlaps/Some.thy" *) +(* fingerprints written in ".tlacache/Some.tlaps/fingerprints" *) +File "./Some.tla", line 1, character 1 to line 6, character 4: +[INFO]: All 1 obligation proved. +EOF + ;; + *) + echo "ERROR: Unexpected testcase, last_arg=$last_arg." + exit 2 + ;; +esac From bf5428868e334ab8b91806f42e5d52af4603f773 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Mon, 2 Oct 2023 20:11:30 +0300 Subject: [PATCH 024/140] Toolbox parser, support multiline fields. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_prover.ml | 223 ++++++++++++++++++++++++------------ 1 file changed, 148 insertions(+), 75 deletions(-) diff --git a/lsp/lib/tlapm_lsp_prover.ml b/lsp/lib/tlapm_lsp_prover.ml index 254b0b99..e522383c 100644 --- a/lsp/lib/tlapm_lsp_prover.ml +++ b/lsp/lib/tlapm_lsp_prover.ml @@ -50,9 +50,7 @@ module ToolboxProtocol = struct obl : string option; } - type parser_state = - | Empty - | Begin + type parser_part_msg = | PartWarning of { msg : string option } | PartError of { url : string option; msg : string option } | PartObligationsNumber of int option @@ -69,6 +67,15 @@ module ToolboxProtocol = struct } | PartUnknown + type parser_state = + | Empty + | Begin + | PartMsg of { + field : string option; + acc_val : string; + acc_msg : parser_part_msg; + } + let match_line line = let re = Str.regexp "^@!!\\([a-z]*\\):\\(.*\\)$" in match Str.string_match re line 0 with @@ -80,54 +87,49 @@ module ToolboxProtocol = struct let parse_start = Empty - (* TODO: Handle multiline fields. *) let parse_line line acc stream = - match (acc, line) with - | Empty, "@!!BEGIN" -> Begin - | Empty, _ -> Empty - | Begin, "@!!type:warning" -> PartWarning { msg = None } - | Begin, "@!!type:error" -> PartError { msg = None; url = None } - | Begin, "@!!type:obligationsnumber" -> PartObligationsNumber None - | Begin, "@!!type:obligation" -> - PartObligation - { - id = None; - loc = None; - status = None; - fp = None; - prover = None; - meth = None; - reason = None; - already = None; - obl = None; - } - | Begin, _ -> PartUnknown - | PartWarning { msg = Some msg }, "@!!END" -> - Eio.Stream.add stream (TlapmWarning { msg }); - Empty - | PartWarning w, _ -> ( - match match_line line with - | Some ("msg", v) -> PartWarning { msg = Some v } - | Some (_, _) -> PartWarning w - | None -> PartWarning w) - | PartError { msg = Some msg; url = Some url }, "@!!END" -> - Eio.Stream.add stream (TlapmError { msg; url }); - Empty - | PartError e, _ -> ( - match match_line line with - | Some ("msg", v) -> PartError { e with msg = Some v } - | Some ("url", v) -> PartError { e with url = Some v } - | Some (_, _) -> PartError e - | None -> PartError e) - | PartObligationsNumber (Some count), "@!!END" -> - Eio.Stream.add stream (TlapmObligationsNumber count); - Empty - | PartObligationsNumber e, _ -> ( - match match_line line with - | Some ("count", v) -> PartObligationsNumber (int_of_string_opt v) - | Some (_, _) -> PartObligationsNumber e - | None -> PartObligationsNumber e) - | ( PartObligation + let new_msg m = PartMsg { field = None; acc_val = ""; acc_msg = m } in + let set_field n v = function + | PartWarning w -> ( + match n with + | "msg" -> PartWarning { msg = Some v } + | _ -> PartWarning w) + | PartError e -> ( + match n with + | "msg" -> PartError { e with msg = Some v } + | "url" -> PartError { e with url = Some v } + | _ -> PartError e) + | PartObligationsNumber e -> ( + match n with + | "count" -> PartObligationsNumber (int_of_string_opt v) + | _ -> PartObligationsNumber e) + | PartObligation o -> ( + match n with + | "id" -> PartObligation { o with id = int_of_string_opt v } + | "loc" -> PartObligation { o with loc = tlapm_loc_of_string_opt v } + | "status" -> + PartObligation + { o with status = Some (tlapm_obl_state_of_string v) } + | "fp" -> PartObligation { o with fp = Some v } + | "prover" -> PartObligation { o with prover = Some v } + | "meth" -> PartObligation { o with meth = Some v } + | "reason" -> PartObligation { o with reason = Some v } + | "already" -> + PartObligation { o with already = bool_of_string_opt v } + | "obl" -> PartObligation { o with obl = Some v } + | _ -> PartObligation o) + | PartUnknown -> PartUnknown + in + let msg_of_part = function + | PartWarning { msg = Some msg } -> Some (TlapmWarning { msg }) + | PartWarning _ -> None + | PartError { msg = Some msg; url = Some url } -> + Some (TlapmError { msg; url }) + | PartError _ -> None + | PartObligationsNumber (Some count) -> + Some (TlapmObligationsNumber count) + | PartObligationsNumber _ -> None + | PartObligation { id = Some id; loc = Some loc; @@ -138,31 +140,58 @@ module ToolboxProtocol = struct reason; already; obl; - }, - "@!!END" ) -> - Eio.Stream.add stream - (TlapmObligation - { id; loc; status; fp; prover; meth; reason; already; obl }); + } -> + Some + (TlapmObligation + { id; loc; status; fp; prover; meth; reason; already; obl }) + | PartObligation _ -> None + | PartUnknown -> None + in + match (acc, line) with + | Empty, "@!!BEGIN" -> Begin + | Empty, _ -> Empty + | Begin, "@!!type:warning" -> new_msg (PartWarning { msg = None }) + | Begin, "@!!type:error" -> new_msg (PartError { msg = None; url = None }) + | Begin, "@!!type:obligationsnumber" -> new_msg (PartObligationsNumber None) + | Begin, "@!!type:obligation" -> + new_msg + (PartObligation + { + id = None; + loc = None; + status = None; + fp = None; + prover = None; + meth = None; + reason = None; + already = None; + obl = None; + }) + | Begin, _ -> new_msg PartUnknown + | PartMsg { field; acc_val; acc_msg }, "@!!END" -> + let maybe_out_msg = + match field with + | Some f -> msg_of_part (set_field f acc_val acc_msg) + | None -> msg_of_part acc_msg + in + (match maybe_out_msg with + | Some out_msg -> Eio.Stream.add stream out_msg + | None -> ()); Empty - | PartObligation o, _ -> ( + | (PartMsg { field; acc_val; acc_msg } as msg), _ -> ( match match_line line with - | Some ("id", v) -> PartObligation { o with id = int_of_string_opt v } - | Some ("loc", v) -> - PartObligation { o with loc = tlapm_loc_of_string_opt v } - | Some ("status", v) -> - PartObligation - { o with status = Some (tlapm_obl_state_of_string v) } - | Some ("fp", v) -> PartObligation { o with fp = Some v } - | Some ("prover", v) -> PartObligation { o with prover = Some v } - | Some ("meth", v) -> PartObligation { o with meth = Some v } - | Some ("reason", v) -> PartObligation { o with reason = Some v } - | Some ("already", v) -> - PartObligation { o with already = bool_of_string_opt v } - | Some ("obl", v) -> PartObligation { o with obl = Some v } - | Some (_, _) -> PartObligation o - | None -> PartObligation o) - | _, "@!!END" -> Empty - | _, _ -> acc + | Some (k, v) -> ( + match field with + | Some f -> + let acc_msg' = set_field f acc_val acc_msg in + PartMsg { field = Some k; acc_val = v; acc_msg = acc_msg' } + | None -> PartMsg { field = Some k; acc_val = v; acc_msg }) + | None -> ( + match field with + | Some _ -> + let acc_val' = acc_val ^ "\n" ^ line in + PartMsg { field; acc_val = acc_val'; acc_msg } + | None -> msg)) end (* ***** Prover process management ****************************************** *) @@ -330,11 +359,17 @@ let start_async st doc_uri doc_vsn line_from line_till = (* ********************** Test cases ********************** *) -let%test_unit "parse_line_warning" = +let%test_unit "parse_line-warning" = let open ToolboxProtocol in let stream = Eio.Stream.create 10 in let lines = - [ "@!!BEGIN"; "@!!type:obligationsnumber"; "@!!count:17"; "@!!END" ] + [ + (* keep it multiline*) + "@!!BEGIN"; + "@!!type:obligationsnumber"; + "@!!count:17"; + "@!!END"; + ] in match List.fold_left (fun acc l -> parse_line l acc stream) parse_start lines @@ -348,6 +383,44 @@ let%test_unit "parse_line_warning" = | _ -> failwith "unexpected msg count") | _ -> failwith "unexpected parser state" +let%test_unit "parse_line-multiline" = + let open ToolboxProtocol in + let stream = Eio.Stream.create 10 in + let lines = + [ + "@!!BEGIN"; + "@!!type:obligation"; + "@!!id:2"; + "@!!loc:10:3:10:10"; + "@!!status:failed"; + "@!!prover:isabelle"; + "@!!meth:auto; time-limit: 30; time-used: 0.0 (0%)"; + "@!!reason:false"; + "@!!already:false"; + "@!!obl:"; + "ASSUME NEW CONSTANT A"; + "PROVE \\A x \\in A : A \\in x"; + ""; + "@!!END"; + ] + in + match + List.fold_left (fun acc l -> parse_line l acc stream) parse_start lines + with + | Empty -> ( + match Eio.Stream.length stream with + | 1 -> ( + let obl = + "\nASSUME NEW CONSTANT A\nPROVE \\A x \\in A : A \\in x\n" + in + match Eio.Stream.take stream with + | TlapmObligation { obl = Some o; _ } when o = obl -> () + | TlapmObligation { obl = Some o; _ } -> + failwith (Format.sprintf "unexpected: %s" o) + | _ -> failwith "unexpected msg") + | _ -> failwith "unexpected msg count") + | _ -> failwith "unexpected parser state" + let%test_unit "basics" = Eio_main.run @@ fun env -> Eio.Switch.run @@ fun sw -> From 10f8edff50ba717ca5be6df7f2005243eb8eec42 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Mon, 2 Oct 2023 20:46:21 +0300 Subject: [PATCH 025/140] Small code simplifications. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_packets.ml | 10 ++-- lsp/lib/tlapm_lsp_prover.ml | 90 ++++++++++++++---------------------- lsp/lib/tlapm_lsp_prover.mli | 9 +++- lsp/lib/tlapm_lsp_server.ml | 2 + 4 files changed, 50 insertions(+), 61 deletions(-) diff --git a/lsp/lib/tlapm_lsp_packets.ml b/lsp/lib/tlapm_lsp_packets.ml index d3752107..0c36f26f 100644 --- a/lsp/lib/tlapm_lsp_packets.ml +++ b/lsp/lib/tlapm_lsp_packets.ml @@ -1,3 +1,5 @@ +(* cSpell:words sprintf *) + (** Helper to send responses to requests. *) let reply_ok (jsonrpc_req : Jsonrpc.Request.t) writer payload = let open Jsonrpc in @@ -34,15 +36,15 @@ let handle_jsonrpc_notif jsonrpc_notif writer state = ~end_:(Position.create ~line:1 ~character:7)) () in - let dpar = + let d_par = PublishDiagnosticsParams.create ~diagnostics:[ some ] ~uri ~version:vsn () in - let diag = Lsp.Server_notification.PublishDiagnostics dpar in - let dpkg = + let diag = Lsp.Server_notification.PublishDiagnostics d_par in + let d_pkg = Jsonrpc.Packet.Notification (Lsp.Server_notification.to_jsonrpc diag) in - writer dpkg + writer d_pkg in let with_docs docs = send_diags (); diff --git a/lsp/lib/tlapm_lsp_prover.ml b/lsp/lib/tlapm_lsp_prover.ml index e522383c..55db8c55 100644 --- a/lsp/lib/tlapm_lsp_prover.ml +++ b/lsp/lib/tlapm_lsp_prover.ml @@ -1,3 +1,5 @@ +(* cSpell:words obligationsnumber Printexc sprintf getcwd *) + module Docs = Tlapm_lsp_docs (* ***** Types and parsers for them ***************************************** *) @@ -196,15 +198,7 @@ end (* ***** Prover process management ****************************************** *) -(* Environment for the parser. Introduced mainly to make it testable. *) -module type ProverEnv = sig - val tlapm_exe : unit -> (string, string) result - val have_error : Lsp.Types.Range.t -> string -> unit -end - -(** Default implementation for ProverEnv *) -module DefaultPE : ProverEnv = struct - (* +(** Returns tha tlapm executable path or error, if there is no such in known places. If installed, both files are in the same dir: - .../bin/tlapm @@ -216,35 +210,30 @@ module DefaultPE : ProverEnv = struct - .../src/tlapm.exe - .../lsp/lib/.tlapm_lsp_lib.inline-tests/inline_test_runner_tlapm_lsp_lib.exe *) - let tlapm_exe () = - let open Filename in - let this_exe = Sys.executable_name in - let this_abs = - match is_relative this_exe with - | true -> concat current_dir_name this_exe - | false -> this_exe - in - let tlapm_in_bin = concat (dirname this_abs) "tlapm" in - let tlapm_in_src = - let base_dir = dirname @@ dirname @@ dirname this_abs in - concat (concat base_dir "src") "tlapm.exe" - in - let tlapm_in_tst = - let base_dir = dirname @@ dirname @@ dirname @@ dirname this_abs in - concat (concat base_dir "src") "tlapm.exe" - in - let paths_to_check = [ tlapm_in_bin; tlapm_in_src; tlapm_in_tst ] in - match List.find_opt Sys.file_exists paths_to_check with - | Some path -> Ok path - | None -> - Error - ("tlapm not found, expected it among as: " - ^ String.concat ", " paths_to_check) - - let have_error _r _m = - (* TODO: Update the docs *) - () -end +let tlapm_exe () = + let open Filename in + let this_exe = Sys.executable_name in + let this_abs = + match is_relative this_exe with + | true -> concat current_dir_name this_exe + | false -> this_exe + in + let tlapm_in_bin = concat (dirname this_abs) "tlapm" in + let tlapm_in_src = + let base_dir = dirname @@ dirname @@ dirname this_abs in + concat (concat base_dir "src") "tlapm.exe" + in + let tlapm_in_tst = + let base_dir = dirname @@ dirname @@ dirname @@ dirname this_abs in + concat (concat base_dir "src") "tlapm.exe" + in + let paths_to_check = [ tlapm_in_bin; tlapm_in_src; tlapm_in_tst ] in + match List.find_opt Sys.file_exists paths_to_check with + | Some path -> Ok path + | None -> + Error + ("tlapm not found, expected it among as: " + ^ String.concat ", " paths_to_check) (* Currently forked tlapm process. *) type tf = { @@ -339,10 +328,9 @@ let start_async_with_text st doc_uri _doc_vsn doc_text line_from line_till { st with forked = Some forked } (* Run the tlapm prover, cancel the preceding one, if any. *) -let start_async' st ?(pe = (module DefaultPE : ProverEnv)) doc_uri doc_vsn - line_from line_till = - let module PE = (val pe : ProverEnv) in - match PE.tlapm_exe () with +let start_async st doc_uri doc_vsn line_from line_till + ?(tlapm_locator = tlapm_exe) () = + match tlapm_locator () with | Ok executable -> ( match Docs.get_vsn_opt st.docs doc_uri doc_vsn with | Some doc_text -> @@ -353,10 +341,6 @@ let start_async' st ?(pe = (module DefaultPE : ProverEnv)) doc_uri doc_vsn | None -> Error "Document not found") | Error reason -> Error reason -(* The public version, just to avoid exposing the ProverEnv module type. *) -let start_async st doc_uri doc_vsn line_from line_till = - start_async' st doc_uri doc_vsn line_from line_till - (* ********************** Test cases ********************** *) let%test_unit "parse_line-warning" = @@ -432,18 +416,12 @@ let%test_unit "basics" = let docs = Docs.add docs du dv "any\ncontent" in let stream = Eio.Stream.create 10 in let pr = create sw fs mgr stream docs in - let errs = ref [] in - let pe = - (module struct - let tlapm_exe () = - let cwd = Sys.getcwd () in - Ok (Filename.concat cwd "../test/tlapm_mock.sh") - - let have_error _r m = errs := m :: !errs - end : ProverEnv) + let tlapm_locator () = + let cwd = Sys.getcwd () in + Ok (Filename.concat cwd "../test/tlapm_mock.sh") in let _docs = - match start_async' pr ~pe du dv 3 7 with + match start_async pr du dv 3 7 ~tlapm_locator () with | Ok docs -> docs | Error e -> failwith e in diff --git a/lsp/lib/tlapm_lsp_prover.mli b/lsp/lib/tlapm_lsp_prover.mli index e7098d04..0d2b7f6f 100644 --- a/lsp/lib/tlapm_lsp_prover.mli +++ b/lsp/lib/tlapm_lsp_prover.mli @@ -39,4 +39,11 @@ val create : t val start_async : - t -> Tlapm_lsp_docs.tk -> int -> int -> int -> (t, string) result + t -> + Tlapm_lsp_docs.tk -> + int -> + int -> + int -> + ?tlapm_locator:(unit -> (string, string) result) -> + unit -> + (t, string) result diff --git a/lsp/lib/tlapm_lsp_server.ml b/lsp/lib/tlapm_lsp_server.ml index af97641e..73cfa8e2 100644 --- a/lsp/lib/tlapm_lsp_server.ml +++ b/lsp/lib/tlapm_lsp_server.ml @@ -1,3 +1,5 @@ +(* cSpell:words Printexc Ipaddr *) + let max_size = 50 * 1024 * 1024 (* 50 MB should be enough. *) From 9316553f9018b7b9ebd5b3df27038a3123f206af Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Tue, 3 Oct 2023 09:31:20 +0300 Subject: [PATCH 026/140] Some notes. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_prover.ml | 8 ++++++++ lsp/lib/tlapm_lsp_prover.mli | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/lsp/lib/tlapm_lsp_prover.ml b/lsp/lib/tlapm_lsp_prover.ml index 55db8c55..5d8d38de 100644 --- a/lsp/lib/tlapm_lsp_prover.ml +++ b/lsp/lib/tlapm_lsp_prover.ml @@ -28,6 +28,12 @@ module ToolboxProtocol = struct type tlapm_loc = (int * int) * (int * int) + let range_of_loc (((fl, fc), (tl, tc)) : tlapm_loc) = + let open Lsp.Types in + Range.create + ~start:(Position.create ~line:fl ~character:fc) + ~end_:(Position.create ~line:tl ~character:tc) + let tlapm_loc_of_string_opt s = match String.split_on_char ':' s with | [ fl; fc; tl; tc ] -> @@ -51,6 +57,7 @@ module ToolboxProtocol = struct already : bool option; obl : string option; } + (* TODO: | TlapmTerminated *) type parser_part_msg = | PartWarning of { msg : string option } @@ -406,6 +413,7 @@ let%test_unit "parse_line-multiline" = | _ -> failwith "unexpected parser state" let%test_unit "basics" = + (* TODO: Test timing and cancellation. *) Eio_main.run @@ fun env -> Eio.Switch.run @@ fun sw -> let fs = Eio.Stdenv.fs env in diff --git a/lsp/lib/tlapm_lsp_prover.mli b/lsp/lib/tlapm_lsp_prover.mli index 0d2b7f6f..0b4694a5 100644 --- a/lsp/lib/tlapm_lsp_prover.mli +++ b/lsp/lib/tlapm_lsp_prover.mli @@ -1,5 +1,6 @@ type t +(** Types representing messages from the prover. *) module ToolboxProtocol : sig type tlapm_obl_state = | ToBeProved @@ -13,6 +14,8 @@ module ToolboxProtocol : sig type tlapm_loc = (int * int) * (int * int) + val range_of_loc : tlapm_loc -> Lsp.Types.Range.t + type tlapm_msg = | TlapmWarning of { msg : string } | TlapmError of { url : string; msg : string } @@ -37,6 +40,10 @@ val create : ToolboxProtocol.tlapm_msg Eio.Stream.t -> Tlapm_lsp_docs.t -> t +(** Create a tlapm process manager. *) + +val cancel_all : t -> t +(** Cancel all the ongoing proof processes, await for their termination. *) val start_async : t -> @@ -47,3 +54,4 @@ val start_async : ?tlapm_locator:(unit -> (string, string) result) -> unit -> (t, string) result +(** Start new proof process after canceling the existing processes. *) From 866892d251484d16dc1c36635b5e9c5f5ce836b3 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sat, 7 Oct 2023 10:18:02 +0300 Subject: [PATCH 027/140] Some test cases. Signed-off-by: Karolis Petrauskas --- lsp/lib/tlapm_lsp_prover.ml | 142 +++++++++++++++++++++++++++++------ lsp/lib/tlapm_lsp_prover.mli | 1 + lsp/test/tlapm_mock.sh | 67 +++++++++++------ 3 files changed, 163 insertions(+), 47 deletions(-) diff --git a/lsp/lib/tlapm_lsp_prover.ml b/lsp/lib/tlapm_lsp_prover.ml index 5d8d38de..afec6595 100644 --- a/lsp/lib/tlapm_lsp_prover.ml +++ b/lsp/lib/tlapm_lsp_prover.ml @@ -1,4 +1,4 @@ -(* cSpell:words obligationsnumber Printexc sprintf getcwd *) +(* cSpell:words obligationsnumber Printexc sprintf getcwd nonblocking *) module Docs = Tlapm_lsp_docs @@ -57,7 +57,7 @@ module ToolboxProtocol = struct already : bool option; obl : string option; } - (* TODO: | TlapmTerminated *) + | TlapmTerminated type parser_part_msg = | PartWarning of { msg : string option } @@ -266,7 +266,7 @@ let cancel_all st = match st.forked with | None -> st | Some { proc; complete; cancel } -> - Eio.Process.signal proc Sys.sigint; + Eio.Process.signal proc Sys.sigkill; (match Eio.Process.await proc with | `Exited x -> Eio.traceln "[TLAPM] Process exited %d" x | `Signaled x -> @@ -300,6 +300,7 @@ let fork_read sw stream r w cancel = let fib_cancel () = Eio.Promise.await cancel in Eio.Fiber.fork_promise ~sw @@ fun () -> Eio.Fiber.first fib_read fib_cancel; + Eio.Stream.add stream TlapmTerminated; Eio.traceln "TLAPM main fiber completed" (** Start the TLAPM process and attach the reader fiber to it. *) @@ -412,25 +413,116 @@ let%test_unit "parse_line-multiline" = | _ -> failwith "unexpected msg count") | _ -> failwith "unexpected parser state" -let%test_unit "basics" = - (* TODO: Test timing and cancellation. *) - Eio_main.run @@ fun env -> - Eio.Switch.run @@ fun sw -> - let fs = Eio.Stdenv.fs env in - let mgr = Eio.Stdenv.process_mgr env in - let docs = Docs.empty in - let du = Lsp.Types.DocumentUri.of_path "TimingExit0.tla" in - let dv = 1 in - let docs = Docs.add docs du dv "any\ncontent" in - let stream = Eio.Stream.create 10 in - let pr = create sw fs mgr stream docs in - let tlapm_locator () = - let cwd = Sys.getcwd () in - Ok (Filename.concat cwd "../test/tlapm_mock.sh") - in - let _docs = - match start_async pr du dv 3 7 ~tlapm_locator () with - | Ok docs -> docs - | Error e -> failwith e - in - () +let%test_module "Mocked TLAPM" = + (module struct + let test_case doc_name timeout assert_fun = + Eio_main.run @@ fun env -> + Eio.Switch.run @@ fun sw -> + let fs = Eio.Stdenv.fs env in + let mgr = Eio.Stdenv.process_mgr env in + let docs = Docs.empty in + let du = Lsp.Types.DocumentUri.of_path doc_name in + let dv = 1 in + let docs = Docs.add docs du dv "any\ncontent" in + let stream = Eio.Stream.create 10 in + let pr = create sw fs mgr stream docs in + let tlapm_locator () = + let cwd = Sys.getcwd () in + Ok (Filename.concat cwd "../test/tlapm_mock.sh") + in + let clock = Eio.Stdenv.clock env in + let ts_start = Eio.Time.now clock in + let pr = + match start_async pr du dv 3 7 ~tlapm_locator () with + | Ok pr -> pr + | Error e -> failwith e + in + let _pr = assert_fun pr clock stream in + let ts_end = Eio.Time.now clock in + let () = + match ts_end -. ts_start < timeout with + | true -> () + | false -> failwith "timeout expired" + in + () + + (* Check a document which outputs a warning then sleeps for 3s and then + outputs another. We will cancel it in 0.5s, only the first warning + should be received, and the overall time should be less than a second. *) + let%test_unit "Mocked: CancelTiming" = + test_case "CancelTiming.tla" 1.0 @@ fun pr clock stream -> + let () = Eio.Time.sleep clock 0.5 in + let _pr = cancel_all pr in + let () = + match Eio.Stream.length stream with + | 2 -> () + | l -> failwith (Format.sprintf "expected 2 events, got %d" l) + in + let () = + match Eio.Stream.take_nonblocking stream with + | Some (TlapmWarning { msg = "message before delay" }) -> () + | _ -> failwith "expected warning msg" + in + let () = + match Eio.Stream.take_nonblocking stream with + | Some TlapmTerminated -> () + | _ -> failwith "expected termination msg" + in + pr + + (* Check if abnormal tlapm termination don't cause any side effects. + We con't sleep or cancel a process here, just wait for expected messages. *) + let%test_unit "Mocked: AbnormalExit" = + test_case "AbnormalExit.tla" 1.0 @@ fun pr _clock stream -> + let () = + match Eio.Stream.take stream with + | TlapmWarning { msg = "this run is going to fail" } -> () + | _ -> failwith "expected warning msg" + in + let () = + match Eio.Stream.take stream with + | TlapmTerminated -> () + | _ -> failwith "expected termination msg" + in + pr + + (* Check if output of running tlapm on a document with no proofs works. *) + let%test_unit "Mocked: Empty" = + test_case "Empty.tla" 1.0 @@ fun pr _clock stream -> + let () = + match Eio.Stream.take stream with + | TlapmObligationsNumber 0 -> () + | _ -> failwith "expected 0 obligations" + in + let () = + match Eio.Stream.take stream with + | TlapmTerminated -> () + | _ -> failwith "expected termination msg" + in + pr + + (* Check if output of running tlapm on a document with some proofs works. *) + let%test_unit "Mocked: Some" = + test_case "Some.tla" 1.0 @@ fun pr _clock stream -> + let () = + match Eio.Stream.take stream with + | TlapmObligation { status = ToBeProved; _ } -> () + | _ -> failwith "expected obligation" + in + let () = + match Eio.Stream.take stream with + | TlapmObligationsNumber 1 -> () + | _ -> failwith "expected 1 obligations" + in + let () = + match Eio.Stream.take stream with + | TlapmObligation { status = Proved; _ } -> () + | _ -> failwith "expected obligation" + in + let () = + match Eio.Stream.take stream with + | TlapmTerminated -> () + | _ -> failwith "expected termination msg" + in + pr + end) diff --git a/lsp/lib/tlapm_lsp_prover.mli b/lsp/lib/tlapm_lsp_prover.mli index 0b4694a5..76f4e923 100644 --- a/lsp/lib/tlapm_lsp_prover.mli +++ b/lsp/lib/tlapm_lsp_prover.mli @@ -31,6 +31,7 @@ module ToolboxProtocol : sig already : bool option; obl : string option; } + | TlapmTerminated end val create : diff --git a/lsp/test/tlapm_mock.sh b/lsp/test/tlapm_mock.sh index 2f160a22..51b27bd1 100755 --- a/lsp/test/tlapm_mock.sh +++ b/lsp/test/tlapm_mock.sh @@ -9,25 +9,37 @@ if [ "$1" != "--toolbox" ] ; then exit 2 fi -# We differentiate the testcases by the last argument, which is usually a TLA file. -last_arg=${@: -1} -case "$last_arg" in - TimingExit0.tla) - echo Starting... - sleep 1; echo First proof done - sleep 1; echo Second proof fone - sleep 1; echo All proofs OK. - exit 0 - ;; - TimingExit1.tla) - echo Starting... - sleep 1; echo First proof done - sleep 1; echo Second proof fone - sleep 1; echo All proofs OK. - exit 1 - ;; - Empty.tla) - cat << EOF +################################################################################ +function CancelTiming() { +cat << EOF +@!!BEGIN +@!!type:warning +@!!msg:message before delay +@!!END +EOF +sleep 3 # NOTE: This. +cat << EOF +@!!BEGIN +@!!type:warning +@!!msg:message after delay +@!!END +EOF +} + +################################################################################ +function AbnormalExit() { +cat << EOF +@!!BEGIN +@!!type:warning +@!!msg:this run is going to fail +@!!END +EOF +exit 1 # NOTE: This. +} + +################################################################################ +function Empty() { +cat << EOF \* TLAPM version 1.5.0 \* launched at 2023-09-30 23:39:35 with command line: \* tlapm --toolbox 0 0 Empty.tla @@ -42,8 +54,10 @@ case "$last_arg" in File "./Empty.tla", line 1, character 1 to line 5, character 4: [INFO]: All 0 obligation proved. EOF - ;; - Some.tla) +} + +################################################################################ +function Some() { cat << EOF \* TLAPM version 1.5.0 \* launched at 2023-09-30 23:43:15 with command line: @@ -79,7 +93,16 @@ cat << EOF File "./Some.tla", line 1, character 1 to line 6, character 4: [INFO]: All 1 obligation proved. EOF - ;; +} + +################################################################################ +# We differentiate the testcases by the last argument, which is usually a TLA file. +last_arg=${@: -1} +case "$last_arg" in + CancelTiming.tla) CancelTiming ;; + AbnormalExit.tla) AbnormalExit ;; + Empty.tla) Empty ;; + Some.tla) Some ;; *) echo "ERROR: Unexpected testcase, last_arg=$last_arg." exit 2 From eeab4f084c5846742a8d9748c5ff69c4ab6c2ed8 Mon Sep 17 00:00:00 2001 From: Karolis Petrauskas Date: Sat, 7 Oct 2023 12:53:28 +0300 Subject: [PATCH 028/140] Support for reading a TLA file from STDIN. Signed-off-by: Karolis Petrauskas --- dune-project | 2 ++ src/dune | 2 ++ src/module.mli | 1 + src/module/m_save.ml | 14 ++++++++++++-- src/module/m_save.mli | 2 +- src/params.ml | 3 +++ src/params.mli | 1 + src/tlapm.t | 31 +++++++++++++++++++++++++++++++ src/tlapm_args.ml | 6 ++++++ src/tlapm_lib.ml | 12 ++++++++++-- 10 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 src/tlapm.t diff --git a/dune-project b/dune-project index 8ec6e3c1..99db86a8 100644 --- a/dune-project +++ b/dune-project @@ -10,6 +10,8 @@ (source (github tlaplus/tlapm)) +(cram enable) + (package (name tlapm) (synopsis "TLA+ Proof Manager") diff --git a/src/dune b/src/dune index 11c8cadb..304af4e4 100644 --- a/src/dune +++ b/src/dune @@ -27,3 +27,5 @@ (include_subdirs unqualified) +(cram + (deps %{bin:tlapm})) diff --git a/src/module.mli b/src/module.mli index 1eb66146..4aeb9a26 100644 --- a/src/module.mli +++ b/src/module.mli @@ -109,6 +109,7 @@ end module Save : sig open T + val use_stdin_prop: unit Property.pfuncs val parse_file : ?clock:Timing.clock -> Util.hint -> mule val store_module : ?clock:Timing.clock -> mule -> unit val complete_load : ?clock:Timing.clock -> ?root:string -> modctx -> modctx diff --git a/src/module/m_save.ml b/src/module/m_save.ml index 5953fe1f..a06b699e 100644 --- a/src/module/m_save.ml +++ b/src/module/m_save.ml @@ -28,7 +28,7 @@ let clocking cl fn x = fn x -let file_search fh = +let file_search' fh = if Filename.is_implicit fh.core then let rec scan = function | [] -> None @@ -43,6 +43,13 @@ let file_search fh = Some fh else None +let use_stdin_prop = Property.make "use_stdin" + +let file_search fh = + match Property.has fh use_stdin_prop with + | true -> Some fh + | false -> file_search' fh + let really_parse_file fn = match file_search fn with @@ -52,7 +59,10 @@ let really_parse_file fn = fn.core; failwith "Module.Parser.parse_file" | Some fn -> - let (flex, _) = Alexer.lex fn.core in + let (flex, _) = match Property.has fn use_stdin_prop with + | true -> Alexer.lex_channel fn.core Stdlib.stdin + | false -> Alexer.lex fn.core + in let hparse = use parse in match P.run hparse ~init:Tla_parser.init ~source:flex with | None -> diff --git a/src/module/m_save.mli b/src/module/m_save.mli index 8709517b..569cca55 100644 --- a/src/module/m_save.mli +++ b/src/module/m_save.mli @@ -4,7 +4,7 @@ Copyright (C) 2008-2010 INRIA and Microsoft Corporation *) open M_t - +val use_stdin_prop: unit Property.pfuncs val parse_file: ?clock:Timing.clock -> Util.hint -> mule val store_module: ?clock:Timing.clock -> mule -> unit val complete_load: diff --git a/src/params.ml b/src/params.ml index 483ee30a..48449d32 100644 --- a/src/params.ml +++ b/src/params.ml @@ -48,6 +48,9 @@ let safefp = ref false let wait = ref 3 (* Wait time before sending a "being proved" message to the toolbox. *) +let use_stdin = ref false +(* Read the document from stdin, if only one file is provided as an input. *) + let noproving = ref false (* Don't send any obligation to the back-ends. *) let printallobs = ref false diff --git a/src/params.mli b/src/params.mli index d125456c..d8e27b56 100644 --- a/src/params.mli +++ b/src/params.mli @@ -4,6 +4,7 @@ (* pars/error.ml *) val toolbox: bool ref +val use_stdin: bool ref (* expr/fmt.ml *) val debugging: string -> bool diff --git a/src/tlapm.t b/src/tlapm.t new file mode 100644 index 00000000..645e86d3 --- /dev/null +++ b/src/tlapm.t @@ -0,0 +1,31 @@ +Test the --stdin option + $ cat <&1 | grep -e '^@!!' | grep -v 'time-used') + > ---- MODULE A ---- + > THEOREM + > ASSUME + > NEW A, + > NEW B, + > A, + > A => B + > PROVE B + > OBVIOUS + > ==== + > EOF + @!!BEGIN + @!!type:obligation + @!!id:1 + @!!loc:9:3:9:10 + @!!status:to be proved + @!!END + @!!BEGIN + @!!type:obligationsnumber + @!!count:1 + @!!END + @!!BEGIN + @!!type:obligation + @!!id:1 + @!!loc:9:3:9:10 + @!!status:proved + @!!prover:smt + @!!already:false + @!!END diff --git a/src/tlapm_args.ml b/src/tlapm_args.ml index 156f32a9..61706083 100644 --- a/src/tlapm_args.ml +++ b/src/tlapm_args.ml @@ -185,6 +185,9 @@ let init () = " line to prove"; "--wait", Arg.Set_int wait, "