Skip to content

Commit 10961b9

Browse files
Disable trigger-character completions and signature help in comments (#1246)
1 parent c2046a2 commit 10961b9

File tree

7 files changed

+126
-74
lines changed

7 files changed

+126
-74
lines changed

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626

2727
- Correctly accept the `--clientProcessId` flag. (#1242)
2828

29+
- Disable automatic completion and signature help inside comments (#1246)
30+
2931
# 1.17.0
3032

3133
## Fixes
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
open Import
2+
3+
let position_in_comment ~position ~merlin =
4+
let loc_contains_position (_, (loc : Loc.t)) =
5+
let start = Position.of_lexical_position loc.loc_start in
6+
let end_ = Position.of_lexical_position loc.loc_end in
7+
match Option.both start end_ with
8+
| Some (start, end_) -> (
9+
let range = Range.create ~start ~end_ in
10+
match Position.compare_inclusion position range with
11+
| `Inside -> true
12+
| `Outside _ -> false)
13+
| None -> false
14+
in
15+
Document.Merlin.with_pipeline_exn ~name:"get-comments" merlin (fun pipeline ->
16+
Mpipeline.reader_comments pipeline |> List.exists ~f:loc_contains_position)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
(** Returns [true] if [position] occurs inside a comment in the document *)
2+
val position_in_comment :
3+
position:Position.t -> merlin:Document.Merlin.t -> bool Fiber.t

ocaml-lsp-server/src/compl.ml

+92-68
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,13 @@ module Complete_with_construct = struct
242242
end
243243

244244
let complete (state : State.t)
245-
({ textDocument = { uri }; position = pos; _ } : CompletionParams.t) =
245+
({ textDocument = { uri }; position = pos; context; _ } :
246+
CompletionParams.t) =
246247
Fiber.of_thunk (fun () ->
247248
let doc = Document_store.get state.store uri in
248249
match Document.kind doc with
249250
| `Other -> Fiber.return None
250-
| `Merlin merlin ->
251+
| `Merlin merlin -> (
251252
let completion_item_capability =
252253
let open Option.O in
253254
let capabilities = State.client_capabilities state in
@@ -265,75 +266,98 @@ let complete (state : State.t)
265266
| Some { properties } ->
266267
List.mem properties ~equal:String.equal "documentation"
267268
in
268-
let+ items =
269-
let position = Position.logical pos in
270-
let prefix =
271-
prefix_of_position ~short_path:false (Document.source doc) position
272-
in
273-
let deprecated =
274-
Option.value
275-
~default:false
276-
(let open Option.O in
277-
let* item = completion_item_capability in
278-
item.deprecatedSupport)
279-
in
280-
if not (Typed_hole.can_be_hole prefix) then
281-
Complete_by_prefix.complete merlin prefix pos ~resolve ~deprecated
282-
else
283-
let reindex_sortText completion_items =
284-
List.mapi completion_items ~f:(fun idx (ci : CompletionItem.t) ->
285-
let sortText = Some (sortText_of_index idx) in
286-
{ ci with sortText })
287-
in
288-
let preselect_first =
289-
match
290-
let open Option.O in
291-
let* item = completion_item_capability in
292-
item.preselectSupport
293-
with
294-
| None | Some false -> fun x -> x
295-
| Some true -> (
296-
function
297-
| [] -> []
298-
| ci :: rest ->
299-
{ ci with CompletionItem.preselect = Some true } :: rest)
300-
in
301-
let+ construct_cmd_resp, compl_by_prefix_resp =
302-
Document.Merlin.with_pipeline_exn
303-
~name:"completion"
304-
merlin
305-
(fun pipeline ->
306-
let construct_cmd_resp =
307-
Complete_with_construct.dispatch_cmd position pipeline
308-
in
309-
let compl_by_prefix_resp =
310-
Complete_by_prefix.dispatch_cmd ~prefix position pipeline
311-
in
312-
(construct_cmd_resp, compl_by_prefix_resp))
313-
in
314-
let construct_completionItems =
315-
let supportsJumpToNextHole =
316-
State.experimental_client_capabilities state
317-
|> Client.Experimental_capabilities.supportsJumpToNextHole
269+
let* should_provide_completions =
270+
match context with
271+
| Some context -> (
272+
match context.triggerKind with
273+
| TriggerCharacter -> (
274+
let+ inside_comment =
275+
Check_for_comments.position_in_comment ~position:pos ~merlin
318276
in
319-
Complete_with_construct.process_dispatch_resp
320-
~supportsJumpToNextHole
321-
construct_cmd_resp
277+
match inside_comment with
278+
| true -> `Ignore
279+
| false -> `Provide_completions)
280+
| Invoked | TriggerForIncompleteCompletions ->
281+
Fiber.return `Provide_completions)
282+
| None -> Fiber.return `Provide_completions
283+
in
284+
match should_provide_completions with
285+
| `Ignore -> Fiber.return None
286+
| `Provide_completions ->
287+
let+ items =
288+
let position = Position.logical pos in
289+
let prefix =
290+
prefix_of_position
291+
~short_path:false
292+
(Document.source doc)
293+
position
322294
in
323-
let compl_by_prefix_completionItems =
324-
Complete_by_prefix.process_dispatch_resp
325-
~resolve
326-
~deprecated
327-
merlin
328-
pos
329-
compl_by_prefix_resp
295+
let deprecated =
296+
Option.value
297+
~default:false
298+
(let open Option.O in
299+
let* item = completion_item_capability in
300+
item.deprecatedSupport)
330301
in
331-
construct_completionItems @ compl_by_prefix_completionItems
332-
|> reindex_sortText |> preselect_first
333-
in
334-
Some
335-
(`CompletionList
336-
(CompletionList.create ~isIncomplete:false ~items ())))
302+
if not (Typed_hole.can_be_hole prefix) then
303+
Complete_by_prefix.complete merlin prefix pos ~resolve ~deprecated
304+
else
305+
let reindex_sortText completion_items =
306+
List.mapi
307+
completion_items
308+
~f:(fun idx (ci : CompletionItem.t) ->
309+
let sortText = Some (sortText_of_index idx) in
310+
{ ci with sortText })
311+
in
312+
let preselect_first =
313+
match
314+
let open Option.O in
315+
let* item = completion_item_capability in
316+
item.preselectSupport
317+
with
318+
| None | Some false -> fun x -> x
319+
| Some true -> (
320+
function
321+
| [] -> []
322+
| ci :: rest ->
323+
{ ci with CompletionItem.preselect = Some true } :: rest)
324+
in
325+
let+ construct_cmd_resp, compl_by_prefix_resp =
326+
Document.Merlin.with_pipeline_exn
327+
~name:"completion"
328+
merlin
329+
(fun pipeline ->
330+
let construct_cmd_resp =
331+
Complete_with_construct.dispatch_cmd position pipeline
332+
in
333+
let compl_by_prefix_resp =
334+
Complete_by_prefix.dispatch_cmd ~prefix position pipeline
335+
in
336+
(construct_cmd_resp, compl_by_prefix_resp))
337+
in
338+
let construct_completionItems =
339+
let supportsJumpToNextHole =
340+
State.experimental_client_capabilities state
341+
|> Client.Experimental_capabilities.supportsJumpToNextHole
342+
in
343+
Complete_with_construct.process_dispatch_resp
344+
~supportsJumpToNextHole
345+
construct_cmd_resp
346+
in
347+
let compl_by_prefix_completionItems =
348+
Complete_by_prefix.process_dispatch_resp
349+
~resolve
350+
~deprecated
351+
merlin
352+
pos
353+
compl_by_prefix_resp
354+
in
355+
construct_completionItems @ compl_by_prefix_completionItems
356+
|> reindex_sortText |> preselect_first
357+
in
358+
Some
359+
(`CompletionList
360+
(CompletionList.create ~isIncomplete:false ~items ()))))
337361

338362
let format_doc ~markdown doc =
339363
match markdown with

ocaml-lsp-server/src/import.ml

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ module Asttypes = Ocaml_parsing.Asttypes
108108
module Cmt_format = Ocaml_typing.Cmt_format
109109
module Ident = Ocaml_typing.Ident
110110
module Env = Ocaml_typing.Env
111+
module Merlin_parsing = Ocaml_parsing
111112

112113
module Loc = struct
113114
module T = struct

ocaml-lsp-server/src/signature_help.ml

+11-5
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,17 @@ let run (state : State.t)
197197
Fiber.return help
198198
| `Merlin merlin -> (
199199
let* application_signature =
200-
Document.Merlin.with_pipeline_exn merlin (fun pipeline ->
201-
let typer = Mpipeline.typer_result pipeline in
202-
let pos = Mpipeline.get_lexing_pos pipeline pos in
203-
let node = Mtyper.node_at typer pos in
204-
application_signature node ~prefix)
200+
let* inside_comment =
201+
Check_for_comments.position_in_comment ~position ~merlin
202+
in
203+
match inside_comment with
204+
| true -> Fiber.return None
205+
| false ->
206+
Document.Merlin.with_pipeline_exn merlin (fun pipeline ->
207+
let typer = Mpipeline.typer_result pipeline in
208+
let pos = Mpipeline.get_lexing_pos pipeline pos in
209+
let node = Mtyper.node_at typer pos in
210+
application_signature node ~prefix)
205211
in
206212
match application_signature with
207213
| None ->

ocaml-lsp-server/test/e2e/__tests__/textDocument-signatureHelp.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ describe_opt("textDocument/completion", () => {
327327
`,
328328
);
329329

330-
let items = await querySignatureHelp(Types.Position.create(23, 13));
330+
let items = await querySignatureHelp(Types.Position.create(80, 13));
331331
expect(items).toMatchObject({
332332
activeSignature: 0,
333333
activeParameter: 0,

0 commit comments

Comments
 (0)