Skip to content

Investigate heuristics in jump to location. #447

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions analysis/src/Cli.ml
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,22 @@ let main () =
~pos:(int_of_string line, int_of_string col)
~currentFile
| [_; "definition"; path; line; col] ->
Commands.definition ~path ~line:(int_of_string line)
~col:(int_of_string col)
Commands.definition ~path
~pos:(int_of_string line, int_of_string col)
~debug:false
| [_; "typeDefinition"; path; line; col] ->
Commands.typeDefinition ~path ~line:(int_of_string line)
~col:(int_of_string col)
Commands.typeDefinition ~path
~pos:(int_of_string line, int_of_string col)
~debug:false
| [_; "documentSymbol"; path] -> DocumentSymbol.command ~path
| [_; "hover"; path; line; col; currentFile] ->
Commands.hover ~path ~line:(int_of_string line) ~col:(int_of_string col)
Commands.hover ~path
~pos:(int_of_string line, int_of_string col)
~currentFile ~debug:false
| [_; "codeAction"; path; line; col; currentFile] ->
Commands.codeAction ~path ~line:(int_of_string line)
~col:(int_of_string col) ~currentFile
Commands.codeAction ~path
~pos:(int_of_string line, int_of_string col)
~currentFile ~debug:false
| _ :: "reanalyze" :: _ ->
let len = Array.length Sys.argv in
for i = 1 to len - 2 do
Expand All @@ -92,11 +96,13 @@ let main () =
Sys.argv.(len - 1) <- "";
Reanalyze.cli ()
| [_; "references"; path; line; col] ->
Commands.references ~path ~line:(int_of_string line)
~col:(int_of_string col)
Commands.references ~path
~pos:(int_of_string line, int_of_string col)
~debug:false
| [_; "rename"; path; line; col; newName] ->
Commands.rename ~path ~line:(int_of_string line) ~col:(int_of_string col)
~newName
Commands.rename ~path
~pos:(int_of_string line, int_of_string col)
~newName ~debug:false
| [_; "semanticTokens"; currentFile] ->
SemanticTokens.semanticTokens ~currentFile
| [_; "createInterface"; path; cmiFile] ->
Expand Down
38 changes: 19 additions & 19 deletions analysis/src/Commands.ml
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,18 @@ let completion ~debug ~path ~pos ~currentFile =
|> List.map Protocol.stringifyCompletionItem
|> Protocol.array)

let hover ~path ~line ~col ~currentFile ~debug =
let hover ~path ~pos ~currentFile ~debug =
let result =
match Cmt.fullFromPath ~path with
| None -> Protocol.null
| Some full -> (
match References.getLocItem ~full ~line ~col with
match References.getLocItem ~full ~pos ~debug with
| None -> (
if debug then
Printf.printf
"Nothing at that position. Now trying to use completion.\n";
let completions =
getCompletions ~debug ~path ~pos:(line, col) ~currentFile
~forHover:true
getCompletions ~debug ~path ~pos ~currentFile ~forHover:true
in
match completions with
| {kind = Label typString; docstring} :: _ ->
Expand Down Expand Up @@ -81,16 +80,16 @@ let hover ~path ~line ~col ~currentFile ~debug =
in
print_endline result

let codeAction ~path ~line ~col ~currentFile =
Xform.extractCodeActions ~path ~pos:(line, col) ~currentFile
let codeAction ~path ~pos ~currentFile ~debug =
Xform.extractCodeActions ~path ~pos ~currentFile ~debug
|> CodeActions.stringifyCodeActions |> print_endline

let definition ~path ~line ~col =
let definition ~path ~pos ~debug =
let locationOpt =
match Cmt.fullFromPath ~path with
| None -> None
| Some full -> (
match References.getLocItem ~full ~line ~col with
match References.getLocItem ~full ~pos ~debug with
| None -> None
| Some locItem -> (
match References.definitionForLocItem ~full locItem with
Expand Down Expand Up @@ -123,12 +122,12 @@ let definition ~path ~line ~col =
| None -> Protocol.null
| Some location -> location |> Protocol.stringifyLocation)

let typeDefinition ~path ~line ~col =
let typeDefinition ~path ~pos ~debug =
let maybeLocation =
match Cmt.fullFromPath ~path with
| None -> None
| Some full -> (
match References.getLocItem ~full ~line ~col with
match References.getLocItem ~full ~pos ~debug with
| None -> None
| Some locItem -> (
match References.typeDefinitionForLocItem ~full locItem with
Expand All @@ -143,12 +142,12 @@ let typeDefinition ~path ~line ~col =
| None -> Protocol.null
| Some location -> location |> Protocol.stringifyLocation)

let references ~path ~line ~col =
let references ~path ~pos ~debug =
let allLocs =
match Cmt.fullFromPath ~path with
| None -> []
| Some full -> (
match References.getLocItem ~full ~line ~col with
match References.getLocItem ~full ~pos ~debug with
| None -> []
| Some locItem ->
let allReferences = References.allReferencesForLocItem ~full locItem in
Expand All @@ -169,12 +168,12 @@ let references ~path ~line ~col =
(if allLocs = [] then Protocol.null
else "[\n" ^ (allLocs |> String.concat ",\n") ^ "\n]")

let rename ~path ~line ~col ~newName =
let rename ~path ~pos ~newName ~debug =
let result =
match Cmt.fullFromPath ~path with
| None -> Protocol.null
| Some full -> (
match References.getLocItem ~full ~line ~col with
match References.getLocItem ~full ~pos ~debug with
| None -> Protocol.null
| Some locItem ->
let allReferences = References.allReferencesForLocItem ~full locItem in
Expand Down Expand Up @@ -305,24 +304,24 @@ let test ~path =
print_endline
("Definition " ^ path ^ " " ^ string_of_int line ^ ":"
^ string_of_int col);
definition ~path ~line ~col
definition ~path ~pos:(line, col) ~debug:true
| "typ" ->
print_endline
("TypeDefinition " ^ path ^ " " ^ string_of_int line ^ ":"
^ string_of_int col);
typeDefinition ~path ~line ~col
typeDefinition ~path ~pos:(line, col) ~debug:true
| "hov" ->
print_endline
("Hover " ^ path ^ " " ^ string_of_int line ^ ":"
^ string_of_int col);
let currentFile = createCurrentFile () in
hover ~path ~line ~col ~currentFile ~debug:true;
hover ~path ~pos:(line, col) ~currentFile ~debug:true;
Sys.remove currentFile
| "ref" ->
print_endline
("References " ^ path ^ " " ^ string_of_int line ^ ":"
^ string_of_int col);
references ~path ~line ~col
references ~path ~pos:(line, col) ~debug:true
| "doc" ->
print_endline ("DocumentSymbol " ^ path);
DocumentSymbol.command ~path
Expand All @@ -333,7 +332,7 @@ let test ~path =
("Rename " ^ path ^ " " ^ string_of_int line ^ ":"
^ string_of_int col ^ " " ^ newName)
in
rename ~path ~line ~col ~newName
rename ~path ~pos:(line, col) ~newName ~debug:true
| "com" ->
print_endline
("Complete " ^ path ^ " " ^ string_of_int line ^ ":"
Expand Down Expand Up @@ -362,6 +361,7 @@ let test ~path =
^ string_of_int col);
let codeActions =
Xform.extractCodeActions ~path ~pos:(line, col) ~currentFile:path
~debug:true
in
codeActions
|> List.iter (fun {Protocol.title; edit = {documentChanges}} ->
Expand Down
83 changes: 54 additions & 29 deletions analysis/src/References.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
open SharedTypes

let debugReferences = ref true

let maybeLog m = if !debugReferences then Log.log ("[ref] " ^ m)

let checkPos (line, char)
Expand All @@ -16,43 +17,56 @@ let checkPos (line, char)
let locItemsForPos ~extra pos =
extra.locItems |> List.filter (fun {loc; locType = _} -> checkPos pos loc)

let lineColToCmtLoc ~line ~col = (line + 1, col)
let lineColToCmtLoc ~pos:(line, col) = (line + 1, col)

let getLocItem ~full ~line ~col =
let pos = lineColToCmtLoc ~line ~col in
let getLocItem ~full ~pos ~debug =
let log n msg = if debug then Printf.printf "getLocItem #%d: %s\n" n msg in
let pos = lineColToCmtLoc ~pos in
let locItems = locItemsForPos ~extra:full.extra pos in
if !Log.verbose then
print_endline
("locItems:\n "
^ (locItems |> List.map locItemToString |> String.concat "\n "));
let nameOf li =
match li.locType with Typed (n, _, _) -> n | _ -> "NotFound"
in
match locItems with
| _ :: _ :: _ :: ({locType = Typed ("makeProps", _, _)} as li) :: _
| li1 :: li2 :: li3 :: ({locType = Typed ("makeProps", _, _)} as li4) :: _
when full.file.uri |> Uri2.isInterface ->
(* heuristic for makeProps in interface files *)
Some li
log 1 "heuristic for makeProps in interface files";
if debug then
Printf.printf "n1:%s n2:%s n3:%s\n" (nameOf li1) (nameOf li2) (nameOf li3);
Some li4
| [
{locType = Typed ("fragment", _, _)};
{locType = Typed ("createElement", _, _)};
] ->
(* heuristic for </Comp> within a fragment *)
log 2 "heuristic for </Comp> within a fragment";
None
| [
{locType = Constant _};
({locType = Typed ("createDOMElementVariadic", _, _)} as li2);
] ->
(* heuristic for <div> *)
log 3 "heuristic for <div>";
Some li2
| {locType = Typed ("makeProps", _, _)}
:: ({locType = Typed ("make", _, _)} as li2) :: _ ->
(* heuristic for </Comp> within fragments: take make as makeProps does not work
the type is not greatl but jump to definition works *)
log 4
"heuristic for </Comp> within fragments: take make as makeProps does not \
work\n\
the type is not great but jump to definition works";
Some li2
| [
({locType = Typed (_, _, LocalReference _)} as li1);
({locType = Typed (_, _, _)} as li2);
]
when li1.loc = li2.loc ->
log 5
"heuristic for JSX and compiler combined:\n\
~x becomes Props#x\n\
heuristic for: [Props, x], give loc of `x`";
if debug then Printf.printf "n1:%s n2:%s\n" (nameOf li1) (nameOf li2);
Some li2
| [({locType = Typed (_, _, LocalReference _)} as li1); li3]
when li1.loc = li3.loc ->
(* JSX and compiler combined:
~x becomes Props#x
heuristic for: [Props, x], give loc of `x` *)
Some li3
| [
({locType = Typed (_, _, LocalReference _)} as li1);
({locType = Typed (_, _, GlobalReference ("Js_OO", ["unsafe_downgrade"], _))}
Expand All @@ -61,28 +75,39 @@ let getLocItem ~full ~line ~col =
]
(* For older compiler 9.0 or earlier *)
when li1.loc = li2.loc && li2.loc = li3.loc ->
(* JSX and compiler combined:
~x becomes Js_OO.unsafe_downgrade(Props)#x
heuristic for: [Props, unsafe_downgrade, x], give loc of `x` *)
(* Not currently testable on 9.1.4 *)
log 6
"heuristic for JSX and compiler combined:\n\
~x becomes Js_OO.unsafe_downgrade(Props)#x\n\
heuristic for: [Props, unsafe_downgrade, x], give loc of `x`";
Some li3
| [
{locType = Typed (_, _, LocalReference (_, Value))};
({locType = Typed (_, _, LocalReference (_, Value))} as li1);
({locType = Typed (_, _, Definition (_, Value))} as li2);
] ->
(* JSX on type-annotated labeled (~arg:t):
(~arg:t) becomes Props#arg
Props has the location range of arg:t
arg has the location range of arg
heuristic for: [Props, arg], give loc of `arg` *)
log 7
"heuristic for JSX on type-annotated labeled (~arg:t):\n\
(~arg:t) becomes Props#arg\n\
Props has the location range of arg:t\n\
arg has the location range of arg\n\
heuristic for: [Props, arg], give loc of `arg`";
if debug then Printf.printf "n1:%s n2:%s\n" (nameOf li1) (nameOf li2);
Some li2
| [li1; li2; li3] when li1.loc = li2.loc && li2.loc = li3.loc ->
(* JSX with at most one child
heuristic for: [makeProps, make, createElement], give the loc of `make` *)
(* Not currently testable on 9.1.4 *)
log 8
"heuristic for JSX with at most one child\n\
heuristic for: [makeProps, make, createElement], give the loc of `make` ";
Some li2
| [li1; li2; li3; li4]
when li1.loc = li2.loc && li2.loc = li3.loc && li3.loc = li4.loc ->
(* JSX variadic, e.g. <C> {x} {y} </C>
heuristic for: [makeProps , React.null, make, createElementVariadic], give the loc of `make` *)
log 9
"heuristic for JSX variadic, e.g. <C> {x} {y} </C>\n\
heuristic for: [React.null, makeProps, make, createElementVariadic], \
give the loc of `make`";
if debug then
Printf.printf "n1:%s n2:%s n3:%s n4:%s\n" (nameOf li1) (nameOf li2)
(nameOf li3) (nameOf li4);
Some li3
| {locType = Typed (_, {desc = Tconstr (path, _, _)}, _)} :: li :: _
when Utils.isUncurriedInternal path ->
Expand Down
10 changes: 4 additions & 6 deletions analysis/src/Xform.ml
Original file line number Diff line number Diff line change
Expand Up @@ -223,16 +223,14 @@ module AddTypeAnnotation = struct
in
{Ast_iterator.default_iterator with structure_item}

let xform ~path ~pos ~full ~structure ~codeActions =
let line, col = pos in

let xform ~path ~pos ~full ~structure ~codeActions ~debug =
let result = ref None in
let iterator = mkIterator ~pos ~result in
iterator.structure iterator structure;
match !result with
| None -> ()
| Some annotation -> (
match References.getLocItem ~full ~line ~col with
match References.getLocItem ~full ~pos ~debug with
| None -> ()
| Some locItem -> (
match locItem.locType with
Expand Down Expand Up @@ -297,14 +295,14 @@ let parse ~filename =
in
(structure, printExpr, printStructureItem)

let extractCodeActions ~path ~pos ~currentFile =
let extractCodeActions ~path ~pos ~currentFile ~debug =
match Cmt.fullFromPath ~path with
| Some full when Filename.check_suffix currentFile ".res" ->
let structure, printExpr, printStructureItem =
parse ~filename:currentFile
in
let codeActions = ref [] in
AddTypeAnnotation.xform ~path ~pos ~full ~structure ~codeActions;
AddTypeAnnotation.xform ~path ~pos ~full ~structure ~codeActions ~debug;
IfThenElse.xform ~pos ~codeActions ~printExpr ~path structure;
AddBracesToFn.xform ~pos ~codeActions ~path ~printStructureItem structure;
!codeActions
Expand Down
14 changes: 7 additions & 7 deletions analysis/tests/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading