Skip to content

Commit f9de892

Browse files
authored
Completion for in keyword (#1217)
feat(auto-completion): auto-complete `in` (in a hacky way) in .ml files
1 parent 9dc8de2 commit f9de892

File tree

3 files changed

+184
-14
lines changed

3 files changed

+184
-14
lines changed

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
- Add mark/remove unused actions for open, types, for loop indexes, modules,
2828
match cases, rec, and constructors (#1141)
2929

30+
- Offer auto-completion for the keyword `in` (#1217)
31+
3032
# 1.16.2
3133

3234
## Fixes

ocaml-lsp-server/src/compl.ml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,23 @@ module Complete_by_prefix = struct
158158
completion_entries
159159
~f:(completionItem_of_completion_entry ~deprecated ~range ~compl_params)
160160

161+
let complete_keywords completion_position prefix =
162+
match prefix with
163+
| "" | "i" | "in" ->
164+
let ci_for_in =
165+
CompletionItem.create
166+
~label:"in"
167+
~textEdit:
168+
(`TextEdit
169+
(TextEdit.create
170+
~newText:"in"
171+
~range:(range_prefix completion_position prefix)))
172+
~kind:CompletionItemKind.Keyword
173+
()
174+
in
175+
[ ci_for_in ]
176+
| _ -> []
177+
161178
let complete doc prefix pos ~deprecated ~resolve =
162179
let+ (completion : Query_protocol.completions) =
163180
let logical_pos = Position.logical pos in
@@ -166,7 +183,14 @@ module Complete_by_prefix = struct
166183
doc
167184
(dispatch_cmd ~prefix logical_pos)
168185
in
169-
process_dispatch_resp ~deprecated ~resolve doc pos completion
186+
let keyword_completionItems =
187+
(* we complete only keyword 'in' for now *)
188+
match Document.Merlin.kind doc with
189+
| Intf -> []
190+
| Impl -> complete_keywords pos prefix
191+
in
192+
keyword_completionItems
193+
@ process_dispatch_resp ~deprecated ~resolve doc pos completion
170194
end
171195

172196
module Complete_with_construct = struct

ocaml-lsp-server/test/e2e-new/completion.ml

Lines changed: 157 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,17 @@ let plus_42 (x:int) (y:int) =
595595
[%expect
596596
{|
597597
Completions:
598+
{
599+
"kind": 14,
600+
"label": "in",
601+
"textEdit": {
602+
"newText": "in",
603+
"range": {
604+
"end": { "character": 12, "line": 5 },
605+
"start": { "character": 12, "line": 5 }
606+
}
607+
}
608+
}
598609
{
599610
"detail": "int",
600611
"kind": 12,
@@ -712,19 +723,6 @@ let plus_42 (x:int) (y:int) =
712723
}
713724
}
714725
}
715-
{
716-
"detail": "char -> int",
717-
"kind": 12,
718-
"label": "int_of_char",
719-
"sortText": "0009",
720-
"textEdit": {
721-
"newText": "int_of_char",
722-
"range": {
723-
"end": { "character": 12, "line": 5 },
724-
"start": { "character": 12, "line": 5 }
725-
}
726-
}
727-
}
728726
.............
729727
|}]
730728
@@ -1162,3 +1160,149 @@ let%expect_test "completion doesn't autocomplete record fields" =
11621160
11631161
(* We expect 0 completions*)
11641162
[%expect {| No completions |}]
1163+
1164+
let%expect_test "completion for `in` keyword - no prefix" =
1165+
let source = {ocaml|
1166+
let foo param1 =
1167+
let bar = param1 |ocaml} in
1168+
let position = Position.create ~line:2 ~character:19 in
1169+
print_completions ~limit:3 source position;
1170+
[%expect
1171+
{|
1172+
Completions:
1173+
{
1174+
"kind": 14,
1175+
"label": "in",
1176+
"textEdit": {
1177+
"newText": "in",
1178+
"range": {
1179+
"end": { "character": 19, "line": 2 },
1180+
"start": { "character": 19, "line": 2 }
1181+
}
1182+
}
1183+
}
1184+
{
1185+
"detail": "'a -> 'b",
1186+
"kind": 12,
1187+
"label": "param1",
1188+
"sortText": "0000",
1189+
"textEdit": {
1190+
"newText": "param1",
1191+
"range": {
1192+
"end": { "character": 19, "line": 2 },
1193+
"start": { "character": 19, "line": 2 }
1194+
}
1195+
}
1196+
}
1197+
{
1198+
"detail": "'a ref -> 'a",
1199+
"kind": 12,
1200+
"label": "!",
1201+
"sortText": "0001",
1202+
"textEdit": {
1203+
"newText": "!",
1204+
"range": {
1205+
"end": { "character": 19, "line": 2 },
1206+
"start": { "character": 19, "line": 2 }
1207+
}
1208+
}
1209+
}
1210+
............. |}]
1211+
1212+
let%expect_test "completion for `in` keyword - prefix i" =
1213+
let source = {ocaml|
1214+
let foo param1 =
1215+
let bar = param1 i
1216+
|ocaml} in
1217+
let position = Position.create ~line:2 ~character:20 in
1218+
print_completions ~limit:3 source position;
1219+
[%expect
1220+
{|
1221+
Completions:
1222+
{
1223+
"kind": 14,
1224+
"label": "in",
1225+
"textEdit": {
1226+
"newText": "in",
1227+
"range": {
1228+
"end": { "character": 20, "line": 2 },
1229+
"start": { "character": 19, "line": 2 }
1230+
}
1231+
}
1232+
}
1233+
{
1234+
"detail": "'a -> unit",
1235+
"kind": 12,
1236+
"label": "ignore",
1237+
"sortText": "0000",
1238+
"textEdit": {
1239+
"newText": "ignore",
1240+
"range": {
1241+
"end": { "character": 20, "line": 2 },
1242+
"start": { "character": 19, "line": 2 }
1243+
}
1244+
}
1245+
}
1246+
{
1247+
"detail": "in_channel -> int",
1248+
"kind": 12,
1249+
"label": "in_channel_length",
1250+
"sortText": "0001",
1251+
"textEdit": {
1252+
"newText": "in_channel_length",
1253+
"range": {
1254+
"end": { "character": 20, "line": 2 },
1255+
"start": { "character": 19, "line": 2 }
1256+
}
1257+
}
1258+
}
1259+
............. |}]
1260+
1261+
let%expect_test "completion for `in` keyword - prefix in" =
1262+
let source = {ocaml|
1263+
let foo param1 =
1264+
let bar = param1 in
1265+
|ocaml} in
1266+
let position = Position.create ~line:2 ~character:21 in
1267+
print_completions ~limit:3 source position;
1268+
[%expect
1269+
{|
1270+
Completions:
1271+
{
1272+
"kind": 14,
1273+
"label": "in",
1274+
"textEdit": {
1275+
"newText": "in",
1276+
"range": {
1277+
"end": { "character": 21, "line": 2 },
1278+
"start": { "character": 19, "line": 2 }
1279+
}
1280+
}
1281+
}
1282+
{
1283+
"detail": "in_channel -> int",
1284+
"kind": 12,
1285+
"label": "in_channel_length",
1286+
"sortText": "0000",
1287+
"textEdit": {
1288+
"newText": "in_channel_length",
1289+
"range": {
1290+
"end": { "character": 21, "line": 2 },
1291+
"start": { "character": 19, "line": 2 }
1292+
}
1293+
}
1294+
}
1295+
{
1296+
"detail": "int ref -> unit",
1297+
"kind": 12,
1298+
"label": "incr",
1299+
"sortText": "0001",
1300+
"textEdit": {
1301+
"newText": "incr",
1302+
"range": {
1303+
"end": { "character": 21, "line": 2 },
1304+
"start": { "character": 19, "line": 2 }
1305+
}
1306+
}
1307+
}
1308+
............. |}]

0 commit comments

Comments
 (0)