Skip to content

Commit 7e54962

Browse files
committed
implement completionResolve LSP request and resolve file module docs async
1 parent 7220f57 commit 7e54962

16 files changed

+224
-27
lines changed

analysis/bin/main.ml

+2
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ let main () =
115115
Commands.completion ~debug ~path
116116
~pos:(int_of_string line, int_of_string col)
117117
~currentFile
118+
| [_; "completionResolve"; path; modulePath] ->
119+
Commands.completionResolve ~path ~modulePath
118120
| [_; "definition"; path; line; col] ->
119121
Commands.definition ~path
120122
~pos:(int_of_string line, int_of_string col)

analysis/src/Commands.ml

+35
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,36 @@ let completion ~debug ~path ~pos ~currentFile =
1111
in
1212
completions |> Protocol.array |> print_endline
1313

14+
let completionResolve ~path ~modulePath =
15+
(* We ignore the internal module path as of now because there's currently
16+
no use case for it. But, if we wanted to move resolving documentation
17+
for regular modules and not just file modules to the completionResolve
18+
hook as well, it'd be easy to implement here. *)
19+
let moduleName, _innerModulePath =
20+
match modulePath |> String.split_on_char '.' with
21+
| [moduleName] -> (moduleName, [])
22+
| moduleName :: rest -> (moduleName, rest)
23+
| [] -> raise (Failure "Invalid module path.")
24+
in
25+
let docstring =
26+
match Cmt.loadFullCmtFromPath ~path with
27+
| None ->
28+
if Debug.verbose () then
29+
Printf.printf "[completion_resolve] Could not load cmt\n";
30+
Protocol.null
31+
| Some full -> (
32+
match ProcessCmt.fileForModule ~package:full.package moduleName with
33+
| None ->
34+
if Debug.verbose () then
35+
Printf.printf "[completion_resolve] Did not find file for module %s\n"
36+
moduleName;
37+
Protocol.null
38+
| Some file ->
39+
file.structure.docstring |> String.concat "\n\n"
40+
|> Protocol.wrapInQuotes)
41+
in
42+
print_endline docstring
43+
1444
let inlayhint ~path ~pos ~maxLength ~debug =
1545
let result =
1646
match Hint.inlay ~path ~pos ~maxLength ~debug with
@@ -320,6 +350,11 @@ let test ~path =
320350
let currentFile = createCurrentFile () in
321351
completion ~debug:true ~path ~pos:(line, col) ~currentFile;
322352
Sys.remove currentFile
353+
| "cre" ->
354+
let modulePath = String.sub rest 3 (String.length rest - 3) in
355+
let modulePath = String.trim modulePath in
356+
print_endline ("Completion resolve: " ^ modulePath);
357+
completionResolve ~path ~modulePath
323358
| "dce" ->
324359
print_endline ("DCE " ^ path);
325360
Reanalyze.RunConfig.runConfig.suppress <- ["src"];

analysis/src/CompletionBackEnd.ml

+9-2
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,11 @@ let kindToDetail name (kind : Completion.kind) =
325325
| ExtractedType (extractedType, _) ->
326326
TypeUtils.extractedTypeToString ~nameOnly:true extractedType
327327

328+
let kindToData filePath (kind : Completion.kind) =
329+
match kind with
330+
| FileModule f -> Some [("modulePath", f); ("filePath", filePath)]
331+
| _ -> None
332+
328333
let findAllCompletions ~(env : QueryEnv.t) ~prefix ~exact ~namesUsed
329334
~(completionContext : Completable.completionContext) =
330335
Log.log ("findAllCompletions uri:" ^ Uri.toString env.file.uri);
@@ -648,7 +653,7 @@ let rec digToRecordFieldsForCompletion ~debug ~package ~opens ~full ~pos ~env
648653
| {kind = Type {kind = Record fields}} :: _ -> Some fields
649654
| _ -> None
650655

651-
let mkItem ~name ~kind ~detail ~deprecated ~docstring =
656+
let mkItem ?data name ~kind ~detail ~deprecated ~docstring =
652657
let docContent =
653658
(match deprecated with
654659
| None -> ""
@@ -676,6 +681,7 @@ let mkItem ~name ~kind ~detail ~deprecated ~docstring =
676681
insertText = None;
677682
insertTextFormat = None;
678683
filterText = None;
684+
data;
679685
}
680686

681687
let completionToItem
@@ -692,7 +698,8 @@ let completionToItem
692698
env;
693699
} ~full =
694700
let item =
695-
mkItem ~name
701+
mkItem name
702+
?data:(kindToData (full.file.uri |> Uri.toPath) kind)
696703
~kind:(Completion.kindToInt kind)
697704
~deprecated
698705
~detail:

analysis/src/Protocol.ml

+9
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type completionItem = {
5050
insertTextFormat: insertTextFormat option;
5151
insertText: string option;
5252
documentation: markupContent option;
53+
data: (string * string) list option;
5354
}
5455

5556
type location = {uri: string; range: range}
@@ -139,6 +140,14 @@ let stringifyCompletionItem c =
139140
| None -> None
140141
| Some insertTextFormat ->
141142
Some (Printf.sprintf "%i" (insertTextFormatToInt insertTextFormat)) );
143+
( "data",
144+
match c.data with
145+
| None -> None
146+
| Some fields ->
147+
Some
148+
(fields
149+
|> List.map (fun (key, value) -> (key, Some (wrapInQuotes value)))
150+
|> stringifyObject ~indentation:2) );
142151
]
143152

144153
let stringifyHover value =

analysis/src/SharedTypes.ml

+4-2
Original file line numberDiff line numberDiff line change
@@ -800,10 +800,11 @@ module Completion = struct
800800
kind: kind;
801801
detail: string option;
802802
typeArgContext: typeArgContext option;
803+
data: (string * string) list option;
803804
}
804805

805-
let create ?typeArgContext ?(includesSnippets = false) ?insertText ~kind ~env
806-
?sortText ?deprecated ?filterText ?detail ?(docstring = []) name =
806+
let create ?data ?typeArgContext ?(includesSnippets = false) ?insertText ~kind
807+
~env ?sortText ?deprecated ?filterText ?detail ?(docstring = []) name =
807808
{
808809
name;
809810
env;
@@ -817,6 +818,7 @@ module Completion = struct
817818
filterText;
818819
detail;
819820
typeArgContext;
821+
data;
820822
}
821823

822824
(* https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion *)
+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// ^cre Belt_Array
2+
3+
// ^cre ModuleStuff
4+

analysis/tests/src/ModuleStuff.res

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/*** This is a top level module doc. */
2+
3+
module Nested = {
4+
/*** Module doc for nested. */
5+
}

analysis/tests/src/expected/Completion.res.txt

+35-7
Original file line numberDiff line numberDiff line change
@@ -878,13 +878,21 @@ Path Lis
878878
"kind": 9,
879879
"tags": [],
880880
"detail": "module List",
881-
"documentation": null
881+
"documentation": null,
882+
"data": {
883+
"modulePath": "List",
884+
"filePath": "src/Completion.res"
885+
}
882886
}, {
883887
"label": "ListLabels",
884888
"kind": 9,
885889
"tags": [],
886890
"detail": "module ListLabels",
887-
"documentation": null
891+
"documentation": null,
892+
"data": {
893+
"modulePath": "ListLabels",
894+
"filePath": "src/Completion.res"
895+
}
888896
}]
889897

890898
Complete src/Completion.res 169:16
@@ -1648,13 +1656,21 @@ Path Res
16481656
"kind": 9,
16491657
"tags": [],
16501658
"detail": "module RescriptReactErrorBoundary",
1651-
"documentation": null
1659+
"documentation": null,
1660+
"data": {
1661+
"modulePath": "RescriptReactErrorBoundary",
1662+
"filePath": "src/Completion.res"
1663+
}
16521664
}, {
16531665
"label": "RescriptReactRouter",
16541666
"kind": 9,
16551667
"tags": [],
16561668
"detail": "module RescriptReactRouter",
1657-
"documentation": null
1669+
"documentation": null,
1670+
"data": {
1671+
"modulePath": "RescriptReactRouter",
1672+
"filePath": "src/Completion.res"
1673+
}
16581674
}]
16591675

16601676
Complete src/Completion.res 343:57
@@ -1765,19 +1781,31 @@ Path T
17651781
"kind": 9,
17661782
"tags": [],
17671783
"detail": "module TableclothMap",
1768-
"documentation": null
1784+
"documentation": null,
1785+
"data": {
1786+
"modulePath": "TableclothMap",
1787+
"filePath": "src/Completion.res"
1788+
}
17691789
}, {
17701790
"label": "TypeAtPosCompletion",
17711791
"kind": 9,
17721792
"tags": [],
17731793
"detail": "module TypeAtPosCompletion",
1774-
"documentation": null
1794+
"documentation": null,
1795+
"data": {
1796+
"modulePath": "TypeAtPosCompletion",
1797+
"filePath": "src/Completion.res"
1798+
}
17751799
}, {
17761800
"label": "TypeDefinition",
17771801
"kind": 9,
17781802
"tags": [],
17791803
"detail": "module TypeDefinition",
1780-
"documentation": null
1804+
"documentation": null,
1805+
"data": {
1806+
"modulePath": "TypeDefinition",
1807+
"filePath": "src/Completion.res"
1808+
}
17811809
}]
17821810

17831811
Complete src/Completion.res 373:21

analysis/tests/src/expected/CompletionFunctionArguments.res.txt

+25-5
Original file line numberDiff line numberDiff line change
@@ -176,13 +176,21 @@ Path someFnTakingVariant
176176
"kind": 9,
177177
"tags": [],
178178
"detail": "module Obj",
179-
"documentation": null
179+
"documentation": null,
180+
"data": {
181+
"modulePath": "Obj",
182+
"filePath": "src/CompletionFunctionArguments.res"
183+
}
180184
}, {
181185
"label": "Objects",
182186
"kind": 9,
183187
"tags": [],
184188
"detail": "module Objects",
185-
"documentation": null
189+
"documentation": null,
190+
"data": {
191+
"modulePath": "Objects",
192+
"filePath": "src/CompletionFunctionArguments.res"
193+
}
186194
}]
187195

188196
Complete src/CompletionFunctionArguments.res 57:33
@@ -208,7 +216,11 @@ Path someFnTakingVariant
208216
"kind": 9,
209217
"tags": [],
210218
"detail": "module Sort",
211-
"documentation": null
219+
"documentation": null,
220+
"data": {
221+
"modulePath": "Sort",
222+
"filePath": "src/CompletionFunctionArguments.res"
223+
}
212224
}]
213225

214226
Complete src/CompletionFunctionArguments.res 60:44
@@ -240,13 +252,21 @@ Path someFnTakingVariant
240252
"kind": 9,
241253
"tags": [],
242254
"detail": "module Obj",
243-
"documentation": null
255+
"documentation": null,
256+
"data": {
257+
"modulePath": "Obj",
258+
"filePath": "src/CompletionFunctionArguments.res"
259+
}
244260
}, {
245261
"label": "Objects",
246262
"kind": 9,
247263
"tags": [],
248264
"detail": "module Objects",
249-
"documentation": null
265+
"documentation": null,
266+
"data": {
267+
"modulePath": "Objects",
268+
"filePath": "src/CompletionFunctionArguments.res"
269+
}
250270
}]
251271

252272
Complete src/CompletionFunctionArguments.res 63:23

analysis/tests/src/expected/CompletionJsxProps.res.txt

+15-3
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,31 @@ Path CompletionSupport.TestComponent.make
6767
"kind": 9,
6868
"tags": [],
6969
"detail": "module TableclothMap",
70-
"documentation": null
70+
"documentation": null,
71+
"data": {
72+
"modulePath": "TableclothMap",
73+
"filePath": "src/CompletionJsxProps.res"
74+
}
7175
}, {
7276
"label": "TypeAtPosCompletion",
7377
"kind": 9,
7478
"tags": [],
7579
"detail": "module TypeAtPosCompletion",
76-
"documentation": null
80+
"documentation": null,
81+
"data": {
82+
"modulePath": "TypeAtPosCompletion",
83+
"filePath": "src/CompletionJsxProps.res"
84+
}
7785
}, {
7886
"label": "TypeDefinition",
7987
"kind": 9,
8088
"tags": [],
8189
"detail": "module TypeDefinition",
82-
"documentation": null
90+
"documentation": null,
91+
"data": {
92+
"modulePath": "TypeDefinition",
93+
"filePath": "src/CompletionJsxProps.res"
94+
}
8395
}]
8496

8597
Complete src/CompletionJsxProps.res 9:52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Completion resolve: Belt_Array
2+
"\nUtilities for `Array` functions.\n\n### Note about index syntax\n\nCode like `arr[0]` does *not* compile to JavaScript `arr[0]`. Reason transforms\nthe `[]` index syntax into a function: `Array.get(arr, 0)`. By default, this\nuses the default standard library's `Array.get` function, which may raise an\nexception if the index isn't found. If you `open Belt`, it will use the\n`Belt.Array.get` function which returns options instead of raising exceptions. \n[See this for more information](../belt.mdx#array-access-runtime-safety).\n"
3+
4+
Completion resolve: ModuleStuff
5+
" This is a top level module doc. "
6+

analysis/tests/src/expected/CompletionTypeAnnotation.res.txt

+10-2
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,21 @@ Path someVariant
8383
"kind": 9,
8484
"tags": [],
8585
"detail": "module Obj",
86-
"documentation": null
86+
"documentation": null,
87+
"data": {
88+
"modulePath": "Obj",
89+
"filePath": "src/CompletionTypeAnnotation.res"
90+
}
8791
}, {
8892
"label": "Objects",
8993
"kind": 9,
9094
"tags": [],
9195
"detail": "module Objects",
92-
"documentation": null
96+
"documentation": null,
97+
"data": {
98+
"modulePath": "Objects",
99+
"filePath": "src/CompletionTypeAnnotation.res"
100+
}
93101
}]
94102

95103
Complete src/CompletionTypeAnnotation.res 21:27

0 commit comments

Comments
 (0)