mirror of
https://github.com/c-cube/linol.git
synced 2025-12-06 11:15:46 -05:00
autoformat
This commit is contained in:
parent
341b9919dc
commit
e9cc94dc14
12 changed files with 409 additions and 411 deletions
|
|
@ -2,13 +2,12 @@
|
||||||
(name main)
|
(name main)
|
||||||
(libraries
|
(libraries
|
||||||
; Deps on linol + LWT backend
|
; Deps on linol + LWT backend
|
||||||
linol linol-lwt
|
linol
|
||||||
|
linol-lwt
|
||||||
; Types from the lsp library are exposed by the linol libs,
|
; Types from the lsp library are exposed by the linol libs,
|
||||||
; and thus almost guaranteed to be used by code using linol;
|
; and thus almost guaranteed to be used by code using linol;
|
||||||
; it is thus better to explicitly list lsp as a dep rather
|
; it is thus better to explicitly list lsp as a dep rather
|
||||||
; than rely on its inclusion as a transitive dep of linol
|
; than rely on its inclusion as a transitive dep of linol
|
||||||
; since it would for instance generate errors if the
|
; since it would for instance generate errors if the
|
||||||
; implicit-transitive-deps option of dune is set to false
|
; implicit-transitive-deps option of dune is set to false
|
||||||
lsp
|
lsp))
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,10 @@ type state_after_processing = unit
|
||||||
let process_some_input_file (_file_contents : string) : state_after_processing =
|
let process_some_input_file (_file_contents : string) : state_after_processing =
|
||||||
()
|
()
|
||||||
|
|
||||||
let diagnostics (_state : state_after_processing) : Lsp.Types.Diagnostic.t list =
|
let diagnostics (_state : state_after_processing) : Lsp.Types.Diagnostic.t list
|
||||||
|
=
|
||||||
[]
|
[]
|
||||||
|
|
||||||
|
|
||||||
(* Lsp server class
|
(* Lsp server class
|
||||||
|
|
||||||
This is the main point of interaction beetween the code checking documents
|
This is the main point of interaction beetween the code checking documents
|
||||||
|
|
@ -40,16 +40,15 @@ class lsp_server =
|
||||||
inherit Linol_lwt.Jsonrpc2.server
|
inherit Linol_lwt.Jsonrpc2.server
|
||||||
|
|
||||||
(* one env per document *)
|
(* one env per document *)
|
||||||
val buffers: (Lsp.Types.DocumentUri.t, state_after_processing) Hashtbl.t
|
val buffers : (Lsp.Types.DocumentUri.t, state_after_processing) Hashtbl.t =
|
||||||
= Hashtbl.create 32
|
Hashtbl.create 32
|
||||||
|
|
||||||
(* We define here a helper method that will:
|
(* We define here a helper method that will:
|
||||||
- process a document
|
- process a document
|
||||||
- store the state resulting from the processing
|
- store the state resulting from the processing
|
||||||
- return the diagnostics from the new state
|
- return the diagnostics from the new state
|
||||||
*)
|
*)
|
||||||
method private _on_doc
|
method private _on_doc ~(notify_back : Linol_lwt.Jsonrpc2.notify_back)
|
||||||
~(notify_back:Linol_lwt.Jsonrpc2.notify_back)
|
|
||||||
(uri : Lsp.Types.DocumentUri.t) (contents : string) =
|
(uri : Lsp.Types.DocumentUri.t) (contents : string) =
|
||||||
let new_state = process_some_input_file contents in
|
let new_state = process_some_input_file contents in
|
||||||
Hashtbl.replace buffers uri new_state;
|
Hashtbl.replace buffers uri new_state;
|
||||||
|
|
@ -63,7 +62,8 @@ class lsp_server =
|
||||||
|
|
||||||
(* Similarly, we also override the [on_notify_doc_did_change] method that will be called
|
(* Similarly, we also override the [on_notify_doc_did_change] method that will be called
|
||||||
by the server each time a new document is opened. *)
|
by the server each time a new document is opened. *)
|
||||||
method on_notif_doc_did_change ~notify_back d _c ~old_content:_old ~new_content =
|
method on_notif_doc_did_change ~notify_back d _c ~old_content:_old
|
||||||
|
~new_content =
|
||||||
self#_on_doc ~notify_back d.uri new_content
|
self#_on_doc ~notify_back d.uri new_content
|
||||||
|
|
||||||
(* On document closes, we remove the state associated to the file from the global
|
(* On document closes, we remove the state associated to the file from the global
|
||||||
|
|
@ -71,7 +71,6 @@ class lsp_server =
|
||||||
method on_notif_doc_did_close ~notify_back:_ d : unit Linol_lwt.t =
|
method on_notif_doc_did_close ~notify_back:_ d : unit Linol_lwt.t =
|
||||||
Hashtbl.remove buffers d.uri;
|
Hashtbl.remove buffers d.uri;
|
||||||
Linol_lwt.return ()
|
Linol_lwt.return ()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
(* Main code
|
(* Main code
|
||||||
|
|
@ -90,4 +89,3 @@ let run () =
|
||||||
|
|
||||||
(* Finally, we actually run the server *)
|
(* Finally, we actually run the server *)
|
||||||
let () = run ()
|
let () = run ()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
type 'a t = 'a
|
type 'a t = 'a
|
||||||
type nonrec in_channel = in_channel
|
type nonrec in_channel = in_channel
|
||||||
type nonrec out_channel = out_channel
|
type nonrec out_channel = out_channel
|
||||||
|
|
@ -7,10 +6,8 @@ let (let+) x f = f x
|
||||||
let ( let* ) x f = f x
|
let ( let* ) x f = f x
|
||||||
let ( and+ ) a b = a, b
|
let ( and+ ) a b = a, b
|
||||||
let return x = x
|
let return x = x
|
||||||
|
|
||||||
let failwith = failwith
|
let failwith = failwith
|
||||||
let fail = raise
|
let fail = raise
|
||||||
|
|
||||||
let stdin = stdin
|
let stdin = stdin
|
||||||
let stdout = stdout
|
let stdout = stdout
|
||||||
|
|
||||||
|
|
@ -18,21 +15,16 @@ let default_spawn_ f =
|
||||||
let run () =
|
let run () =
|
||||||
try f ()
|
try f ()
|
||||||
with e ->
|
with e ->
|
||||||
Log.err (fun k->k
|
Log.err (fun k ->
|
||||||
"uncaught exception in `spawn`:\n%s\n%!"
|
k "uncaught exception in `spawn`:\n%s\n%!" (Printexc.to_string e));
|
||||||
(Printexc.to_string e));
|
|
||||||
raise e
|
raise e
|
||||||
in
|
in
|
||||||
ignore (Thread.create run ())
|
ignore (Thread.create run ())
|
||||||
|
|
||||||
let spawn_ref_ = ref default_spawn_
|
let spawn_ref_ = ref default_spawn_
|
||||||
|
|
||||||
let set_spawn_function f = spawn_ref_ := f
|
let set_spawn_function f = spawn_ref_ := f
|
||||||
let spawn f = !spawn_ref_ f
|
let spawn f = !spawn_ref_ f
|
||||||
|
let catch f g = try f () with e -> g e
|
||||||
let catch f g =
|
|
||||||
try f()
|
|
||||||
with e -> g e
|
|
||||||
|
|
||||||
let rec read ic buf i len =
|
let rec read ic buf i len =
|
||||||
if len > 0 then (
|
if len > 0 then (
|
||||||
|
|
@ -43,6 +35,9 @@ let rec read ic buf i len =
|
||||||
let read_line = input_line
|
let read_line = input_line
|
||||||
|
|
||||||
let write oc b i len =
|
let write oc b i len =
|
||||||
output oc b i len; flush oc
|
output oc b i len;
|
||||||
|
flush oc
|
||||||
|
|
||||||
let write_string oc s =
|
let write_string oc s =
|
||||||
output_string oc s; flush oc
|
output_string oc s;
|
||||||
|
flush oc
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
|
|
||||||
(** {1 Blocking IO with a new thread for each [spawn]} *)
|
(** {1 Blocking IO with a new thread for each [spawn]} *)
|
||||||
|
|
||||||
include Sigs.IO with type 'a t = 'a
|
include
|
||||||
|
Sigs.IO
|
||||||
|
with type 'a t = 'a
|
||||||
and type in_channel = in_channel
|
and type in_channel = in_channel
|
||||||
and type out_channel = out_channel
|
and type out_channel = out_channel
|
||||||
|
|
||||||
|
|
|
||||||
1
src/dune
1
src/dune
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
(library
|
(library
|
||||||
(name linol)
|
(name linol)
|
||||||
(public_name linol)
|
(public_name linol)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
type json = Yojson.Safe.t
|
type json = Yojson.Safe.t
|
||||||
|
|
||||||
module type IO = Sigs.IO
|
module type IO = Sigs.IO
|
||||||
|
|
@ -12,22 +10,15 @@ module type S = sig
|
||||||
|
|
||||||
include module type of Server.Make (IO)
|
include module type of Server.Make (IO)
|
||||||
|
|
||||||
val create :
|
val create : ic:IO.in_channel -> oc:IO.out_channel -> server -> t
|
||||||
ic:IO.in_channel ->
|
|
||||||
oc:IO.out_channel ->
|
|
||||||
server ->
|
|
||||||
t
|
|
||||||
(** Create a connection from the pair of channels *)
|
(** Create a connection from the pair of channels *)
|
||||||
|
|
||||||
val create_stdio : server -> t
|
val create_stdio : server -> t
|
||||||
(** Create a connection using stdin/stdout *)
|
(** Create a connection using stdin/stdout *)
|
||||||
|
|
||||||
val run :
|
val run : ?shutdown:(unit -> bool) -> t -> unit IO.t
|
||||||
?shutdown:(unit -> bool) ->
|
|
||||||
t -> unit IO.t
|
|
||||||
(** Listen for incoming messages and responses.
|
(** Listen for incoming messages and responses.
|
||||||
@param shutdown if true, tells the server to shut down *)
|
@param shutdown if true, tells the server to shut down *)
|
||||||
end
|
end
|
||||||
|
|
||||||
module Make (IO : IO) : S with module IO = IO
|
module Make (IO : IO) : S with module IO = IO
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
|
|
||||||
(** {1 Linol}
|
(** {1 Linol}
|
||||||
|
|
||||||
Abstraction over The "Lsp" library, to make it easier to develop
|
Abstraction over The "Lsp" library, to make it easier to develop
|
||||||
LSP servers in OCaml (but not necessarily {b for} OCaml). *)
|
LSP servers in OCaml (but not necessarily {b for} OCaml). *)
|
||||||
|
|
||||||
module type IO = Sigs.IO
|
module type IO = Sigs.IO
|
||||||
|
|
||||||
module Jsonrpc2 = Jsonrpc2
|
module Jsonrpc2 = Jsonrpc2
|
||||||
module Server = Server
|
module Server = Server
|
||||||
module Blocking_IO = Blocking_IO
|
module Blocking_IO = Blocking_IO
|
||||||
module Log = Log
|
module Log = Log
|
||||||
|
|
||||||
module Make = Jsonrpc2.Make
|
module Make = Jsonrpc2.Make
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1 @@
|
||||||
|
|
||||||
include (val Logs.src_log (Logs.Src.create ~doc:"linol (LSP library)" "linol"))
|
include (val Logs.src_log (Logs.Src.create ~doc:"linol (LSP library)" "linol"))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
(library
|
(library
|
||||||
(name linol_lwt)
|
(name linol_lwt)
|
||||||
(public_name linol-lwt)
|
(public_name linol-lwt)
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,22 @@
|
||||||
|
|
||||||
module type IO = Linol.IO
|
module type IO = Linol.IO
|
||||||
|
|
||||||
module IO_lwt
|
module IO_lwt :
|
||||||
: IO with type 'a t = 'a Lwt.t
|
IO
|
||||||
|
with type 'a t = 'a Lwt.t
|
||||||
and type in_channel = Lwt_io.input Lwt_io.channel
|
and type in_channel = Lwt_io.input Lwt_io.channel
|
||||||
and type out_channel = Lwt_io.output Lwt_io.channel
|
and type out_channel = Lwt_io.output Lwt_io.channel = struct
|
||||||
= struct
|
|
||||||
type 'a t = 'a Lwt.t
|
type 'a t = 'a Lwt.t
|
||||||
|
|
||||||
let ( let+ ) = Lwt.( >|= )
|
let ( let+ ) = Lwt.( >|= )
|
||||||
let ( let* ) = Lwt.( >>= )
|
let ( let* ) = Lwt.( >>= )
|
||||||
|
|
||||||
let ( and+ ) a b =
|
let ( and+ ) a b =
|
||||||
let open Lwt in
|
let open Lwt in
|
||||||
a >>= fun x -> b >|= fun y -> x,y
|
a >>= fun x ->
|
||||||
|
b >|= fun y -> x, y
|
||||||
|
|
||||||
let return = Lwt.return
|
let return = Lwt.return
|
||||||
let failwith = Lwt.fail_with
|
let failwith = Lwt.fail_with
|
||||||
|
|
||||||
let stdin = Lwt_io.stdin
|
let stdin = Lwt_io.stdin
|
||||||
let stdout = Lwt_io.stdout
|
let stdout = Lwt_io.stdout
|
||||||
|
|
||||||
|
|
@ -25,15 +27,12 @@ module IO_lwt
|
||||||
let write = Lwt_io.write_from_exactly
|
let write = Lwt_io.write_from_exactly
|
||||||
let read = Lwt_io.read_into_exactly
|
let read = Lwt_io.read_into_exactly
|
||||||
let read_line = Lwt_io.read_line
|
let read_line = Lwt_io.read_line
|
||||||
|
|
||||||
let catch = Lwt.catch
|
let catch = Lwt.catch
|
||||||
let fail = Lwt.fail
|
let fail = Lwt.fail
|
||||||
|
|
||||||
let spawn f =
|
let spawn f =
|
||||||
Lwt.async
|
Lwt.async (fun () ->
|
||||||
(fun () ->
|
Lwt.catch f (fun exn ->
|
||||||
Lwt.catch f
|
|
||||||
(fun exn ->
|
|
||||||
Printf.eprintf "uncaught exception in `spawn`:\n%s\n%!"
|
Printf.eprintf "uncaught exception in `spawn`:\n%s\n%!"
|
||||||
(Printexc.to_string exn);
|
(Printexc.to_string exn);
|
||||||
Lwt.return ()))
|
Lwt.return ()))
|
||||||
|
|
@ -41,6 +40,7 @@ end
|
||||||
|
|
||||||
include Lsp.Types
|
include Lsp.Types
|
||||||
include IO_lwt
|
include IO_lwt
|
||||||
|
|
||||||
type doc_state = Linol.Server.doc_state
|
type doc_state = Linol.Server.doc_state
|
||||||
|
|
||||||
module Jsonrpc2 = Linol.Jsonrpc2.Make (IO_lwt)
|
module Jsonrpc2 = Linol.Jsonrpc2.Make (IO_lwt)
|
||||||
|
|
|
||||||
351
src/server.ml
351
src/server.ml
|
|
@ -1,13 +1,12 @@
|
||||||
|
|
||||||
open Sigs
|
open Sigs
|
||||||
|
|
||||||
(** Current state of a document. *)
|
|
||||||
type nonrec doc_state = {
|
type nonrec doc_state = {
|
||||||
uri: Lsp.Types.DocumentUri.t;
|
uri: Lsp.Types.DocumentUri.t;
|
||||||
languageId: string;
|
languageId: string;
|
||||||
version: int;
|
version: int;
|
||||||
content: string;
|
content: string;
|
||||||
}
|
}
|
||||||
|
(** Current state of a document. *)
|
||||||
|
|
||||||
(** {2 Request ID}
|
(** {2 Request ID}
|
||||||
|
|
||||||
|
|
@ -24,7 +23,6 @@ end
|
||||||
(** {2 Server interface for some IO substrate} *)
|
(** {2 Server interface for some IO substrate} *)
|
||||||
module Make (IO : IO) = struct
|
module Make (IO : IO) = struct
|
||||||
open Lsp.Types
|
open Lsp.Types
|
||||||
|
|
||||||
module Position = Position
|
module Position = Position
|
||||||
module Range = Range
|
module Range = Range
|
||||||
module Diagnostic = Diagnostic
|
module Diagnostic = Diagnostic
|
||||||
|
|
@ -32,13 +30,15 @@ module Make(IO : IO) = struct
|
||||||
module Req_id = Req_id
|
module Req_id = Req_id
|
||||||
|
|
||||||
(** The server baseclass *)
|
(** The server baseclass *)
|
||||||
class virtual base_server = object
|
class virtual base_server =
|
||||||
method virtual on_notification :
|
object
|
||||||
notify_back:(Lsp.Server_notification.t -> unit IO.t) ->
|
method virtual on_notification
|
||||||
|
: notify_back:(Lsp.Server_notification.t -> unit IO.t) ->
|
||||||
Lsp.Client_notification.t ->
|
Lsp.Client_notification.t ->
|
||||||
unit IO.t
|
unit IO.t
|
||||||
|
|
||||||
method virtual on_request : 'a.
|
method virtual on_request
|
||||||
|
: 'a.
|
||||||
notify_back:(Lsp.Server_notification.t -> unit IO.t) ->
|
notify_back:(Lsp.Server_notification.t -> unit IO.t) ->
|
||||||
id:Req_id.t ->
|
id:Req_id.t ->
|
||||||
'a Lsp.Client_request.t ->
|
'a Lsp.Client_request.t ->
|
||||||
|
|
@ -48,72 +48,75 @@ module Make(IO : IO) = struct
|
||||||
messages, diagnostics, etc.
|
messages, diagnostics, etc.
|
||||||
@param id the query RPC ID, can be used for tracing, cancellation, etc. *)
|
@param id the query RPC ID, can be used for tracing, cancellation, etc. *)
|
||||||
|
|
||||||
(** Set to true if the client requested to exit *)
|
|
||||||
method must_quit = false
|
method must_quit = false
|
||||||
|
(** Set to true if the client requested to exit *)
|
||||||
end
|
end
|
||||||
|
|
||||||
(** A wrapper to more easily reply to notifications *)
|
(** A wrapper to more easily reply to notifications *)
|
||||||
class notify_back ~notify_back ?version ?(uri:DocumentUri.t option) () = object
|
class notify_back ~notify_back ?version ?(uri : DocumentUri.t option) () =
|
||||||
|
object
|
||||||
val mutable uri = uri
|
val mutable uri = uri
|
||||||
method set_uri u = uri <- Some u
|
method set_uri u = uri <- Some u
|
||||||
|
|
||||||
(** Send a log message to the editor *)
|
|
||||||
method send_log_msg ~type_ msg : unit IO.t =
|
method send_log_msg ~type_ msg : unit IO.t =
|
||||||
let params = LogMessageParams.create ~type_ ~message:msg in
|
let params = LogMessageParams.create ~type_ ~message:msg in
|
||||||
notify_back (Lsp.Server_notification.LogMessage params)
|
notify_back (Lsp.Server_notification.LogMessage params)
|
||||||
|
(** Send a log message to the editor *)
|
||||||
|
|
||||||
(** Send diagnostics for the current document *)
|
|
||||||
method send_diagnostic (l : Diagnostic.t list) : unit IO.t =
|
method send_diagnostic (l : Diagnostic.t list) : unit IO.t =
|
||||||
match uri with
|
match uri with
|
||||||
| None -> IO.failwith "notify_back: cannot publish diagnostics, no URI given"
|
| None ->
|
||||||
|
IO.failwith "notify_back: cannot publish diagnostics, no URI given"
|
||||||
| Some uri ->
|
| Some uri ->
|
||||||
let params = PublishDiagnosticsParams.create
|
let params =
|
||||||
~uri ?version ~diagnostics:l () in
|
PublishDiagnosticsParams.create ~uri ?version ~diagnostics:l ()
|
||||||
|
in
|
||||||
notify_back (Lsp.Server_notification.PublishDiagnostics params)
|
notify_back (Lsp.Server_notification.PublishDiagnostics params)
|
||||||
|
(** Send diagnostics for the current document *)
|
||||||
|
|
||||||
|
method send_notification (n : Lsp.Server_notification.t) = notify_back n
|
||||||
(** Send a notification (general purpose method) *)
|
(** Send a notification (general purpose method) *)
|
||||||
method send_notification (n:Lsp.Server_notification.t) =
|
|
||||||
notify_back n
|
|
||||||
end
|
end
|
||||||
|
|
||||||
(** Current state of a document. *)
|
|
||||||
type nonrec doc_state = doc_state = {
|
type nonrec doc_state = doc_state = {
|
||||||
uri: DocumentUri.t;
|
uri: DocumentUri.t;
|
||||||
languageId: string;
|
languageId: string;
|
||||||
version: int;
|
version: int;
|
||||||
content: string;
|
content: string;
|
||||||
}
|
}
|
||||||
|
(** Current state of a document. *)
|
||||||
|
|
||||||
(** An easily overloadable class. Pick the methods you want to support.
|
(** An easily overloadable class. Pick the methods you want to support.
|
||||||
The user must provide at least the callbacks for document lifecycle:
|
The user must provide at least the callbacks for document lifecycle:
|
||||||
open, close, update. The most basic LSP server should check documents
|
open, close, update. The most basic LSP server should check documents
|
||||||
when they're updated and report diagnostics back to the editor. *)
|
when they're updated and report diagnostics back to the editor. *)
|
||||||
class virtual server = object(self)
|
class virtual server =
|
||||||
|
object (self)
|
||||||
inherit base_server
|
inherit base_server
|
||||||
val mutable _quit = false
|
val mutable _quit = false
|
||||||
val docs : (DocumentUri.t, doc_state) Hashtbl.t = Hashtbl.create 16
|
val docs : (DocumentUri.t, doc_state) Hashtbl.t = Hashtbl.create 16
|
||||||
|
|
||||||
method! must_quit = _quit
|
method! must_quit = _quit
|
||||||
|
|
||||||
(** Find current state of the given document, if present. *)
|
|
||||||
method find_doc (uri : DocumentUri.t) : doc_state option =
|
method find_doc (uri : DocumentUri.t) : doc_state option =
|
||||||
try Some (Hashtbl.find docs uri)
|
try Some (Hashtbl.find docs uri) with Not_found -> None
|
||||||
with Not_found -> None
|
(** Find current state of the given document, if present. *)
|
||||||
|
|
||||||
(** Override to process other requests *)
|
method on_request_unhandled : type r.
|
||||||
method on_request_unhandled
|
notify_back:notify_back ->
|
||||||
: type r. notify_back:notify_back ->
|
id:Req_id.t ->
|
||||||
id:Req_id.t -> r Lsp.Client_request.t -> r IO.t
|
r Lsp.Client_request.t ->
|
||||||
= fun ~notify_back:_ ~id:_ _r ->
|
r IO.t =
|
||||||
|
fun ~notify_back:_ ~id:_ _r ->
|
||||||
Log.debug (fun k -> k "req: unhandled request");
|
Log.debug (fun k -> k "req: unhandled request");
|
||||||
IO.failwith "TODO: handle this request"
|
IO.failwith "TODO: handle this request"
|
||||||
|
(** Override to process other requests *)
|
||||||
|
|
||||||
(** Parameter for how to synchronize content with the editor *)
|
|
||||||
method config_sync_opts : TextDocumentSyncOptions.t =
|
method config_sync_opts : TextDocumentSyncOptions.t =
|
||||||
TextDocumentSyncOptions.create
|
TextDocumentSyncOptions.create ~change:TextDocumentSyncKind.Incremental
|
||||||
~change:TextDocumentSyncKind.Incremental ~openClose:true
|
~openClose:true
|
||||||
~save:(`SaveOptions (SaveOptions.create ~includeText:false ()))
|
~save:(`SaveOptions (SaveOptions.create ~includeText:false ()))
|
||||||
~willSave:false ()
|
~willSave:false ()
|
||||||
|
(** Parameter for how to synchronize content with the editor *)
|
||||||
|
|
||||||
method config_completion : CompletionOptions.t option = None
|
method config_completion : CompletionOptions.t option = None
|
||||||
(** Configuration for the completion API.
|
(** Configuration for the completion API.
|
||||||
|
|
@ -122,39 +125,50 @@ module Make(IO : IO) = struct
|
||||||
method config_code_lens_options : CodeLensOptions.t option = None
|
method config_code_lens_options : CodeLensOptions.t option = None
|
||||||
(** @since 0.3 *)
|
(** @since 0.3 *)
|
||||||
|
|
||||||
method config_definition :
|
method config_definition
|
||||||
[`Bool of bool | `DefinitionOptions of DefinitionOptions.t ] option = None
|
: [ `Bool of bool | `DefinitionOptions of DefinitionOptions.t ] option
|
||||||
|
=
|
||||||
|
None
|
||||||
(** @since 0.3 *)
|
(** @since 0.3 *)
|
||||||
|
|
||||||
method config_hover :
|
method config_hover
|
||||||
[`Bool of bool | `HoverOptions of HoverOptions.t ] option = None
|
: [ `Bool of bool | `HoverOptions of HoverOptions.t ] option =
|
||||||
|
None
|
||||||
(** @since 0.3 *)
|
(** @since 0.3 *)
|
||||||
|
|
||||||
method config_symbol :
|
method config_symbol
|
||||||
[`Bool of bool | `DocumentSymbolOptions of DocumentSymbolOptions.t ] option = None
|
: [ `Bool of bool
|
||||||
|
| `DocumentSymbolOptions of DocumentSymbolOptions.t
|
||||||
|
]
|
||||||
|
option =
|
||||||
|
None
|
||||||
(** @since 0.3 *)
|
(** @since 0.3 *)
|
||||||
|
|
||||||
method config_code_action_provider :
|
method config_code_action_provider
|
||||||
[`CodeActionOptions of CodeActionOptions.t | `Bool of bool] = `Bool false
|
: [ `CodeActionOptions of CodeActionOptions.t | `Bool of bool ] =
|
||||||
|
`Bool false
|
||||||
(** @since 0.3 *)
|
(** @since 0.3 *)
|
||||||
|
|
||||||
|
method config_modify_capabilities (c : ServerCapabilities.t)
|
||||||
|
: ServerCapabilities.t =
|
||||||
|
c
|
||||||
(** Modify capabilities before sending them back to the client.
|
(** Modify capabilities before sending them back to the client.
|
||||||
By default we just return them unmodified.
|
By default we just return them unmodified.
|
||||||
@since 0.3 *)
|
@since 0.3 *)
|
||||||
method config_modify_capabilities (c:ServerCapabilities.t) : ServerCapabilities.t = c
|
|
||||||
|
|
||||||
(** List of commands available *)
|
|
||||||
method config_list_commands : string list = []
|
method config_list_commands : string list = []
|
||||||
|
(** List of commands available *)
|
||||||
|
|
||||||
method on_req_initialize ~notify_back:_
|
method on_req_initialize ~notify_back:_ (_i : InitializeParams.t)
|
||||||
(_i:InitializeParams.t) : InitializeResult.t IO.t =
|
: InitializeResult.t IO.t =
|
||||||
let sync_opts = self#config_sync_opts in
|
let sync_opts = self#config_sync_opts in
|
||||||
let capabilities =
|
let capabilities =
|
||||||
ServerCapabilities.create
|
ServerCapabilities.create
|
||||||
?codeLensProvider:self#config_code_lens_options
|
?codeLensProvider:self#config_code_lens_options
|
||||||
~codeActionProvider:self#config_code_action_provider
|
~codeActionProvider:self#config_code_action_provider
|
||||||
~executeCommandProvider:(ExecuteCommandOptions.create
|
~executeCommandProvider:
|
||||||
~commands:self#config_list_commands ())
|
(ExecuteCommandOptions.create ~commands:self#config_list_commands
|
||||||
|
())
|
||||||
?completionProvider:self#config_completion
|
?completionProvider:self#config_completion
|
||||||
?definitionProvider:self#config_definition
|
?definitionProvider:self#config_definition
|
||||||
?hoverProvider:self#config_hover
|
?hoverProvider:self#config_hover
|
||||||
|
|
@ -164,143 +178,145 @@ module Make(IO : IO) = struct
|
||||||
in
|
in
|
||||||
IO.return @@ InitializeResult.create ~capabilities ()
|
IO.return @@ InitializeResult.create ~capabilities ()
|
||||||
|
|
||||||
(** Called when the user hovers on some identifier in the document *)
|
|
||||||
method on_req_hover ~notify_back:_ ~id:_ ~uri:_ ~pos:_ ~workDoneToken:_
|
method on_req_hover ~notify_back:_ ~id:_ ~uri:_ ~pos:_ ~workDoneToken:_
|
||||||
(_ : doc_state) : Hover.t option IO.t =
|
(_ : doc_state) : Hover.t option IO.t =
|
||||||
IO.return None
|
IO.return None
|
||||||
|
(** Called when the user hovers on some identifier in the document *)
|
||||||
|
|
||||||
(** Called when the user requests completion in the document *)
|
|
||||||
method on_req_completion ~notify_back:_ ~id:_ ~uri:_ ~pos:_ ~ctx:_
|
method on_req_completion ~notify_back:_ ~id:_ ~uri:_ ~pos:_ ~ctx:_
|
||||||
~workDoneToken:_ ~partialResultToken:_
|
~workDoneToken:_ ~partialResultToken:_ (_ : doc_state)
|
||||||
(_ : doc_state) :
|
: [ `CompletionList of CompletionList.t
|
||||||
[ `CompletionList of CompletionList.t
|
| `List of CompletionItem.t list
|
||||||
| `List of CompletionItem.t list ] option IO.t =
|
]
|
||||||
|
option
|
||||||
|
IO.t =
|
||||||
IO.return None
|
IO.return None
|
||||||
|
(** Called when the user requests completion in the document *)
|
||||||
|
|
||||||
(** Called when the user wants to jump-to-definition *)
|
|
||||||
method on_req_definition ~notify_back:_ ~id:_ ~uri:_ ~pos:_
|
method on_req_definition ~notify_back:_ ~id:_ ~uri:_ ~pos:_
|
||||||
~workDoneToken:_ ~partialResultToken:_
|
~workDoneToken:_ ~partialResultToken:_ (_ : doc_state)
|
||||||
(_ : doc_state) : Locations.t option IO.t =
|
: Locations.t option IO.t =
|
||||||
IO.return None
|
IO.return None
|
||||||
|
(** Called when the user wants to jump-to-definition *)
|
||||||
|
|
||||||
|
method on_req_code_lens ~notify_back:_ ~id:_ ~uri:_ ~workDoneToken:_
|
||||||
|
~partialResultToken:_ (_ : doc_state) : CodeLens.t list IO.t =
|
||||||
|
IO.return []
|
||||||
(** List code lenses for the given document
|
(** List code lenses for the given document
|
||||||
@since 0.3 *)
|
@since 0.3 *)
|
||||||
method on_req_code_lens ~notify_back:_ ~id:_ ~uri:_
|
|
||||||
~workDoneToken:_ ~partialResultToken:_
|
|
||||||
(_ : doc_state) : CodeLens.t list IO.t =
|
|
||||||
IO.return []
|
|
||||||
|
|
||||||
(** Code lens resolution, must return a code lens with non null "command"
|
method on_req_code_lens_resolve ~notify_back:(_ : notify_back) ~id:_
|
||||||
@since 0.3 *)
|
|
||||||
method on_req_code_lens_resolve
|
|
||||||
~notify_back:(_:notify_back) ~id:_
|
|
||||||
(cl : CodeLens.t) : CodeLens.t IO.t =
|
(cl : CodeLens.t) : CodeLens.t IO.t =
|
||||||
IO.return cl
|
IO.return cl
|
||||||
|
(** Code lens resolution, must return a code lens with non null "command"
|
||||||
|
@since 0.3 *)
|
||||||
|
|
||||||
|
method on_req_code_action ~notify_back:(_ : notify_back) ~id:_
|
||||||
|
(_c : CodeActionParams.t) : CodeActionResult.t IO.t =
|
||||||
|
IO.return None
|
||||||
(** Code action.
|
(** Code action.
|
||||||
@since 0.3 *)
|
@since 0.3 *)
|
||||||
method on_req_code_action ~notify_back:(_:notify_back) ~id:_
|
|
||||||
(_c:CodeActionParams.t)
|
|
||||||
: CodeActionResult.t IO.t =
|
|
||||||
IO.return None
|
|
||||||
|
|
||||||
|
method on_req_execute_command ~notify_back:_ ~id:_ ~workDoneToken:_
|
||||||
|
(_c : string) (_args : Yojson.Safe.t list option) : Yojson.Safe.t IO.t
|
||||||
|
=
|
||||||
|
IO.return `Null
|
||||||
(** Execute a command with given arguments.
|
(** Execute a command with given arguments.
|
||||||
@since 0.3 *)
|
@since 0.3 *)
|
||||||
method on_req_execute_command ~notify_back:_ ~id:_ ~workDoneToken:_
|
|
||||||
(_c:string) (_args:Yojson.Safe.t list option) : Yojson.Safe.t IO.t =
|
|
||||||
IO.return `Null
|
|
||||||
|
|
||||||
|
method on_req_symbol ~notify_back:_ ~id:_ ~uri:_ ~workDoneToken:_
|
||||||
|
~partialResultToken:_ ()
|
||||||
|
: [ `DocumentSymbol of DocumentSymbol.t list
|
||||||
|
| `SymbolInformation of SymbolInformation.t list
|
||||||
|
]
|
||||||
|
option
|
||||||
|
IO.t =
|
||||||
|
IO.return None
|
||||||
(** List symbols in this document.
|
(** List symbols in this document.
|
||||||
@since 0.3 *)
|
@since 0.3 *)
|
||||||
method on_req_symbol ~notify_back:_ ~id:_ ~uri:_
|
|
||||||
~workDoneToken:_ ~partialResultToken:_
|
|
||||||
() : [ `DocumentSymbol of DocumentSymbol.t list
|
|
||||||
| `SymbolInformation of SymbolInformation.t list ] option IO.t =
|
|
||||||
IO.return None
|
|
||||||
|
|
||||||
method on_request
|
method on_request : type r.
|
||||||
: type r. notify_back:_ -> id:Req_id.t -> r Lsp.Client_request.t -> r IO.t
|
notify_back:_ -> id:Req_id.t -> r Lsp.Client_request.t -> r IO.t =
|
||||||
= fun ~notify_back ~id (r:_ Lsp.Client_request.t) ->
|
fun ~notify_back ~id (r : _ Lsp.Client_request.t) ->
|
||||||
Log.debug (fun k->k "handle request[id=%s] <opaque>" (Req_id.to_string id));
|
Log.debug (fun k ->
|
||||||
|
k "handle request[id=%s] <opaque>" (Req_id.to_string id));
|
||||||
|
|
||||||
begin match r with
|
match r with
|
||||||
| Lsp.Client_request.Shutdown ->
|
| Lsp.Client_request.Shutdown ->
|
||||||
Log.info (fun k -> k "shutdown");
|
Log.info (fun k -> k "shutdown");
|
||||||
_quit <- true; IO.return ()
|
_quit <- true;
|
||||||
|
IO.return ()
|
||||||
| Lsp.Client_request.Initialize i ->
|
| Lsp.Client_request.Initialize i ->
|
||||||
Log.debug (fun k -> k "req: initialize");
|
Log.debug (fun k -> k "req: initialize");
|
||||||
let notify_back = new notify_back ~notify_back () in
|
let notify_back = new notify_back ~notify_back () in
|
||||||
self#on_req_initialize ~notify_back i
|
self#on_req_initialize ~notify_back i
|
||||||
|
| Lsp.Client_request.TextDocumentHover
|
||||||
| Lsp.Client_request.TextDocumentHover { textDocument; position; workDoneToken } ->
|
{ textDocument; position; workDoneToken } ->
|
||||||
let uri = textDocument.uri in
|
let uri = textDocument.uri in
|
||||||
Log.debug (fun k -> k "req: hover '%s'" (DocumentUri.to_path uri));
|
Log.debug (fun k -> k "req: hover '%s'" (DocumentUri.to_path uri));
|
||||||
|
|
||||||
begin match Hashtbl.find_opt docs uri with
|
(match Hashtbl.find_opt docs uri with
|
||||||
| None -> IO.return None
|
| None -> IO.return None
|
||||||
| Some doc_st ->
|
| Some doc_st ->
|
||||||
let notify_back = new notify_back ~uri ~notify_back () in
|
let notify_back = new notify_back ~uri ~notify_back () in
|
||||||
self#on_req_hover ~notify_back ~id ~uri ~pos:position ~workDoneToken doc_st
|
self#on_req_hover ~notify_back ~id ~uri ~pos:position
|
||||||
end
|
~workDoneToken doc_st)
|
||||||
|
| Lsp.Client_request.TextDocumentCompletion
|
||||||
| Lsp.Client_request.TextDocumentCompletion {
|
{
|
||||||
textDocument; position; context; workDoneToken; partialResultToken;
|
textDocument;
|
||||||
|
position;
|
||||||
|
context;
|
||||||
|
workDoneToken;
|
||||||
|
partialResultToken;
|
||||||
} ->
|
} ->
|
||||||
let uri = textDocument.uri in
|
let uri = textDocument.uri in
|
||||||
Log.debug (fun k->k "req: complete '%s'" (DocumentUri.to_path uri));
|
Log.debug (fun k ->
|
||||||
begin match Hashtbl.find_opt docs uri with
|
k "req: complete '%s'" (DocumentUri.to_path uri));
|
||||||
|
(match Hashtbl.find_opt docs uri with
|
||||||
| None -> IO.return None
|
| None -> IO.return None
|
||||||
| Some doc_st ->
|
| Some doc_st ->
|
||||||
let notify_back = new notify_back ~uri ~notify_back () in
|
let notify_back = new notify_back ~uri ~notify_back () in
|
||||||
self#on_req_completion ~notify_back ~id ~uri
|
self#on_req_completion ~notify_back ~id ~uri ~workDoneToken
|
||||||
~workDoneToken ~partialResultToken
|
~partialResultToken ~pos:position ~ctx:context doc_st)
|
||||||
~pos:position ~ctx:context doc_st
|
| Lsp.Client_request.TextDocumentDefinition
|
||||||
end
|
{ textDocument; position; workDoneToken; partialResultToken } ->
|
||||||
| Lsp.Client_request.TextDocumentDefinition {
|
|
||||||
textDocument; position; workDoneToken; partialResultToken;
|
|
||||||
} ->
|
|
||||||
let uri = textDocument.uri in
|
let uri = textDocument.uri in
|
||||||
Log.debug (fun k->k "req: definition '%s'" (DocumentUri.to_path uri));
|
Log.debug (fun k ->
|
||||||
|
k "req: definition '%s'" (DocumentUri.to_path uri));
|
||||||
let notify_back = new notify_back ~uri ~notify_back () in
|
let notify_back = new notify_back ~uri ~notify_back () in
|
||||||
|
|
||||||
begin match Hashtbl.find_opt docs uri with
|
(match Hashtbl.find_opt docs uri with
|
||||||
| None -> IO.return None
|
| None -> IO.return None
|
||||||
| Some doc_st ->
|
| Some doc_st ->
|
||||||
self#on_req_definition ~notify_back ~id
|
self#on_req_definition ~notify_back ~id ~workDoneToken
|
||||||
~workDoneToken ~partialResultToken
|
~partialResultToken ~uri ~pos:position doc_st)
|
||||||
~uri ~pos:position doc_st
|
| Lsp.Client_request.TextDocumentCodeLens
|
||||||
end
|
{ textDocument; workDoneToken; partialResultToken } ->
|
||||||
|
|
||||||
| Lsp.Client_request.TextDocumentCodeLens {
|
|
||||||
textDocument; workDoneToken; partialResultToken;
|
|
||||||
} ->
|
|
||||||
let uri = textDocument.uri in
|
let uri = textDocument.uri in
|
||||||
Log.debug (fun k->k "req: codelens '%s'" (DocumentUri.to_path uri));
|
Log.debug (fun k ->
|
||||||
|
k "req: codelens '%s'" (DocumentUri.to_path uri));
|
||||||
let notify_back = new notify_back ~uri ~notify_back () in
|
let notify_back = new notify_back ~uri ~notify_back () in
|
||||||
|
|
||||||
begin match Hashtbl.find_opt docs uri with
|
(match Hashtbl.find_opt docs uri with
|
||||||
| None -> IO.return []
|
| None -> IO.return []
|
||||||
| Some doc_st ->
|
| Some doc_st ->
|
||||||
self#on_req_code_lens ~notify_back ~id ~uri
|
self#on_req_code_lens ~notify_back ~id ~uri ~workDoneToken
|
||||||
~workDoneToken ~partialResultToken doc_st
|
~partialResultToken doc_st)
|
||||||
end
|
|
||||||
|
|
||||||
| Lsp.Client_request.TextDocumentCodeLensResolve cl ->
|
| Lsp.Client_request.TextDocumentCodeLensResolve cl ->
|
||||||
Log.debug (fun k -> k "req: codelens resolve");
|
Log.debug (fun k -> k "req: codelens resolve");
|
||||||
let notify_back = new notify_back ~notify_back () in
|
let notify_back = new notify_back ~notify_back () in
|
||||||
self#on_req_code_lens_resolve ~notify_back ~id cl
|
self#on_req_code_lens_resolve ~notify_back ~id cl
|
||||||
|
| Lsp.Client_request.ExecuteCommand
|
||||||
| Lsp.Client_request.ExecuteCommand { command; arguments; workDoneToken } ->
|
{ command; arguments; workDoneToken } ->
|
||||||
Log.debug (fun k -> k "req: execute command '%s'" command);
|
Log.debug (fun k -> k "req: execute command '%s'" command);
|
||||||
let notify_back = new notify_back ~notify_back () in
|
let notify_back = new notify_back ~notify_back () in
|
||||||
self#on_req_execute_command ~notify_back ~id ~workDoneToken command arguments
|
self#on_req_execute_command ~notify_back ~id ~workDoneToken command
|
||||||
|
arguments
|
||||||
| Lsp.Client_request.DocumentSymbol { textDocument=d; workDoneToken; partialResultToken } ->
|
| Lsp.Client_request.DocumentSymbol
|
||||||
|
{ textDocument = d; workDoneToken; partialResultToken } ->
|
||||||
let notify_back = new notify_back ~notify_back () in
|
let notify_back = new notify_back ~notify_back () in
|
||||||
self#on_req_symbol ~notify_back ~id ~uri:d.uri
|
self#on_req_symbol ~notify_back ~id ~uri:d.uri ~workDoneToken
|
||||||
~workDoneToken ~partialResultToken ()
|
~partialResultToken ()
|
||||||
|
|
||||||
| Lsp.Client_request.CodeAction a ->
|
| Lsp.Client_request.CodeAction a ->
|
||||||
let notify_back = new notify_back ~notify_back () in
|
let notify_back = new notify_back ~notify_back () in
|
||||||
self#on_req_code_action ~notify_back ~id a
|
self#on_req_code_action ~notify_back ~id a
|
||||||
|
|
@ -341,78 +357,83 @@ module Make(IO : IO) = struct
|
||||||
| Lsp.Client_request.UnknownRequest _ ->
|
| Lsp.Client_request.UnknownRequest _ ->
|
||||||
let notify_back = new notify_back ~notify_back () in
|
let notify_back = new notify_back ~notify_back () in
|
||||||
self#on_request_unhandled ~notify_back ~id r
|
self#on_request_unhandled ~notify_back ~id r
|
||||||
end
|
|
||||||
|
|
||||||
(** Called when a document is opened *)
|
method virtual on_notif_doc_did_open
|
||||||
method virtual on_notif_doc_did_open :
|
: notify_back:notify_back ->
|
||||||
notify_back:notify_back ->
|
|
||||||
TextDocumentItem.t ->
|
TextDocumentItem.t ->
|
||||||
content:string ->
|
content:string ->
|
||||||
unit IO.t
|
unit IO.t
|
||||||
|
(** Called when a document is opened *)
|
||||||
|
|
||||||
method virtual on_notif_doc_did_close :
|
method virtual on_notif_doc_did_close
|
||||||
notify_back:notify_back ->
|
: notify_back:notify_back -> TextDocumentIdentifier.t -> unit IO.t
|
||||||
TextDocumentIdentifier.t ->
|
|
||||||
unit IO.t
|
|
||||||
|
|
||||||
(** Called when the document changes. *)
|
method virtual on_notif_doc_did_change
|
||||||
method virtual on_notif_doc_did_change :
|
: notify_back:notify_back ->
|
||||||
notify_back:notify_back ->
|
|
||||||
VersionedTextDocumentIdentifier.t ->
|
VersionedTextDocumentIdentifier.t ->
|
||||||
TextDocumentContentChangeEvent.t list ->
|
TextDocumentContentChangeEvent.t list ->
|
||||||
old_content:string ->
|
old_content:string ->
|
||||||
new_content:string ->
|
new_content:string ->
|
||||||
unit IO.t
|
unit IO.t
|
||||||
|
(** Called when the document changes. *)
|
||||||
|
|
||||||
(** Override to handle unprocessed notifications *)
|
method on_notification_unhandled ~notify_back:_
|
||||||
method on_notification_unhandled
|
(_n : Lsp.Client_notification.t) : unit IO.t =
|
||||||
~notify_back:_ (_n:Lsp.Client_notification.t) : unit IO.t =
|
|
||||||
IO.return ()
|
IO.return ()
|
||||||
|
(** Override to handle unprocessed notifications *)
|
||||||
|
|
||||||
method on_notification
|
method on_notification ~notify_back (n : Lsp.Client_notification.t)
|
||||||
~notify_back (n:Lsp.Client_notification.t) : unit IO.t =
|
: unit IO.t =
|
||||||
let open Lsp.Types in
|
let open Lsp.Types in
|
||||||
|
match n with
|
||||||
begin match n with
|
|
||||||
| Lsp.Client_notification.TextDocumentDidOpen
|
| Lsp.Client_notification.TextDocumentDidOpen
|
||||||
{ DidOpenTextDocumentParams.textDocument = doc } ->
|
{ DidOpenTextDocumentParams.textDocument = doc } ->
|
||||||
Log.debug (fun k->k "notif: did open '%s'" (DocumentUri.to_path doc.uri));
|
Log.debug (fun k ->
|
||||||
|
k "notif: did open '%s'" (DocumentUri.to_path doc.uri));
|
||||||
let notify_back =
|
let notify_back =
|
||||||
new notify_back ~uri:doc.uri ~version:doc.version ~notify_back () in
|
new notify_back ~uri:doc.uri ~version:doc.version ~notify_back ()
|
||||||
let st = {
|
in
|
||||||
uri=doc.uri; version=doc.version; content=doc.text;
|
let st =
|
||||||
|
{
|
||||||
|
uri = doc.uri;
|
||||||
|
version = doc.version;
|
||||||
|
content = doc.text;
|
||||||
languageId = doc.languageId;
|
languageId = doc.languageId;
|
||||||
} in
|
}
|
||||||
|
in
|
||||||
Hashtbl.replace docs doc.uri st;
|
Hashtbl.replace docs doc.uri st;
|
||||||
self#on_notif_doc_did_open ~notify_back doc ~content:st.content
|
self#on_notif_doc_did_open ~notify_back doc ~content:st.content
|
||||||
|
|
||||||
| Lsp.Client_notification.TextDocumentDidClose { textDocument = doc } ->
|
| Lsp.Client_notification.TextDocumentDidClose { textDocument = doc } ->
|
||||||
Log.debug (fun k->k "notif: did close '%s'" (DocumentUri.to_path doc.uri));
|
Log.debug (fun k ->
|
||||||
|
k "notif: did close '%s'" (DocumentUri.to_path doc.uri));
|
||||||
let notify_back = new notify_back ~uri:doc.uri ~notify_back () in
|
let notify_back = new notify_back ~uri:doc.uri ~notify_back () in
|
||||||
self#on_notif_doc_did_close ~notify_back doc
|
self#on_notif_doc_did_close ~notify_back doc
|
||||||
|
| Lsp.Client_notification.TextDocumentDidChange
|
||||||
| Lsp.Client_notification.TextDocumentDidChange {textDocument=doc; contentChanges=c} ->
|
{ textDocument = doc; contentChanges = c } ->
|
||||||
Log.debug (fun k->k "notif: did change '%s'" (DocumentUri.to_path doc.uri));
|
Log.debug (fun k ->
|
||||||
|
k "notif: did change '%s'" (DocumentUri.to_path doc.uri));
|
||||||
let notify_back = new notify_back ~uri:doc.uri ~notify_back () in
|
let notify_back = new notify_back ~uri:doc.uri ~notify_back () in
|
||||||
|
|
||||||
let old_doc =
|
let old_doc =
|
||||||
match Hashtbl.find_opt docs doc.uri with
|
match Hashtbl.find_opt docs doc.uri with
|
||||||
| None ->
|
| None ->
|
||||||
(* WTF vscode. Well let's try and deal with it. *)
|
(* WTF vscode. Well let's try and deal with it. *)
|
||||||
Log.err (fun k->k "unknown document: '%s'" (DocumentUri.to_path doc.uri));
|
Log.err (fun k ->
|
||||||
|
k "unknown document: '%s'" (DocumentUri.to_path doc.uri));
|
||||||
let version = doc.version in
|
let version = doc.version in
|
||||||
|
|
||||||
let languageId = "" in (* FIXME*)
|
let languageId = "" in
|
||||||
|
(* FIXME*)
|
||||||
Lsp.Text_document.make
|
Lsp.Text_document.make
|
||||||
(DidOpenTextDocumentParams.create
|
(DidOpenTextDocumentParams.create
|
||||||
~textDocument:(
|
~textDocument:
|
||||||
TextDocumentItem.create ~languageId
|
(TextDocumentItem.create ~languageId ~uri:doc.uri ~version
|
||||||
~uri:doc.uri ~version ~text:""))
|
~text:""))
|
||||||
| Some st ->
|
| Some st ->
|
||||||
Lsp.Text_document.make
|
Lsp.Text_document.make
|
||||||
(DidOpenTextDocumentParams.create
|
(DidOpenTextDocumentParams.create
|
||||||
~textDocument:(
|
~textDocument:
|
||||||
TextDocumentItem.create ~languageId:st.languageId
|
(TextDocumentItem.create ~languageId:st.languageId
|
||||||
~uri:doc.uri ~version:st.version ~text:st.content))
|
~uri:doc.uri ~version:st.version ~text:st.content))
|
||||||
in
|
in
|
||||||
|
|
||||||
|
|
@ -422,18 +443,22 @@ module Make(IO : IO) = struct
|
||||||
old_doc c
|
old_doc c
|
||||||
in
|
in
|
||||||
|
|
||||||
let new_st : doc_state = {
|
let new_st : doc_state =
|
||||||
uri=doc.uri; languageId=Lsp.Text_document.languageId new_doc;
|
{
|
||||||
|
uri = doc.uri;
|
||||||
|
languageId = Lsp.Text_document.languageId new_doc;
|
||||||
content = Lsp.Text_document.text new_doc;
|
content = Lsp.Text_document.text new_doc;
|
||||||
version = Lsp.Text_document.version new_doc;
|
version = Lsp.Text_document.version new_doc;
|
||||||
} in
|
}
|
||||||
|
in
|
||||||
|
|
||||||
Hashtbl.replace docs doc.uri new_st;
|
Hashtbl.replace docs doc.uri new_st;
|
||||||
self#on_notif_doc_did_change ~notify_back doc c
|
self#on_notif_doc_did_change ~notify_back doc c
|
||||||
~old_content:(Lsp.Text_document.text old_doc)
|
~old_content:(Lsp.Text_document.text old_doc)
|
||||||
~new_content:new_st.content
|
~new_content:new_st.content
|
||||||
|
| Lsp.Client_notification.Exit ->
|
||||||
| Lsp.Client_notification.Exit -> _quit <- true; IO.return ()
|
_quit <- true;
|
||||||
|
IO.return ()
|
||||||
| Lsp.Client_notification.DidSaveTextDocument _
|
| Lsp.Client_notification.DidSaveTextDocument _
|
||||||
| Lsp.Client_notification.WillSaveTextDocument _
|
| Lsp.Client_notification.WillSaveTextDocument _
|
||||||
| Lsp.Client_notification.ChangeWorkspaceFolders _
|
| Lsp.Client_notification.ChangeWorkspaceFolders _
|
||||||
|
|
@ -447,10 +472,8 @@ module Make(IO : IO) = struct
|
||||||
| Lsp.Client_notification.DidCreateFiles _
|
| Lsp.Client_notification.DidCreateFiles _
|
||||||
| Lsp.Client_notification.DidDeleteFiles _
|
| Lsp.Client_notification.DidDeleteFiles _
|
||||||
| Lsp.Client_notification.DidRenameFiles _
|
| Lsp.Client_notification.DidRenameFiles _
|
||||||
| Lsp.Client_notification.LogTrace _
|
| Lsp.Client_notification.LogTrace _ ->
|
||||||
->
|
|
||||||
let notify_back = new notify_back ~notify_back () in
|
let notify_back = new notify_back ~notify_back () in
|
||||||
self#on_notification_unhandled ~notify_back n
|
self#on_notification_unhandled ~notify_back n
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
|
|
||||||
|
|
||||||
(** {2 Parametrized IO Interface} *)
|
(** {2 Parametrized IO Interface} *)
|
||||||
module type IO = sig
|
module type IO = sig
|
||||||
type 'a t
|
type 'a t
|
||||||
|
|
||||||
val return : 'a -> 'a t
|
val return : 'a -> 'a t
|
||||||
val failwith : string -> 'a t
|
val failwith : string -> 'a t
|
||||||
|
|
||||||
val ( let+ ) : 'a t -> ('a -> 'b) -> 'b t
|
val ( let+ ) : 'a t -> ('a -> 'b) -> 'b t
|
||||||
val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t
|
val ( let* ) : 'a t -> ('a -> 'b t) -> 'b t
|
||||||
val ( and+ ) : 'a t -> 'b t -> ('a * 'b) t
|
val ( and+ ) : 'a t -> 'b t -> ('a * 'b) t
|
||||||
|
|
@ -16,10 +13,8 @@ module type IO = sig
|
||||||
|
|
||||||
val stdin : in_channel
|
val stdin : in_channel
|
||||||
val stdout : out_channel
|
val stdout : out_channel
|
||||||
|
|
||||||
val read : in_channel -> bytes -> int -> int -> unit t
|
val read : in_channel -> bytes -> int -> int -> unit t
|
||||||
val read_line : in_channel -> string t
|
val read_line : in_channel -> string t
|
||||||
|
|
||||||
val write : out_channel -> bytes -> int -> int -> unit t
|
val write : out_channel -> bytes -> int -> int -> unit t
|
||||||
val write_string : out_channel -> string -> unit t
|
val write_string : out_channel -> string -> unit t
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue