-
Notifications
You must be signed in to change notification settings - Fork 126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OCamlformat RPC #386
OCamlformat RPC #386
Conversation
|
0dd9f6d
to
6738834
Compare
About error messages, I think most of them will stay as debug messages. OCamlformat crashes and errors should be kept in the debug log: there are useful for devs to debug issues but useless to the users and unrelated to their programs. |
As you suggested it in a comment I decided to stick more closely to how Dune RPC process is handled (in Fiber.parallel_iter
~f:(fun f -> f ())
[ (fun () -> Server.start server)
; (fun () ->
let* _state = Ocamlformat_rpc.run ocamlformat_rpc in
(* TODO ulysse Handle errors*)
Fiber.return ())
; (fun () -> ... Dune.run dune ... )
] However I have a problem to stop it: you appear to stop the DRPC client after this first fiber returns: match !dune with
| None -> Fiber.return ()
| Some dune -> Dune.stop dune) But I don't understand why the first fiber would return before the process is stopped because it is waiting for the process to stop to complete ? In any case I had that problem with OCamlformat server and decided to stop it explicitely when the Server does: Fiber.parallel_iter
~f:(fun f -> f ())
[ (fun () ->
let* () = Server.start server in
(* When server exits we also stop ocamlformat rpc *)
Ocamlformat_rpc.stop ocamlformat_rpc)
; (fun () ->
let* _state = Ocamlformat_rpc.run ocamlformat_rpc in
(* TODO ulysse Handle errors*)
Fiber.return ())
; (fun () -> ... Dune.run dune ... )
] This way the second item in the parallel iter does complete because it watches the process' exit and the process is exited after stopping the server in the first item of the parallel iter. Is that the right thing to do or did I miss something essential ? (Also when I use Dune master the ocamllsp process does not exits when asking a reload of the server in vscode, process are multiplying , which does not happen with a version of Dune without the rpc server) |
You aren't missing anything. I already had this fixed in a branch that I merged yesterday. |
Great, I will have one last pass and it will be ready for a (hopefully) final review. |
I refactored the module a bit. I also added a user notification ( Some types will fail to be formatted by ocamlformat: Merlin prints types which may be disambiguated with a stamp like in @gpetiot is working on supporting this syntax in ocamlformat. |
Looks much better now! There are still some opaque error messages that need fixing (or removing) |
I reworked the logging in ead0825. Edit: running the tests spawns a huge number of hard-to-kill |
That's definitely problematic. I forgot to mention that we should delay launching the process until we actually request it to format something. |
I decided to use a Along with some marginal tweaks this does solve the tests. No more zombies |
This is used to format types returned by Merlin.
Signed-off-by: Rudi Grinberg <[email protected]>
make sure that we turn off dune after the server is done Signed-off-by: Rudi Grinberg <[email protected]>
6f94e3e
to
c101f63
Compare
It pulls too many transitive test deps. This now causes a conflict with ocamlformat-rpc's test deps Signed-off-by: Rudi Grinberg <[email protected]>
Looks good. I modified the code to us two ivars instead of the mvar. I'm more confident with an ivar that we won't double write when we shouldn't. |
CHANGES: ## Features - Add a new code action `Add missing rec keyword`, which is available when adding a `rec` keyword can fix `Unbound value ...` error, e.g., ```ocaml let fact n = if n = 0 then 1 else n * fact (n - 1) (* ^^^^ Unbound value fact *) ``` Adding `rec` to the definition of `fact` will fix the problem. The new code action offers adding `rec`. - Jump to the first hole on calling `Destruct` code action (only with client VSCode OCaml Platform) (ocaml/ocaml-lsp#468) Example: when a user invokes `Destruct` code action on `Some 1`, this code is replaced by `match Some 1 with None -> _ | Some _ -> _`, where the 1st and 3rd underscores are "typed holes", a concept created by Merlin to be able to put "holes" in OCaml code. With this change, now for VSCode OCaml Platform users, on such invocation of `Destruct`, the cursor will jump to the first typed hole and select it, so that user can start editing right away. - Use ocamlformat to properly format type snippets. This feature requires the `ocamlformat-rpc` opam package to be installed. (ocaml/ocaml-lsp#386) - Add completion support for polymorphic variants, when it is possible to pin down the precise type. Examples (`<|>` stands for the cursor) when completion will work (ocaml/ocaml-lsp#473) Function application: ``` let foo (a: [`Alpha | `Beta]) = () foo `A<|> ``` Type explicitly shown: ``` let a : [`Alpha | `Beta] = `B<|> ``` Note: this is actually a bug fix, since we were ignoring the backtick when constructing the prefix for completion. - Parse merlin errors (best effort) into a more structured form. This allows reporting all locations as "related information" (ocaml/ocaml-lsp#475) - Add support for Merlin `Construct` command as completion suggestions, i.e., show complex expressions that could complete the typed hole. (ocaml/ocaml-lsp#472) - Add a code action `Construct an expression` that is shown when the cursor is at the end of the typed hole, i.e., `_|`, where `|` is the cursor. The code action simply triggers the client (currently only VS Code is supported) to show completion suggestions. (ocaml/ocaml-lsp#472) - Change the formatting-on-save error notification to a warning notification (ocaml/ocaml-lsp#472) - Code action to qualify ("put module name in identifiers") and unqualify ("remove module name from identifiers") module names in identifiers (ocaml/ocaml-lsp#399) Starting from: ```ocaml open Unix let times = Unix.times () let f x = x.Unix.tms_stime, x.Unix.tms_utime ``` Calling "remove module name from identifiers" with the cursor on the open statement will produce: ```ocaml open Unix let times = times () let f x = x.tms_stime, x.tms_utime ``` Calling "put module name in identifiers" will restore: ```ocaml open Unix let times = Unix.times () let f x = x.Unix.tms_stime, x.Unix.tms_utime ``` ## Fixes - Do not show "random" documentation on hover - fixed by [merlin#1364](ocaml/merlin#1364) - fixes duplicate: - [ocaml-lsp#344](ocaml/ocaml-lsp#344) - [vscode-ocaml-platform#111](ocamllabs/vscode-ocaml-platform#111) - Correctly rename a variable used as a named/optional argument (ocaml/ocaml-lsp#478) - When reporting an error at the beginning of the file, use the first line not the second (ocaml/ocaml-lsp#489)
CHANGES: ## Features - Add a new code action `Add missing rec keyword`, which is available when adding a `rec` keyword can fix `Unbound value ...` error, e.g., ```ocaml let fact n = if n = 0 then 1 else n * fact (n - 1) (* ^^^^ Unbound value fact *) ``` Adding `rec` to the definition of `fact` will fix the problem. The new code action offers adding `rec`. - Use ocamlformat to properly format type snippets. This feature requires the `ocamlformat-rpc` opam package to be installed. (ocaml/ocaml-lsp#386) - Add completion support for polymorphic variants, when it is possible to pin down the precise type. Examples (`<|>` stands for the cursor) when completion will work (ocaml/ocaml-lsp#473) Function application: ``` let foo (a: [`Alpha | `Beta]) = () foo `A<|> ``` Type explicitly shown: ``` let a : [`Alpha | `Beta] = `B<|> ``` Note: this is actually a bug fix, since we were ignoring the backtick when constructing the prefix for completion. - Parse merlin errors (best effort) into a more structured form. This allows reporting all locations as "related information" (ocaml/ocaml-lsp#475) - Add support for Merlin `Construct` command as completion suggestions, i.e., show complex expressions that could complete the typed hole. (ocaml/ocaml-lsp#472) - Add a code action `Construct an expression` that is shown when the cursor is at the end of the typed hole, i.e., `_|`, where `|` is the cursor. The code action simply triggers the client (currently only VS Code is supported) to show completion suggestions. (ocaml/ocaml-lsp#472) - Change the formatting-on-save error notification to a warning notification (ocaml/ocaml-lsp#472) - Code action to qualify ("put module name in identifiers") and unqualify ("remove module name from identifiers") module names in identifiers (ocaml/ocaml-lsp#399) Starting from: ```ocaml open Unix let times = Unix.times () let f x = x.Unix.tms_stime, x.Unix.tms_utime ``` Calling "remove module name from identifiers" with the cursor on the open statement will produce: ```ocaml open Unix let times = times () let f x = x.tms_stime, x.tms_utime ``` Calling "put module name in identifiers" will restore: ```ocaml open Unix let times = Unix.times () let f x = x.Unix.tms_stime, x.Unix.tms_utime ``` ## Fixes - Do not show "random" documentation on hover - fixed by [merlin#1364](ocaml/merlin#1364) - fixes duplicate: - [ocaml-lsp#344](ocaml/ocaml-lsp#344) - [vscode-ocaml-platform#111](ocamllabs/vscode-ocaml-platform#111) - Correctly rename a variable used as a named/optional argument (ocaml/ocaml-lsp#478) - When reporting an error at the beginning of the file, use the first line not the second (ocaml/ocaml-lsp#489)
This PR add support for formatting of types in popups. Types provided by Merlin are not always nicely formatted and module signatures often wrap because it exceeds the maximum number of columns of a VSCode popup (64 characters on my setup). The idea is to use OCamlformat to format these types, but starting a new process would be to heavy for that usage.
In a joint effort with the OCamlformat team this PR acheive type formatting by spawning an "OCamlformat RPC server" and then communicating with it using a simple protocol. The protocol is vendored for now (in the file
ocamlformat_rpc_lib.ml
but will be made available as a separate and common package.In case of failure to start the server, negotiate a version or receive a response we log some information and fallback to the non-formatted type.
Todo
Related works