Skip to content

Commit

Permalink
Completion for in keyword (ocaml#1217)
Browse files Browse the repository at this point in the history
feat(auto-completion): auto-complete `in` (in a hacky way) in .ml files
  • Loading branch information
ulugbekna committed Dec 11, 2023
1 parent 9dc8de2 commit f9de892
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 14 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
- Add mark/remove unused actions for open, types, for loop indexes, modules,
match cases, rec, and constructors (#1141)

- Offer auto-completion for the keyword `in` (#1217)

# 1.16.2

## Fixes
Expand Down
26 changes: 25 additions & 1 deletion ocaml-lsp-server/src/compl.ml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,23 @@ module Complete_by_prefix = struct
completion_entries
~f:(completionItem_of_completion_entry ~deprecated ~range ~compl_params)

let complete_keywords completion_position prefix =
match prefix with
| "" | "i" | "in" ->
let ci_for_in =
CompletionItem.create
~label:"in"
~textEdit:
(`TextEdit
(TextEdit.create
~newText:"in"
~range:(range_prefix completion_position prefix)))
~kind:CompletionItemKind.Keyword
()
in
[ ci_for_in ]
| _ -> []

let complete doc prefix pos ~deprecated ~resolve =
let+ (completion : Query_protocol.completions) =
let logical_pos = Position.logical pos in
Expand All @@ -166,7 +183,14 @@ module Complete_by_prefix = struct
doc
(dispatch_cmd ~prefix logical_pos)
in
process_dispatch_resp ~deprecated ~resolve doc pos completion
let keyword_completionItems =
(* we complete only keyword 'in' for now *)
match Document.Merlin.kind doc with
| Intf -> []
| Impl -> complete_keywords pos prefix
in
keyword_completionItems
@ process_dispatch_resp ~deprecated ~resolve doc pos completion
end

module Complete_with_construct = struct
Expand Down
170 changes: 157 additions & 13 deletions ocaml-lsp-server/test/e2e-new/completion.ml
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,17 @@ let plus_42 (x:int) (y:int) =
[%expect
{|
Completions:
{
"kind": 14,
"label": "in",
"textEdit": {
"newText": "in",
"range": {
"end": { "character": 12, "line": 5 },
"start": { "character": 12, "line": 5 }
}
}
}
{
"detail": "int",
"kind": 12,
Expand Down Expand Up @@ -712,19 +723,6 @@ let plus_42 (x:int) (y:int) =
}
}
}
{
"detail": "char -> int",
"kind": 12,
"label": "int_of_char",
"sortText": "0009",
"textEdit": {
"newText": "int_of_char",
"range": {
"end": { "character": 12, "line": 5 },
"start": { "character": 12, "line": 5 }
}
}
}
.............
|}]
Expand Down Expand Up @@ -1162,3 +1160,149 @@ let%expect_test "completion doesn't autocomplete record fields" =
(* We expect 0 completions*)
[%expect {| No completions |}]
let%expect_test "completion for `in` keyword - no prefix" =
let source = {ocaml|
let foo param1 =
let bar = param1 |ocaml} in
let position = Position.create ~line:2 ~character:19 in
print_completions ~limit:3 source position;
[%expect
{|
Completions:
{
"kind": 14,
"label": "in",
"textEdit": {
"newText": "in",
"range": {
"end": { "character": 19, "line": 2 },
"start": { "character": 19, "line": 2 }
}
}
}
{
"detail": "'a -> 'b",
"kind": 12,
"label": "param1",
"sortText": "0000",
"textEdit": {
"newText": "param1",
"range": {
"end": { "character": 19, "line": 2 },
"start": { "character": 19, "line": 2 }
}
}
}
{
"detail": "'a ref -> 'a",
"kind": 12,
"label": "!",
"sortText": "0001",
"textEdit": {
"newText": "!",
"range": {
"end": { "character": 19, "line": 2 },
"start": { "character": 19, "line": 2 }
}
}
}
............. |}]
let%expect_test "completion for `in` keyword - prefix i" =
let source = {ocaml|
let foo param1 =
let bar = param1 i
|ocaml} in
let position = Position.create ~line:2 ~character:20 in
print_completions ~limit:3 source position;
[%expect
{|
Completions:
{
"kind": 14,
"label": "in",
"textEdit": {
"newText": "in",
"range": {
"end": { "character": 20, "line": 2 },
"start": { "character": 19, "line": 2 }
}
}
}
{
"detail": "'a -> unit",
"kind": 12,
"label": "ignore",
"sortText": "0000",
"textEdit": {
"newText": "ignore",
"range": {
"end": { "character": 20, "line": 2 },
"start": { "character": 19, "line": 2 }
}
}
}
{
"detail": "in_channel -> int",
"kind": 12,
"label": "in_channel_length",
"sortText": "0001",
"textEdit": {
"newText": "in_channel_length",
"range": {
"end": { "character": 20, "line": 2 },
"start": { "character": 19, "line": 2 }
}
}
}
............. |}]
let%expect_test "completion for `in` keyword - prefix in" =
let source = {ocaml|
let foo param1 =
let bar = param1 in
|ocaml} in
let position = Position.create ~line:2 ~character:21 in
print_completions ~limit:3 source position;
[%expect
{|
Completions:
{
"kind": 14,
"label": "in",
"textEdit": {
"newText": "in",
"range": {
"end": { "character": 21, "line": 2 },
"start": { "character": 19, "line": 2 }
}
}
}
{
"detail": "in_channel -> int",
"kind": 12,
"label": "in_channel_length",
"sortText": "0000",
"textEdit": {
"newText": "in_channel_length",
"range": {
"end": { "character": 21, "line": 2 },
"start": { "character": 19, "line": 2 }
}
}
}
{
"detail": "int ref -> unit",
"kind": 12,
"label": "incr",
"sortText": "0001",
"textEdit": {
"newText": "incr",
"range": {
"end": { "character": 21, "line": 2 },
"start": { "character": 19, "line": 2 }
}
}
}
............. |}]

0 comments on commit f9de892

Please sign in to comment.