Skip to content

Add completions for included modules #7509

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

Closed
wants to merge 2 commits into from
Closed
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
2 changes: 1 addition & 1 deletion analysis/src/Commands.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ let completion ~debug ~path ~pos ~currentFile =
Completions.getCompletions ~debug ~path ~pos ~currentFile ~forHover:false
with
| None -> []
| Some (completions, full, _) ->
| Some (completions, full, _, _) ->
completions
|> List.map (CompletionBackEnd.completionToItem ~full)
|> List.map Protocol.stringifyCompletionItem
Expand Down
80 changes: 48 additions & 32 deletions analysis/src/CompletionBackEnd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ let completionsGetCompletionType ~full completions =
| _ -> None

let rec completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos
completions =
~cursorPath completions =
let firstNonSyntheticCompletion =
List.find_opt (fun c -> not c.Completion.synthetic) completions
in
Expand All @@ -787,8 +787,9 @@ let rec completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos
| Some {Completion.kind = FollowContextPath (ctxPath, scope); env} ->
ctxPath
|> getCompletionsForContextPath ~debug ~full ~env ~exact:true ~opens
~rawOpens ~pos ~scope
~rawOpens ~pos ~scope ~cursorPath
|> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos
~cursorPath
| Some {Completion.kind = Type typ; env} -> (
match TypeUtils.extractTypeFromResolvedType typ ~env ~full with
| None -> None
Expand All @@ -798,7 +799,7 @@ let rec completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos
| _ -> None

and completionsGetTypeEnv2 ~debug (completions : Completion.t list) ~full ~opens
~rawOpens ~pos =
~rawOpens ~pos ~cursorPath =
let firstNonSyntheticCompletion =
List.find_opt (fun c -> not c.Completion.synthetic) completions
in
Expand All @@ -809,12 +810,12 @@ and completionsGetTypeEnv2 ~debug (completions : Completion.t list) ~full ~opens
| Some {Completion.kind = FollowContextPath (ctxPath, scope); env} ->
ctxPath
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
~exact:true ~scope ~cursorPath
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~cursorPath
| _ -> None

and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
~scope ?(mode = Regular) contextPath =
~scope ?(mode = Regular) ~cursorPath contextPath =
let envCompletionIsMadeFrom = env in
if debug then
Printf.printf "ContextPath %s\n"
Expand Down Expand Up @@ -847,7 +848,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
match
cp
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope
~exact:true ~scope ~cursorPath
|> completionsGetCompletionType ~full
with
| None -> []
Expand All @@ -869,7 +870,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
match
cp
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope
~exact:true ~scope ~cursorPath
|> completionsGetCompletionType ~full
with
| None -> []
Expand All @@ -884,7 +885,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
match
cp
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope
~exact:true ~scope ~cursorPath
|> completionsGetCompletionType ~full
with
| Some (Tpromise (env, typ), _env) ->
Expand Down Expand Up @@ -934,8 +935,9 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
match
cp
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope
~exact:true ~scope ~cursorPath
|> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos
~cursorPath
with
| Some ((TypeExpr typ | ExtractedType (Tfunction {typ})), env) -> (
let rec reconstructFunctionType args tRet =
Expand Down Expand Up @@ -985,11 +987,11 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
let completionsFromCtxPath =
cp
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope
~exact:true ~scope ~cursorPath
in
let mainTypeCompletionEnv =
completionsFromCtxPath
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~cursorPath
in
match mainTypeCompletionEnv with
| None ->
Expand Down Expand Up @@ -1021,7 +1023,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
let pipeCompletions =
cpAsPipeCompletion
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos
~env:envCompletionIsMadeFrom ~exact ~scope
~env:envCompletionIsMadeFrom ~exact ~scope ~cursorPath
|> List.filter_map (fun c ->
TypeUtils.transformCompletionToPipeCompletion ~synthetic:true
~env ?posOfDot c)
Expand All @@ -1033,8 +1035,8 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
match
cp
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
~exact:true ~scope ~cursorPath
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~cursorPath
with
| Some (typ, env) -> (
match typ |> TypeUtils.extractObjectType ~env ~package with
Expand All @@ -1052,8 +1054,8 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
match
cp
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope ~mode:Pipe
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
~exact:true ~scope ~mode:Pipe ~cursorPath
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~cursorPath
with
| None ->
if Debug.verbose () then
Expand Down Expand Up @@ -1180,8 +1182,17 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
|> TypeUtils.filterPipeableFunctions ~synthetic:true ~env ~full
~targetTypeId:mainTypeId
in
(* Add completions from current fully qualified path module *)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, I use the cursorPath collected via the frontend, to ask for DotPipeCompleteFromCurrentModule.Wall completions.

This is the only way I get the addPos and addPosFromVec2 completions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, of course, doesn't take into account functions defined after the cursor.
So that is not ideal.
It also proposes fully qualified function calls instead of having no path at all.

let currentFullyQualifiedPathModuleCompletions =
completionsForPipeFromCompletionPath ~envCompletionIsMadeFrom
~opens:[] ~pos ~scope ~debug ~prefix ~env ~rawOpens ~full cursorPath

|> TypeUtils.filterPipeableFunctions ~synthetic:true ~env ~full
~targetTypeId:mainTypeId
in
jsxCompletions @ pipeCompletions @ extraCompletions
@ currentModuleCompletions @ globallyConfiguredCompletions))
@ currentModuleCompletions @ globallyConfiguredCompletions
@ currentFullyQualifiedPathModuleCompletions))
| CTuple ctxPaths ->
if Debug.verbose () then print_endline "[ctx_path]--> CTuple";
(* Turn a list of context paths into a list of type expressions. *)
Expand All @@ -1190,7 +1201,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
|> List.map (fun contextPath ->
contextPath
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos
~env ~exact:true ~scope)
~env ~exact:true ~scope ~cursorPath)
|> List.filter_map (fun completionItems ->
match completionItems with
| {Completion.kind = Value typ} :: _ -> Some typ
Expand All @@ -1208,7 +1219,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
path
|> getCompletionsForPath ~debug ~completionContext:Value ~exact:true
~opens ~full ~pos ~env ~scope
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~cursorPath
in
let lowercaseComponent =
match pathToComponent with
Expand Down Expand Up @@ -1283,8 +1294,9 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
match
functionContextPath
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope
~exact:true ~scope ~cursorPath
|> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos
~cursorPath
with
| Some ((TypeExpr typ | ExtractedType (Tfunction {typ})), env) ->
if Debug.verbose () then print_endline "--> found function type";
Expand Down Expand Up @@ -1330,8 +1342,9 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
match
rootCtxPath
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope
~exact:true ~scope ~cursorPath
|> completionsGetCompletionType2 ~debug ~full ~opens ~rawOpens ~pos
~cursorPath
with
| Some (typ, env) -> (
match typ |> TypeUtils.resolveNestedPatternPath ~env ~full ~nested with
Expand Down Expand Up @@ -1846,7 +1859,8 @@ let rec completeTypedValue ?(typeArgContext : typeArgContext option) ~rawOpens

module StringSet = Set.Make (String)

let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover ~cursorPath
completable =
if debug then
Printf.printf "Completable: %s\n" (Completable.toString completable);
let package = full.package in
Expand All @@ -1857,14 +1871,14 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
path
|> getCompletionsForPath ~debug ~completionContext:Value ~exact:true ~opens
~full ~pos ~env ~scope
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~cursorPath
in
match completable with
| Cnone -> []
| Cpath contextPath ->
contextPath
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:forHover ~scope
~exact:forHover ~scope ~cursorPath
| Cjsx ([id], prefix, identsSeen) when String.uncapitalize_ascii id = id -> (
(* Lowercase JSX tag means builtin *)
let mkLabel (name, typString) =
Expand Down Expand Up @@ -2115,8 +2129,8 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
match
cp
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
~exact:true ~scope ~cursorPath
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~cursorPath
with
| Some (typ, _env) ->
if debug then
Expand Down Expand Up @@ -2144,15 +2158,17 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
let fallbackOrEmpty ?items () =
match (fallback, items) with
| Some fallback, (None | Some []) ->
fallback |> processCompletable ~debug ~full ~scope ~env ~pos ~forHover
fallback
|> processCompletable ~debug ~full ~scope ~env ~pos ~forHover
~cursorPath
| _, Some items -> items
| None, None -> []
in
match
contextPath
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos
~exact:true ~scope ~cursorPath
|> completionsGetTypeEnv2 ~debug ~full ~opens ~rawOpens ~pos ~cursorPath
with
| Some (typ, env) -> (
match
Expand Down Expand Up @@ -2200,7 +2216,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
match
contextPath
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:true ~scope
~exact:true ~scope ~cursorPath
|> completionsGetCompletionType ~full
with
| None ->
Expand Down Expand Up @@ -2301,7 +2317,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
let completionsForContextPath =
contextPath
|> getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env
~exact:forHover ~scope
~exact:forHover ~scope ~cursorPath
in
completionsForContextPath
|> List.map (fun (c : Completion.t) ->
Expand Down
9 changes: 7 additions & 2 deletions analysis/src/CompletionFrontEnd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ let completePipeChain ~(inJsxContext : bool) (exp : Parsetree.expression) =

let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
?findThisExprLoc text =
let cursorPath = Stack.create () in
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to keep track of which nested modules we have visited so far.
So, I can construct the current path of the cursor.

let offsetNoWhite = Utils.skipWhite text (offset - 1) in
let posNoWhite =
let line, col = posCursor in
Expand Down Expand Up @@ -737,8 +738,10 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
if recFlag = Nonrecursive then decls |> List.iter scopeTypeDeclaration;
processed := true
| Pstr_module mb ->
if Loc.hasPos mb.pmb_loc ~pos:posCursor then Stack.push mb.pmb_name.txt cursorPath;
iterator.module_binding iterator mb;
scopeModuleBinding mb;
(* if Loc.hasPos mb.pmb_loc ~pos:posCursor then Stack.pop cursorPath |> ignore; *)
processed := true
| Pstr_recmodule mbs ->
mbs |> List.iter scopeModuleBinding;
Expand Down Expand Up @@ -1737,7 +1740,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
(Cpath
(CPId {loc = Location.none; path = [""]; completionContext = Value})));
if !found = false then if debug then Printf.printf "XXX Not found!\n";
!result)
let cursorPath = Stack.to_seq cursorPath |> List.of_seq |> List.rev in
!result |> Option.map (fun (c, s) -> (c, s, cursorPath)))
else if Filename.check_suffix path ".resi" then (
let parser = Res_driver.parsing_engine.parse_interface ~for_printer:false in
let {Res_driver.parsetree = signature} = parser ~filename:currentFile in
Expand All @@ -1748,7 +1752,8 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
(Cpath
(CPId {loc = Location.none; path = [""]; completionContext = Type})));
if !found = false then if debug then Printf.printf "XXX Not found!\n";
!result)
let cursorPath = Stack.to_seq cursorPath |> List.of_seq |> List.rev in
!result |> Option.map (fun (c, s) -> (c, s, cursorPath)))
else None

let completionWithParser ~debug ~path ~posCursor ~currentFile ~text =
Expand Down
7 changes: 4 additions & 3 deletions analysis/src/Completions.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ let getCompletions ~debug ~path ~pos ~currentFile ~forHover =
~currentFile ~text
with
| None -> None
| Some (completable, scope) -> (
| Some (completable, scope, cursorPath) -> (
(* Only perform expensive ast operations if there are completables *)
match Cmt.loadFullCmtFromPath ~path with
| None -> None
| Some full ->
let env = SharedTypes.QueryEnv.fromFile full.file in
let cursorPath = full.file.moduleName :: cursorPath in
let completables =
completable
|> CompletionBackEnd.processCompletable ~debug ~full ~pos ~scope ~env
~forHover
~forHover ~cursorPath
in
Some (completables, full, scope)))
Some (completables, full, scope, cursorPath)))
6 changes: 3 additions & 3 deletions analysis/src/Hover.ml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ let getHoverViaCompletions ~debug ~path ~pos ~currentFile ~forHover
~supportsMarkdownLinks =
match Completions.getCompletions ~debug ~path ~pos ~currentFile ~forHover with
| None -> None
| Some (completions, ({file; package} as full), scope) -> (
| Some (completions, ({file; package} as full), scope, cursorPath) -> (
let rawOpens = Scope.getRawOpens scope in
match completions with
| {kind = Label typString; docstring} :: _ ->
Expand All @@ -166,7 +166,7 @@ let getHoverViaCompletions ~debug ~path ~pos ~currentFile ~forHover
let opens = CompletionBackEnd.getOpens ~debug ~rawOpens ~package ~env in
match
CompletionBackEnd.completionsGetTypeEnv2 ~debug ~full ~rawOpens ~opens
~pos completions
~pos completions ~cursorPath
with
| Some (typ, _env) ->
let typeString =
Expand All @@ -179,7 +179,7 @@ let getHoverViaCompletions ~debug ~path ~pos ~currentFile ~forHover
let opens = CompletionBackEnd.getOpens ~debug ~rawOpens ~package ~env in
match
CompletionBackEnd.completionsGetTypeEnv2 ~debug ~full ~rawOpens ~opens
~pos completions
~pos completions ~cursorPath
with
| Some (typ, _env) ->
let typeString =
Expand Down
4 changes: 2 additions & 2 deletions analysis/src/SignatureHelp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ let findFunctionType ~currentFile ~debug ~path ~pos =
~currentFile ~text
with
| None -> None
| Some (completable, scope) ->
| Some (completable, scope, cursorPath) ->
Some
( completable
|> CompletionBackEnd.processCompletable ~debug ~full ~pos ~scope
~env ~forHover:true,
~env ~forHover:true ~cursorPath,
env,
package,
file ))
Expand Down
6 changes: 3 additions & 3 deletions analysis/src/Xform.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ let extractTypeFromExpr expr ~debug ~path ~currentFile ~full ~pos =
|> CompletionFrontEnd.findTypeOfExpressionAtLoc ~debug ~path ~currentFile
~posCursor:(Pos.ofLexing expr.Parsetree.pexp_loc.loc_start)
with
| Some (completable, scope) -> (
| Some (completable, scope, cursorPath) -> (
let env = SharedTypes.QueryEnv.fromFile full.SharedTypes.file in
let completions =
completable
|> CompletionBackEnd.processCompletable ~debug ~full ~pos ~scope ~env
~forHover:true
~forHover:true ~cursorPath
in
let rawOpens = Scope.getRawOpens scope in
match completions with
Expand All @@ -23,7 +23,7 @@ let extractTypeFromExpr expr ~debug ~path ~currentFile ~full ~pos =
in
match
CompletionBackEnd.completionsGetCompletionType2 ~debug ~full ~rawOpens
~opens ~pos completions
~opens ~pos completions ~cursorPath
with
| Some (typ, _env) ->
let extractedType =
Expand Down
Loading
Loading