Skip to content

Commit 51e16ea

Browse files
authored
Fix prefix parsing to start method completion when typing # (#1363)
* Add a test illustrating issue #1358 Object methods are not completed * Fix prefix parsing for method call When completing module paths or record fields Merlin expects the beginning of the path and the `.` to be part of the prefix. But when accessing an object's methods, the prefix should not contain the `#` sign. We use a sub-matching group to that effect. - Prefix for [my_record.|] is ["my_record."] (handled by [name_or_label]) - Prefix for [my_object#|] is [""] (handled by [method_call]) * Changelog entry for #1363 Fixes #1358
1 parent 1509ff4 commit 51e16ea

File tree

3 files changed

+72
-3
lines changed

3 files changed

+72
-3
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Fixes
44

55
- Fix fd leak in running external processes for preprocessing (#1349)
6+
- Fix prefix parsing for completion of object methods (#1363, fixes #1358)
67

78
# 1.19.0
89

ocaml-lsp-server/src/prefix_parser.ml

+15-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ include struct
2424
])
2525
;;
2626

27+
(* When completing module paths or record fields Merlin expects the
28+
beginning of the path and the `.` to be part of the prefix. But when
29+
accessing an object's methods, the prefix should not contain the `#`
30+
sign. We use a sub-matching group to that effect.
31+
32+
- Prefix for [my_record.|] is ["my_record."] (handled by [name_or_label])
33+
- Prefix for [my_object#|] is [""] (handled by [method_call]) *)
34+
let method_call = compile (seq [ char '#'; Re.group (rep name_char); stop ])
35+
2736
(** matches let%lwt and let* style expressions. See
2837
here:https://v2.ocaml.org/manual/bindingops.html *)
2938
let monadic_bind =
@@ -42,8 +51,11 @@ let parse ~pos ~len text =
4251
(*Attempt to match each of our possible prefix types, the order is important
4352
because there is some overlap between the regexs*)
4453
let matched =
45-
List.find_map [ name_or_label; monadic_bind; infix_operator ] ~f:(fun regex ->
46-
Re.exec_opt ~pos ~len regex text)
54+
List.find_map
55+
[ name_or_label; method_call; monadic_bind; infix_operator ]
56+
~f:(fun regex -> Re.exec_opt ~pos ~len regex text)
4757
in
48-
matched |> Option.map ~f:(fun x -> Re.Group.get x 0)
58+
matched
59+
|> Option.map ~f:(fun x ->
60+
if Re.Group.test x 1 then Re.Group.get x 1 else Re.Group.get x 0)
4961
;;

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

+56
Original file line numberDiff line numberDiff line change
@@ -1243,3 +1243,59 @@ let foo param1 =
12431243
}
12441244
............. |}]
12451245
;;
1246+
1247+
(* Test case was taken from issue #1358 *)
1248+
let%expect_test "completion for object methods" =
1249+
let source = {ocaml|let f (x : < a_method : 'a >) = x#|ocaml} in
1250+
let position = Position.create ~line:0 ~character:34 in
1251+
print_completions ~limit:3 source position;
1252+
[%expect
1253+
{|
1254+
Completions:
1255+
{
1256+
"kind": 14,
1257+
"label": "in",
1258+
"textEdit": {
1259+
"newText": "in",
1260+
"range": {
1261+
"end": { "character": 34, "line": 0 },
1262+
"start": { "character": 34, "line": 0 }
1263+
}
1264+
}
1265+
}
1266+
{
1267+
"detail": "'a",
1268+
"kind": 2,
1269+
"label": "a_method",
1270+
"sortText": "0000",
1271+
"textEdit": {
1272+
"newText": "a_method",
1273+
"range": {
1274+
"end": { "character": 34, "line": 0 },
1275+
"start": { "character": 34, "line": 0 }
1276+
}
1277+
}
1278+
} |}]
1279+
;;
1280+
1281+
let%expect_test "completion for object methods" =
1282+
let source = {ocaml|let f (x : < a_method : 'a; ab_m : 'b >) = x#ab|ocaml} in
1283+
let position = Position.create ~line:0 ~character:49 in
1284+
print_completions ~limit:3 source position;
1285+
[%expect
1286+
{|
1287+
Completions:
1288+
{
1289+
"detail": "'b",
1290+
"kind": 2,
1291+
"label": "ab_m",
1292+
"sortText": "0000",
1293+
"textEdit": {
1294+
"newText": "ab_m",
1295+
"range": {
1296+
"end": { "character": 49, "line": 0 },
1297+
"start": { "character": 47, "line": 0 }
1298+
}
1299+
}
1300+
} |}]
1301+
;;

0 commit comments

Comments
 (0)