@@ -970,30 +970,103 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
970970 with
971971 | Some (TypeExpr typ , env ) -> (
972972 match typ |> TypeUtils. extractRecordType ~env ~package with
973- | Some (env , fields , typDecl ) ->
973+ | Some (env , fields , typDecl , path ) ->
974974 Some
975975 ( env,
976976 fields,
977- typDecl.item.decl |> Shared. declToString typDecl.name.txt )
977+ typDecl.item.decl |> Shared. declToString typDecl.name.txt,
978+ Some path )
978979 | None -> None )
979980 | Some (ExtractedType typ , env ) -> (
980981 match typ with
981- | Trecord {fields} ->
982- Some (env, fields, typ |> TypeUtils. extractedTypeToString)
982+ | Trecord {fields; path } ->
983+ Some (env, fields, typ |> TypeUtils. extractedTypeToString, path )
983984 | _ -> None )
984985 | None -> None
985986 in
986987 match extracted with
987988 | None -> []
988- | Some (env , fields , recordAsString ) ->
989- fields
990- |> Utils. filterMap (fun field ->
991- if Utils. checkName field.fname.txt ~prefix: fieldName ~exact then
992- Some
993- (Completion. create field.fname.txt ~env
994- ?deprecated:field.deprecated ~docstring: field.docstring
995- ~kind: (Completion. Field (field, recordAsString)))
996- else None ))
989+ | Some (env , fields , recordAsString , path ) ->
990+ let pipeCompletionsForModule =
991+ match path with
992+ | Some path ->
993+ let completionPath =
994+ (* Remove the last part of the path since we're only after the parent module *)
995+ match
996+ path |> SharedTypes. pathIdentToString |> String. split_on_char '.'
997+ |> List. rev
998+ with
999+ | _ :: rest -> rest
1000+ | [] -> []
1001+ in
1002+ (* Most of this is copied from the pipe completion code. Should probably be unified. *)
1003+ let completions =
1004+ completionPath @ [fieldName]
1005+ |> getCompletionsForPath ~debug ~completion Context:Value
1006+ ~exact: false ~opens ~full ~pos ~env ~scope
1007+ in
1008+ let completionPathMinusOpens =
1009+ TypeUtils. removeOpensFromCompletionPath ~raw Opens ~package
1010+ completionPath
1011+ |> String. concat " ."
1012+ in
1013+ let completionName name =
1014+ if completionPathMinusOpens = " " then name
1015+ else completionPathMinusOpens ^ " ." ^ name
1016+ in
1017+ (* Find all functions in the module that takes type t *)
1018+ let rec fnTakesTypeT t =
1019+ match t.Types. desc with
1020+ | Tlink t1
1021+ | Tsubst t1
1022+ | Tpoly (t1, [] )
1023+ | Tconstr (Pident {name = "function$" } , [t1 ; _ ], _ ) ->
1024+ fnTakesTypeT t1
1025+ | Tarrow _ -> (
1026+ match
1027+ TypeUtils. extractFunctionType ~env ~package: full.package t
1028+ with
1029+ | ( (Nolabel , {desc = Tconstr (Path. Pident {name = " t" }, _, _)})
1030+ :: _,
1031+ _ ) ->
1032+ true
1033+ | _ -> false )
1034+ | _ -> false
1035+ in
1036+ completions
1037+ |> List. filter_map (fun (completion : Completion.t ) ->
1038+ match completion.kind with
1039+ | Value t when fnTakesTypeT t ->
1040+ let name = completionName completion.name in
1041+ let nameWithPipe = " ->" ^ name in
1042+ (* TODO: We need to add support for setting the text insertion location explicitly,
1043+ so we can account for the dot that triggered the completion, but that we want
1044+ removed when inserting the pipe. This means we also need to track the loc of
1045+ the dot + the identifier that we're filtering with (fieldName here).
1046+ That should be easy to do by extending CPField. *)
1047+ Some
1048+ {
1049+ completion with
1050+ name = nameWithPipe;
1051+ sortText =
1052+ Some
1053+ (name |> String. split_on_char '.' |> List. rev
1054+ |> List. hd);
1055+ insertText = Some nameWithPipe;
1056+ env;
1057+ }
1058+ | _ -> None )
1059+ | None -> []
1060+ in
1061+ pipeCompletionsForModule
1062+ @ (fields
1063+ |> Utils. filterMap (fun field ->
1064+ if Utils. checkName field.fname.txt ~prefix: fieldName ~exact then
1065+ Some
1066+ (Completion. create field.fname.txt ~env
1067+ ?deprecated:field.deprecated ~docstring: field.docstring
1068+ ~kind: (Completion. Field (field, recordAsString)))
1069+ else None )))
9971070 | CPObj (cp , label ) -> (
9981071 (* TODO: Also needs to support ExtractedType *)
9991072 if Debug. verbose () then print_endline " [ctx_path]--> CPObj" ;
@@ -1936,6 +2009,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
19362009 {
19372010 env;
19382011 definition = `NameOnly " jsxConfig" ;
2012+ path = None ;
19392013 fields =
19402014 [
19412015 mkField ~name: " version" ~primitive: " int" ;
@@ -1965,6 +2039,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
19652039 Trecord
19662040 {
19672041 env;
2042+ path = None ;
19682043 definition = `NameOnly " importAttributesConfig" ;
19692044 fields = [mkField ~name: " type_" ~primitive: " string" ];
19702045 }
@@ -1973,6 +2048,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
19732048 Trecord
19742049 {
19752050 env;
2051+ path = None ;
19762052 definition = `NameOnly " moduleConfig" ;
19772053 fields =
19782054 [
0 commit comments