diff --git a/ocaml-lsp-server/src/compl.ml b/ocaml-lsp-server/src/compl.ml index f0cf6e5bb..72579bc9a 100644 --- a/ocaml-lsp-server/src/compl.ml +++ b/ocaml-lsp-server/src/compl.ml @@ -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:"" + ~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 @@ -166,7 +183,9 @@ module Complete_by_prefix = struct doc (dispatch_cmd ~prefix logical_pos) in - process_dispatch_resp ~deprecated ~resolve doc pos completion + let keyword_completionItems = complete_keywords pos prefix in + keyword_completionItems + @ process_dispatch_resp ~deprecated ~resolve doc pos completion end module Complete_with_construct = struct diff --git a/ocaml-lsp-server/test/e2e-new/completion.ml b/ocaml-lsp-server/test/e2e-new/completion.ml index e5a5dc3c7..09eb7dcf7 100644 --- a/ocaml-lsp-server/test/e2e-new/completion.ml +++ b/ocaml-lsp-server/test/e2e-new/completion.ml @@ -595,6 +595,17 @@ let plus_42 (x:int) (y:int) = [%expect {| Completions: + { + "kind": 14, + "label": "in", + "textEdit": { + "newText": "", + "range": { + "end": { "character": 12, "line": 5 }, + "start": { "character": 12, "line": 5 } + } + } + } { "detail": "int", "kind": 12, @@ -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 } - } - } - } ............. |}] @@ -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": "", + "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": "", + "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": "", + "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 } + } + } + } + ............. |}]