Skip to content

Commit ef94d47

Browse files
committed
Show type when hovering on JSX props.
Fixes #314
1 parent 443f5d1 commit ef94d47

File tree

8 files changed

+90
-44
lines changed

8 files changed

+90
-44
lines changed

analysis/src/Cli.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,17 @@ let main () =
7070
| [_; "completion"; path; line; col; currentFile] ->
7171
Commands.completion ~debug:false ~path
7272
~pos:(int_of_string line, int_of_string col)
73-
~currentFile ~forHover:false
73+
~currentFile
7474
| [_; "definition"; path; line; col] ->
7575
Commands.definition ~path ~line:(int_of_string line)
7676
~col:(int_of_string col)
7777
| [_; "typeDefinition"; path; line; col] ->
7878
Commands.typeDefinition ~path ~line:(int_of_string line)
7979
~col:(int_of_string col)
8080
| [_; "documentSymbol"; path] -> DocumentSymbol.command ~path
81-
| [_; "hover"; path; line; col] ->
81+
| [_; "hover"; path; line; col; currentFile] ->
8282
Commands.hover ~path ~line:(int_of_string line) ~col:(int_of_string col)
83+
~currentFile ~debug:false
8384
| [_; "codeAction"; path; line; col; currentFile] ->
8485
Commands.codeAction ~path ~line:(int_of_string line)
8586
~col:(int_of_string col) ~currentFile

analysis/src/Commands.ml

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,49 @@
1-
let completion ~debug ~path ~pos ~currentFile ~forHover =
2-
let result =
3-
let textOpt = Files.readFile currentFile in
4-
match textOpt with
5-
| None | Some "" -> []
6-
| Some text ->
7-
let completions =
8-
match
9-
CompletionFrontEnd.completionWithParser ~debug ~path ~posCursor:pos
10-
~currentFile ~text
11-
with
12-
| None -> []
13-
| Some (completable, scope) -> (
14-
if debug then
15-
Printf.printf "Completable: %s\n"
16-
(SharedTypes.Completable.toString completable);
17-
(* Only perform expensive ast operations if there are completables *)
18-
match Cmt.fromPath ~path with
19-
| None -> []
20-
| Some full ->
21-
let env = SharedTypes.QueryEnv.fromFile full.file in
22-
let package = full.package in
23-
completable
24-
|> CompletionBackEnd.processCompletable ~debug ~package ~pos ~scope
25-
~env ~forHover)
26-
in
27-
completions |> List.map CompletionBackEnd.completionToItem
28-
in
1+
let getCompletions ~debug ~path ~pos ~currentFile ~forHover =
2+
let textOpt = Files.readFile currentFile in
3+
match textOpt with
4+
| None | Some "" -> []
5+
| Some text -> (
6+
match
7+
CompletionFrontEnd.completionWithParser ~debug ~path ~posCursor:pos
8+
~currentFile ~text
9+
with
10+
| None -> []
11+
| Some (completable, scope) -> (
12+
if debug then
13+
Printf.printf "Completable: %s\n"
14+
(SharedTypes.Completable.toString completable);
15+
(* Only perform expensive ast operations if there are completables *)
16+
match Cmt.fromPath ~path with
17+
| None -> []
18+
| Some full ->
19+
let env = SharedTypes.QueryEnv.fromFile full.file in
20+
let package = full.package in
21+
completable
22+
|> CompletionBackEnd.processCompletable ~debug ~package ~pos ~scope ~env
23+
~forHover))
24+
25+
let completion ~debug ~path ~pos ~currentFile =
2926
print_endline
30-
(result |> List.map Protocol.stringifyCompletionItem |> Protocol.array)
27+
(getCompletions ~debug ~path ~pos ~currentFile ~forHover:false
28+
|> List.map CompletionBackEnd.completionToItem
29+
|> List.map Protocol.stringifyCompletionItem
30+
|> Protocol.array)
3131

32-
let hover ~path ~line ~col =
32+
let hover ~path ~line ~col ~currentFile ~debug =
3333
let result =
3434
match Cmt.fromPath ~path with
3535
| None -> Protocol.null
3636
| Some ({file} as full) -> (
3737
match References.getLocItem ~full ~line ~col with
38-
| None -> Protocol.null
38+
| None -> (
39+
let completions =
40+
getCompletions ~debug ~path ~pos:(line, col) ~currentFile
41+
~forHover:true
42+
in
43+
match completions with
44+
| {kind = Label typString} :: _ ->
45+
Protocol.stringifyHover {contents = Hover.codeBlock typString}
46+
| _ -> Protocol.null)
3947
| Some locItem -> (
4048
let isModule =
4149
match locItem.locType with
@@ -273,7 +281,7 @@ let test ~path =
273281
print_endline
274282
("Hover " ^ path ^ " " ^ string_of_int line ^ ":"
275283
^ string_of_int col);
276-
hover ~path ~line ~col
284+
hover ~path ~line ~col ~currentFile:path ~debug:true
277285
| "ref" ->
278286
print_endline
279287
("References " ^ path ^ " " ^ string_of_int line ^ ":"
@@ -316,8 +324,7 @@ let test ~path =
316324
in
317325
Printf.fprintf cout "%s\n" lineToOutput);
318326
close_out cout;
319-
completion ~debug:true ~path ~pos:(line, col) ~currentFile
320-
~forHover:false;
327+
completion ~debug:true ~path ~pos:(line, col) ~currentFile;
321328
Sys.remove currentFile
322329
| "hig" ->
323330
print_endline ("Highlight " ^ path);

analysis/src/CompletionBackEnd.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,7 +1328,7 @@ let processCompletable ~debug ~package ~scope ~env ~pos ~forHover
13281328
| Cpath contextPath ->
13291329
contextPath
13301330
|> getCompletionsForContextPath ~package ~opens ~rawOpens ~allFiles ~pos
1331-
~env ~exact:false ~scope
1331+
~env ~exact:forHover ~scope
13321332
| Cjsx ([id], prefix, identsSeen) when String.uncapitalize_ascii id = id ->
13331333
let mkLabel (name, typString) =
13341334
Completion.create ~name ~kind:(Label typString) ~env
@@ -1338,7 +1338,8 @@ let processCompletable ~debug ~package ~scope ~env ~pos ~forHover
13381338
in
13391339
(domLabels
13401340
|> List.filter (fun (name, _t) ->
1341-
Utils.startsWith name prefix && not (List.mem name identsSeen))
1341+
Utils.startsWith name prefix
1342+
&& (forHover || not (List.mem name identsSeen)))
13421343
|> List.map mkLabel)
13431344
@ keyLabels
13441345
| Cjsx (componentPath, prefix, identsSeen) ->

analysis/src/CompletionFrontEnd.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ let rec exprToContextPath (e : Parsetree.expression) =
211211
| Some contexPath -> Some (CPApply (contexPath, args |> List.map fst)))
212212
| _ -> None
213213

214-
let completionWithParser ~debug ~path ~posCursor ~currentFile ~text =
214+
let completionWithParser ~debug ~path ~posCursor ~currentFile ~text =
215215
let offset =
216216
match positionToOffset text posCursor with
217217
| Some offset -> offset

analysis/tests/src/Completion.res

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,4 +342,7 @@ let _ =
342342
</div>
343343

344344
//let _ = switch Some(3) { | Some(thisIsNotSaved) -> this
345-
// ^com
345+
// ^com
346+
347+
let _ = <div name="" />
348+
// ^hov

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,8 +1307,9 @@ Found type for function (~a: int) => int
13071307
}]
13081308

13091309
Complete tests/src/Completion.res 336:26
1310-
posCursor:[336:26] posNoWhite:[336:25] Found expr:[333:3->341:8]
1311-
JSX <div:[333:3->333:6] onClick[334:4->334:11]=...[334:13->0:-1]> _children:None
1310+
posCursor:[336:26] posNoWhite:[336:25] Found expr:[333:3->346:23]
1311+
JSX <div:[333:3->333:6] onClick[334:4->334:11]=...[334:13->346:23]> _children:None
1312+
posCursor:[336:26] posNoWhite:[336:25] Found expr:[334:13->346:23]
13121313
posCursor:[336:26] posNoWhite:[336:25] Found expr:[334:13->338:6]
13131314
posCursor:[336:26] posNoWhite:[336:25] Found expr:[335:6->338:5]
13141315
posCursor:[336:26] posNoWhite:[336:25] Found expr:[336:16->338:5]
@@ -1330,7 +1331,8 @@ Completable: Cpath Type[Res]
13301331
}]
13311332

13321333
Complete tests/src/Completion.res 343:57
1333-
posCursor:[343:57] posNoWhite:[343:56] Found expr:[343:10->343:57]
1334+
posCursor:[343:57] posNoWhite:[343:56] Found expr:[343:10->346:23]
1335+
posCursor:[343:57] posNoWhite:[343:56] Found expr:[343:53->346:23]
13341336
posCursor:[343:57] posNoWhite:[343:56] Found expr:[343:53->343:57]
13351337
Pexp_ident this:[343:53->343:57]
13361338
Completable: Cpath Value[this]
@@ -1342,3 +1344,9 @@ Completable: Cpath Value[this]
13421344
"documentation": null
13431345
}]
13441346

1347+
Hover tests/src/Completion.res 346:14
1348+
posCursor:[346:14] posNoWhite:[346:13] Found expr:[346:9->346:23]
1349+
JSX <div:[346:9->346:12] name[346:13->346:17]=...[346:18->346:20]> _children:346:21
1350+
Completable: Cjsx([div], name, [name])
1351+
{"contents": "```rescript\nstring\n```"}
1352+

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,12 @@ Hover tests/src/Fragment.res 6:19
22
{"contents": "```rescript\nReact.component<{\"children\": React.element}>\n```\n\n```rescript\ntype component<'props> = componentLike<'props, element>\n```"}
33

44
Hover tests/src/Fragment.res 9:56
5+
posCursor:[9:56] posNoWhite:[9:55] Found expr:[9:10->9:67]
6+
Pexp_construct :::[9:13->9:67] [9:13->9:67]
7+
posCursor:[9:56] posNoWhite:[9:55] Found expr:[9:13->9:67]
8+
posCursor:[9:56] posNoWhite:[9:55] Found expr:[9:13->9:66]
9+
JSX <SectionHeader:[9:13->9:26] > _children:9:26
10+
posCursor:[9:56] posNoWhite:[9:55] Found expr:__ghost__[9:10->9:67]
11+
Pexp_construct []:__ghost__[9:10->9:67] None
512
null
613

server/src/server.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,11 +271,30 @@ if (process.argv.includes("--stdio")) {
271271
function hover(msg: p.RequestMessage) {
272272
let params = msg.params as p.HoverParams;
273273
let filePath = fileURLToPath(params.textDocument.uri);
274+
let extension = path.extname(params.textDocument.uri);
275+
if (extension !== c.resExt && extension !== c.resiExt) {
276+
// Can be called on renamed extension after rename
277+
return {
278+
jsonrpc: c.jsonrpcVersion,
279+
id: msg.id,
280+
result: null,
281+
};
282+
}
283+
let code = getOpenedFileContent(params.textDocument.uri);
284+
let tmpname = utils.createFileInTempDir();
285+
fs.writeFileSync(tmpname, code, { encoding: "utf-8" });
274286
let response = utils.runAnalysisCommand(
275287
filePath,
276-
["hover", filePath, params.position.line, params.position.character],
288+
[
289+
"hover",
290+
filePath,
291+
params.position.line,
292+
params.position.character,
293+
tmpname,
294+
],
277295
msg
278296
);
297+
fs.unlink(tmpname, () => null);
279298
return response;
280299
}
281300

0 commit comments

Comments
 (0)