|
1 | 1 | open SharedTypes
|
2 | 2 | type cursorAtArg = Unlabelled of int | Labelled of string
|
3 | 3 |
|
4 |
| -let findFunctionType ~currentFile ~debug ~path ~pos = |
5 |
| - let completables = |
6 |
| - let textOpt = Files.readFile currentFile in |
7 |
| - match textOpt with |
8 |
| - | None | Some "" -> None |
9 |
| - | Some text -> ( |
10 |
| - (* Leverage the completion functionality to pull out the type of the identifier doing the function application. |
11 |
| - This lets us leverage all of the smart work done in completions to find the correct type in many cases even |
12 |
| - for files not saved yet. *) |
13 |
| - match |
14 |
| - CompletionFrontEnd.completionWithParser ~debug ~path ~posCursor:pos |
15 |
| - ~currentFile ~text |
16 |
| - with |
17 |
| - | None -> None |
18 |
| - | Some (completable, scope) -> ( |
19 |
| - match Cmt.loadFullCmtFromPath ~path with |
20 |
| - | None -> None |
21 |
| - | Some full -> |
22 |
| - let {file; package} = full in |
23 |
| - let env = QueryEnv.fromFile file in |
| 4 | +let shouldPrintMainTypeStr typ ~env ~package = |
| 5 | + match typ |> Shared.digConstructor with |
| 6 | + | Some path -> ( |
| 7 | + match References.digConstructor ~env ~package path with |
| 8 | + | Some (_, {item = {kind = Record _}}) -> false |
| 9 | + | _ -> true) |
| 10 | + | _ -> false |
| 11 | + |
| 12 | +(* Produces the doc string shown below the signature help for each parameter. *) |
| 13 | +let docsForLabel typeExpr ~file ~package ~supportsMarkdownLinks = |
| 14 | + let env = QueryEnv.fromFile file in |
| 15 | + let types = Hover.findRelevantTypesFromType ~file ~package typeExpr in |
| 16 | + let typeString = |
| 17 | + if shouldPrintMainTypeStr typeExpr ~env ~package then |
| 18 | + Markdown.codeBlock (typeExpr |> Shared.typeToString) |
| 19 | + else "" |
| 20 | + in |
| 21 | + let typeNames = types |> List.map (fun {Hover.name} -> name) in |
| 22 | + let typeDefinitions = |
| 23 | + types |
| 24 | + |> List.map (fun {Hover.decl; name; env; loc; path} -> |
| 25 | + let linkToTypeDefinitionStr = |
| 26 | + if supportsMarkdownLinks then |
| 27 | + Markdown.goToDefinitionText ~env ~pos:loc.Warnings.loc_start |
| 28 | + else "" |
| 29 | + in |
| 30 | + (* Since printing the whole name via its path can get quite long, and |
| 31 | + we're short on space for the signature help, we'll only print the |
| 32 | + fully "qualified" type name if we must (ie if several types we're |
| 33 | + displaying have the same name). *) |
| 34 | + let multipleTypesHaveThisName = |
| 35 | + typeNames |
| 36 | + |> List.filter (fun typeName -> typeName = name) |
| 37 | + |> List.length > 1 |
| 38 | + in |
| 39 | + let typeName = |
| 40 | + if multipleTypesHaveThisName then |
| 41 | + path |> SharedTypes.pathIdentToString |
| 42 | + else name |
| 43 | + in |
| 44 | + Markdown.codeBlock |
| 45 | + (Shared.declToString ~printNameAsIs:true typeName decl) |
| 46 | + ^ linkToTypeDefinitionStr) |
| 47 | + in |
| 48 | + typeString :: typeDefinitions |> String.concat "\n" |
| 49 | + |
| 50 | +let findFunctionType ~currentFile ~debug ~path ~pos ~supportsMarkdownLinks = |
| 51 | + (* Start by looking at the typed info at the loc of the fn *) |
| 52 | + match Cmt.loadFullCmtFromPath ~path with |
| 53 | + | None -> None |
| 54 | + | Some full -> ( |
| 55 | + let {file; package} = full in |
| 56 | + let env = QueryEnv.fromFile file in |
| 57 | + let fnFromLocItem = |
| 58 | + match References.getLocItem ~full ~pos ~debug:false with |
| 59 | + | Some {locType = Typed (_, typeExpr, _)} -> ( |
| 60 | + if Debug.verbose () then |
| 61 | + Printf.printf "[sig_help_fn] Found loc item: %s.\n" |
| 62 | + (Shared.typeToString typeExpr); |
| 63 | + match |
| 64 | + TypeUtils.extractFunctionType2 ~env ~package:full.package typeExpr |
| 65 | + with |
| 66 | + | args, _tRet, _ when args <> [] -> |
24 | 67 | Some
|
25 |
| - ( completable |
26 |
| - |> CompletionBackEnd.processCompletable ~debug ~full ~pos ~scope |
27 |
| - ~env ~forHover:true, |
28 |
| - env, |
| 68 | + ( args, |
| 69 | + [docsForLabel ~file ~package ~supportsMarkdownLinks typeExpr], |
| 70 | + typeExpr, |
29 | 71 | package,
|
30 |
| - file ))) |
31 |
| - in |
32 |
| - match completables with |
33 |
| - | Some ({kind = Value type_expr; docstring} :: _, env, package, file) -> |
34 |
| - let args, _ = TypeUtils.extractFunctionType type_expr ~env ~package in |
35 |
| - Some (args, docstring, type_expr, package, env, file) |
36 |
| - | _ -> None |
| 72 | + env, |
| 73 | + file ) |
| 74 | + | _ -> None) |
| 75 | + | None -> |
| 76 | + if Debug.verbose () then |
| 77 | + Printf.printf "[sig_help_fn] Found no loc item.\n"; |
| 78 | + None |
| 79 | + | Some _ -> |
| 80 | + if Debug.verbose () then |
| 81 | + Printf.printf |
| 82 | + "[sig_help_fn] Found loc item, but not what was expected.\n"; |
| 83 | + None |
| 84 | + in |
| 85 | + match fnFromLocItem with |
| 86 | + | Some fnFromLocItem -> Some fnFromLocItem |
| 87 | + | None -> ( |
| 88 | + (* If nothing was found there, try using the unsaved completion engine *) |
| 89 | + let completables = |
| 90 | + let textOpt = Files.readFile currentFile in |
| 91 | + match textOpt with |
| 92 | + | None | Some "" -> None |
| 93 | + | Some text -> ( |
| 94 | + (* Leverage the completion functionality to pull out the type of the identifier doing the function application. |
| 95 | + This lets us leverage all of the smart work done in completions to find the correct type in many cases even |
| 96 | + for files not saved yet. *) |
| 97 | + match |
| 98 | + CompletionFrontEnd.completionWithParser ~debug ~path ~posCursor:pos |
| 99 | + ~currentFile ~text |
| 100 | + with |
| 101 | + | None -> None |
| 102 | + | Some (completable, scope) -> |
| 103 | + Some |
| 104 | + ( completable |
| 105 | + |> CompletionBackEnd.processCompletable ~debug ~full ~pos ~scope |
| 106 | + ~env ~forHover:true, |
| 107 | + env, |
| 108 | + package, |
| 109 | + file )) |
| 110 | + in |
| 111 | + match completables with |
| 112 | + | Some ({kind = Value type_expr; docstring} :: _, env, package, file) -> |
| 113 | + let args, _, _ = |
| 114 | + TypeUtils.extractFunctionType2 type_expr ~env ~package |
| 115 | + in |
| 116 | + Some (args, docstring, type_expr, package, env, file) |
| 117 | + | _ -> None)) |
37 | 118 |
|
38 | 119 | (* Extracts all parameters from a parsed function signature *)
|
39 | 120 | let extractParameters ~signature ~typeStrForParser ~labelPrefixLen =
|
@@ -126,52 +207,6 @@ let findActiveParameter ~argAtCursor ~args =
|
126 | 207 | index := !index + 1;
|
127 | 208 | None)
|
128 | 209 |
|
129 |
| -let shouldPrintMainTypeStr typ ~env ~package = |
130 |
| - match typ |> Shared.digConstructor with |
131 |
| - | Some path -> ( |
132 |
| - match References.digConstructor ~env ~package path with |
133 |
| - | Some (_, {item = {kind = Record _}}) -> false |
134 |
| - | _ -> true) |
135 |
| - | _ -> false |
136 |
| - |
137 |
| -(* Produces the doc string shown below the signature help for each parameter. *) |
138 |
| -let docsForLabel typeExpr ~file ~package ~supportsMarkdownLinks = |
139 |
| - let env = QueryEnv.fromFile file in |
140 |
| - let types = Hover.findRelevantTypesFromType ~file ~package typeExpr in |
141 |
| - let typeString = |
142 |
| - if shouldPrintMainTypeStr typeExpr ~env ~package then |
143 |
| - Markdown.codeBlock (typeExpr |> Shared.typeToString) |
144 |
| - else "" |
145 |
| - in |
146 |
| - let typeNames = types |> List.map (fun {Hover.name} -> name) in |
147 |
| - let typeDefinitions = |
148 |
| - types |
149 |
| - |> List.map (fun {Hover.decl; name; env; loc; path} -> |
150 |
| - let linkToTypeDefinitionStr = |
151 |
| - if supportsMarkdownLinks then |
152 |
| - Markdown.goToDefinitionText ~env ~pos:loc.Warnings.loc_start |
153 |
| - else "" |
154 |
| - in |
155 |
| - (* Since printing the whole name via its path can get quite long, and |
156 |
| - we're short on space for the signature help, we'll only print the |
157 |
| - fully "qualified" type name if we must (ie if several types we're |
158 |
| - displaying have the same name). *) |
159 |
| - let multipleTypesHaveThisName = |
160 |
| - typeNames |
161 |
| - |> List.filter (fun typeName -> typeName = name) |
162 |
| - |> List.length > 1 |
163 |
| - in |
164 |
| - let typeName = |
165 |
| - if multipleTypesHaveThisName then |
166 |
| - path |> SharedTypes.pathIdentToString |
167 |
| - else name |
168 |
| - in |
169 |
| - Markdown.codeBlock |
170 |
| - (Shared.declToString ~printNameAsIs:true typeName decl) |
171 |
| - ^ linkToTypeDefinitionStr) |
172 |
| - in |
173 |
| - typeString :: typeDefinitions |> String.concat "\n" |
174 |
| - |
175 | 210 | let findConstructorArgs ~full ~env ~constructorName loc =
|
176 | 211 | match
|
177 | 212 | References.getLocItem ~debug:false ~full
|
@@ -232,10 +267,11 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
|
232 | 267 | of %s\n"
|
233 | 268 | (printThing thing) (printThing currentThing)
|
234 | 269 | | Some (_, currentThing) ->
|
235 |
| - Printf.printf |
236 |
| - "[sig_help_result] Doing nothing because loc of %s < then \ |
237 |
| - existing of %s\n" |
238 |
| - (printThing thing) (printThing currentThing)) |
| 270 | + if Debug.verbose () then |
| 271 | + Printf.printf |
| 272 | + "[sig_help_result] Doing nothing because loc of %s < then \ |
| 273 | + existing of %s\n" |
| 274 | + (printThing thing) (printThing currentThing)) |
239 | 275 | in
|
240 | 276 | let searchForArgWithCursor ~isPipeExpr ~args =
|
241 | 277 | let extractedArgs = extractExpApplyArgs ~args in
|
@@ -358,7 +394,9 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
|
358 | 394 | | Some (_, `FunctionCall (argAtCursor, exp, _extractedArgs)) -> (
|
359 | 395 | (* Not looking for the cursor position after this, but rather the target function expression's loc. *)
|
360 | 396 | let pos = exp.pexp_loc |> Loc.end_ in
|
361 |
| - match findFunctionType ~currentFile ~debug ~path ~pos with |
| 397 | + match |
| 398 | + findFunctionType ~currentFile ~debug ~path ~pos ~supportsMarkdownLinks |
| 399 | + with |
362 | 400 | | Some (args, docstring, type_expr, package, _env, file) ->
|
363 | 401 | if debug then
|
364 | 402 | Printf.printf "argAtCursor: %s\n"
|
|
0 commit comments