Construct as completion suggestions#472
Conversation
040446a to
11a3aeb
Compare
rgrinberg
left a comment
There was a problem hiding this comment.
Thanks for your efforts. I did an initial review and the PR should be good to go after some minor fixes.
ocaml-lsp-server/test/e2e/__tests__/textDocument-completion.test.ts
Outdated
Show resolved
Hide resolved
I would wait until it is possible to insert snippets with code actions before exploring this. It would be very confusing UI if the editor only offers snippets only via completions. |
* we don't need to pair completion entries with a fixed range * use more self-explanatory names for variables * add comments to where it's not obvious why we're doing this * make newlines more consistent
(AFAIU, await in an async function is useless if we don't await that function itself)
…aram of request) does not have `data` field. We return the completion item itself if the `data` field is missing. We need this for the "merlin construct as completions" feature
…ode action `Construct an expression`
* add comments to explain the code action
syntactically or in AST form
especially vscode-specific commands
* do not put two separate task in merlin thread; do requests in one
036c29e to
fcd625b
Compare
|
I hope that trying to make two merlin dispatches at once (fcd625b) is worth the complexity. But I tried to make the code modular, readable, and maintainable. |
rgrinberg
left a comment
There was a problem hiding this comment.
I hope that trying to make two merlin dispatches at once (fcd625b) is worth the complexity. But I tried to make the code modular, readable, and maintainable.
It's definitely worth it.
The new code looks much better. Some more minor tweaks and it should be good to go.
ocaml-lsp-server/test/e2e/__tests__/textDocument-completion.test.ts
Outdated
Show resolved
Hide resolved
Signed-off-by: Rudi Grinberg <me@rgrinberg.com>
rgrinberg
left a comment
There was a problem hiding this comment.
Pushed a few tweaks.
Looks good to go.
600e4ec to
6f9a240
Compare
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)
Implements support for merlin
Construct.The main reservation that I have so far is that we're not flexible enough about the
depthparameter forConstruct. How can we fix this?From our discussion with voodoos:
Localparam forConstructisn't ready yet, and we should specifydepthparam later, when it's more efficient.To discuss: Maybe it makes more sense to replace
_s with snippets, eg calling construct in_ arg1 arg2will result in(fun _ _ -> _) arg1 arg2and the cursor will jump to the third underscore (typed hole), while the user likely wants to change the function arguments first.Otherwise, I used the implementation myself. It seems quite good to me. Demo (the demo used Construct with param set to `Local to use local values, which we turned off now)
Screen.Recording.2021-07-06.at.23.13.40.mov