Skip to content

Commit

Permalink
feature: channel argument support
Browse files Browse the repository at this point in the history
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>

ps-id: c83c8f44-e41d-4e16-9a59-f01ff9654cb9
  • Loading branch information
rgrinberg committed Dec 17, 2022
1 parent 4300cfc commit 6164537
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 13 deletions.
37 changes: 33 additions & 4 deletions ocaml-lsp-server/bin/main.ml
Original file line number Diff line number Diff line change
@@ -1,16 +1,45 @@
open Stdune

let () =
Printexc.record_backtrace true;
let version = ref false in
let read_dot_merlin = ref false in
Arg.parse
let pipe = ref None in
let port = ref None in
let stdio = ref false in
let spec =
[ ("--version", Arg.Set version, "print version")
; ("--pipe", Arg.String (fun p -> pipe := Some p), "set pipe path")
; ("--socket", Arg.Int (fun p -> port := Some p), "set port")
; ("--stdio", Arg.Set stdio, "set stdio")
; ( "--node-ipc"
, Arg.Unit (fun () -> raise @@ Arg.Bad "node-ipc isn't supported")
, "not supported" )
; ( "--fallback-read-dot-merlin"
, Arg.Set read_dot_merlin
, "read Merlin config from .merlin files. The `dot-merlin-reader` \
package must be installed" )
]
(fun _ -> raise (Arg.Bad "anonymous arguments are not accepted"))
"ocamllsp";
in
let usage =
"ocamllsp [ --stdio | --socket SOCKET --port PORT | --pipe PIPE ]"
in
Arg.parse
spec
(fun _ -> raise @@ Arg.Bad "anonymous arguments aren't allowed")
usage;
let channel : Ocaml_lsp_server.channel =
try
match (!pipe, !port, !stdio) with
| None, None, _ -> Stdio
| Some p, None, false -> Pipe p
| None, Some s, false -> Socket s
| _, _, _ -> raise @@ Arg.Bad "invalid arguments"
with Arg.Bad s ->
Format.eprintf "%s@.%!" s;
Arg.usage spec usage;
exit 1
in
let version = !version in
if version then
let version = Ocaml_lsp_server.Version.get () in
Expand All @@ -19,7 +48,7 @@ let () =
let module Exn_with_backtrace = Stdune.Exn_with_backtrace in
match
Exn_with_backtrace.try_with
(Ocaml_lsp_server.run ~read_dot_merlin:!read_dot_merlin)
(Ocaml_lsp_server.run channel ~read_dot_merlin:!read_dot_merlin)
with
| Ok () -> ()
| Error exn ->
Expand Down
45 changes: 37 additions & 8 deletions ocaml-lsp-server/src/ocaml_lsp_server.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1010,19 +1010,14 @@ let on_notification server (notification : Client_notification.t) :
in
state

let start () =
let start stream =
let detached = Fiber.Pool.create () in
let server = Fdecl.create Dyn.opaque in
let store = Document_store.make server detached in
let handler =
let on_request = { Server.Handler.on_request } in
Server.Handler.make ~on_request ~on_notification ()
in
let* stream =
let* stdin = Lev_fiber.Io.stdin in
let+ stdout = Lev_fiber.Io.stdout in
Lsp_fiber.Fiber_io.make stdin stdout
in
let ocamlformat_rpc = Ocamlformat_rpc.create () in
let* configuration = Configuration.default () in
let wheel = Configuration.wheel configuration in
Expand Down Expand Up @@ -1105,8 +1100,42 @@ let start () =
let metrics = Metrics.create () in
Metrics.with_metrics metrics run

let run ~read_dot_merlin () =
type channel =
| Stdio
| Pipe of string
| Socket of int

let socket sockaddr =
let domain = Unix.domain_of_sockaddr sockaddr in
let fd =
Lev_fiber.Fd.create
(Unix.socket ~cloexec:true domain Unix.SOCK_STREAM 0)
(`Non_blocking false)
in
let* () = Lev_fiber.Socket.connect fd sockaddr in
Lev_fiber.Io.create_rw fd

let stream_of_channel = 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

let run channel ~read_dot_merlin () =
Merlin_utils.Lib_config.set_program_name "ocamllsp";
Merlin_config.should_read_dot_merlin := read_dot_merlin;
Unix.putenv "__MERLIN_MASTER_PID" (string_of_int (Unix.getpid ()));
Lev_fiber.run ~sigpipe:`Ignore start |> Lev_fiber.Error.ok_exn
Lev_fiber.run ~sigpipe:`Ignore (fun () ->
let* input, output = stream_of_channel channel in
start (Lsp_fiber.Fiber_io.make input output))
|> Lev_fiber.Error.ok_exn
7 changes: 6 additions & 1 deletion ocaml-lsp-server/src/ocaml_lsp_server.mli
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
val run : read_dot_merlin:bool -> unit -> unit
type channel =
| Stdio
| Pipe of string
| Socket of int

val run : channel -> read_dot_merlin:bool -> unit -> unit

module Diagnostics = Diagnostics
module Version = Version
Expand Down

0 comments on commit 6164537

Please sign in to comment.