@@ -514,7 +514,7 @@ let getComplementaryCompletionsForTypedValue ~opens ~allFiles ~scope ~env prefix
514
514
in
515
515
localCompletionsWithOpens @ fileModules
516
516
517
- let getCompletionsForPath ~debug ~package ~ opens ~full ~pos ~exact ~scope
517
+ let getCompletionsForPath ~debug ~opens ~full ~pos ~exact ~scope
518
518
~completionContext ~env path =
519
519
if debug then Printf. printf " Path %s\n " (path |> String. concat " ." );
520
520
let allFiles = allFilesInPackage full.package in
@@ -541,7 +541,9 @@ let getCompletionsForPath ~debug ~package ~opens ~full ~pos ~exact ~scope
541
541
localCompletionsWithOpens @ fileModules
542
542
| moduleName :: path -> (
543
543
Log. log (" Path " ^ pathToString path);
544
- match getEnvWithOpens ~scope ~env ~package ~opens ~module Name path with
544
+ match
545
+ getEnvWithOpens ~scope ~env ~package: full.package ~opens ~module Name path
546
+ with
545
547
| Some (env , prefix ) ->
546
548
Log. log " Got the env" ;
547
549
let namesUsed = Hashtbl. create 10 in
@@ -552,8 +554,8 @@ let rec digToRecordFieldsForCompletion ~debug ~package ~opens ~full ~pos ~env
552
554
~scope path =
553
555
match
554
556
path
555
- |> getCompletionsForPath ~debug ~completion Context:Type ~exact: true ~package
556
- ~opens ~ full ~pos ~env ~scope
557
+ |> getCompletionsForPath ~debug ~completion Context:Type ~exact: true ~opens
558
+ ~full ~pos ~env ~scope
557
559
with
558
560
| {kind = Type {kind = Abstract (Some (p , _ ))} } :: _ ->
559
561
(* This case happens when what we're looking for is a type alias.
@@ -769,8 +771,8 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
769
771
| _ -> [] )
770
772
| CPId (path , completionContext ) ->
771
773
path
772
- |> getCompletionsForPath ~debug ~package ~ opens ~full ~pos ~exact
773
- ~completion Context ~ env ~scope
774
+ |> getCompletionsForPath ~debug ~opens ~full ~pos ~exact ~completion Context
775
+ ~env ~scope
774
776
| CPApply (cp , labels ) -> (
775
777
match
776
778
cp
@@ -815,7 +817,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
815
817
| CPField (CPId (path , Module), fieldName ) ->
816
818
(* M.field *)
817
819
path @ [fieldName]
818
- |> getCompletionsForPath ~debug ~package ~ opens ~full ~pos ~exact
820
+ |> getCompletionsForPath ~debug ~opens ~full ~pos ~exact
819
821
~completion Context:Field ~env ~scope
820
822
| CPField (cp , fieldName ) -> (
821
823
let completionsForCtxPath =
@@ -933,52 +935,18 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
933
935
| Tconstr (path, _typeArgs, _)
934
936
| Tlink {desc = Tconstr (path, _typeArgs, _)}
935
937
| Tsubst {desc = Tconstr (path, _typeArgs, _)}
936
- | Tpoly ({desc = Tconstr (path , _typeArgs , _ )} , [] ) -> (
938
+ | Tpoly ({desc = Tconstr (path , _typeArgs , _ )} , [] ) ->
937
939
if debug then Printf. printf " CPPipe type path:%s\n " (Path. name path);
938
- match Utils. expandPath path with
939
- | _ :: pathRev ->
940
- (* type path is relative to the completion environment
941
- express it from the root of the file *)
942
- let found, pathFromEnv =
943
- QueryEnv. pathFromEnv envFromCompletionItem (List. rev pathRev)
944
- in
945
- if debug then
946
- Printf. printf " CPPipe pathFromEnv:%s found:%b\n "
947
- (pathFromEnv |> String. concat " ." )
948
- found;
949
- if pathFromEnv = [] then None
950
- else if
951
- env.file.moduleName <> envFromCompletionItem.file.moduleName
952
- && found
953
- (* If the module names are different, then one needs to qualify the path.
954
- But only if the path belongs to the env from completion *)
955
- then Some (envFromCompletionItem.file.moduleName :: pathFromEnv)
956
- else Some pathFromEnv
957
- | _ -> None )
940
+ TypeUtils. getPathRelativeToEnv ~debug ~env
941
+ ~env FromItem:envFromCompletionItem (Utils. expandPath path)
958
942
| _ -> None )
959
943
in
960
944
match completionPath with
961
945
| Some completionPath -> (
962
- let rec removeRawOpen rawOpen modulePath =
963
- match (rawOpen, modulePath) with
964
- | [_], _ -> Some modulePath
965
- | s :: inner , first :: restPath when s = first ->
966
- removeRawOpen inner restPath
967
- | _ -> None
968
- in
969
- let rec removeRawOpens rawOpens modulePath =
970
- match rawOpens with
971
- | rawOpen :: restOpens -> (
972
- let newModulePath = removeRawOpens restOpens modulePath in
973
- match removeRawOpen rawOpen newModulePath with
974
- | None -> newModulePath
975
- | Some mp -> mp)
976
- | [] -> modulePath
977
- in
978
946
let completionPathMinusOpens =
979
- completionPath |> Utils. flattenAnyNamespaceInPath
980
- |> removeRawOpens package.opens
981
- |> removeRawOpens rawOpens |> String. concat " ."
947
+ TypeUtils. removeOpensFromCompletionPath ~raw Opens ~package
948
+ completionPath
949
+ |> String. concat " ."
982
950
in
983
951
let completionName name =
984
952
if completionPathMinusOpens = " " then name
@@ -987,7 +955,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
987
955
let completions =
988
956
completionPath @ [funNamePrefix]
989
957
|> getCompletionsForPath ~debug ~completion Context:Value ~exact: false
990
- ~package ~ opens ~full ~pos ~env ~scope
958
+ ~opens ~full ~pos ~env ~scope
991
959
in
992
960
let completions =
993
961
completions
@@ -1051,7 +1019,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
1051
1019
let findTypeOfValue path =
1052
1020
path
1053
1021
|> getCompletionsForPath ~debug ~completion Context:Value ~exact: true
1054
- ~package ~ opens ~full ~pos ~env ~scope
1022
+ ~opens ~full ~pos ~env ~scope
1055
1023
|> completionsGetTypeEnv2 ~debug ~full ~opens ~raw Opens ~pos
1056
1024
in
1057
1025
let lowercaseComponent =
@@ -1061,16 +1029,25 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
1061
1029
in
1062
1030
let targetLabel =
1063
1031
if lowercaseComponent then
1064
- match
1065
- [" ReactDOM" ; " domProps" ]
1066
- |> digToRecordFieldsForCompletion ~debug ~package ~opens ~full ~pos
1067
- ~env ~scope
1068
- with
1069
- | None -> None
1070
- | Some fields -> (
1071
- match fields |> List. find_opt (fun f -> f.fname.txt = propName) with
1072
- | None -> None
1073
- | Some f -> Some (f.fname.txt, f.typ, env))
1032
+ let rec digToTypeForCompletion path =
1033
+ match
1034
+ path
1035
+ |> getCompletionsForPath ~debug ~completion Context:Type ~exact: true
1036
+ ~opens ~full ~pos ~env ~scope
1037
+ with
1038
+ | {kind = Type {kind = Abstract (Some (p , _ ))} } :: _ ->
1039
+ (* This case happens when what we're looking for is a type alias.
1040
+ This is the case in newer rescript-react versions where
1041
+ ReactDOM.domProps is an alias for JsxEvent.t. *)
1042
+ let pathRev = p |> Utils. expandPath in
1043
+ pathRev |> List. rev |> digToTypeForCompletion
1044
+ | {kind = Type {kind = Record fields } } :: _ -> (
1045
+ match fields |> List. find_opt (fun f -> f.fname.txt = propName) with
1046
+ | None -> None
1047
+ | Some f -> Some (f.fname.txt, f.typ, env))
1048
+ | _ -> None
1049
+ in
1050
+ [" ReactDOM" ; " domProps" ] |> digToTypeForCompletion
1074
1051
else
1075
1052
CompletionJsx. getJsxLabels ~component Path:pathToComponent
1076
1053
~find TypeOfValue ~package
@@ -1202,14 +1179,67 @@ let printConstructorArgs argsLen ~asSnippet =
1202
1179
1203
1180
type completionMode = Pattern of Completable .patternMode | Expression
1204
1181
1205
- let rec completeTypedValue ~full ~prefix ~completionContext ~mode
1182
+ let rec completeTypedValue ~rawOpens ~ full ~prefix ~completionContext ~mode
1206
1183
(t : SharedTypes.completionType ) =
1207
1184
let emptyCase num =
1208
1185
match mode with
1209
1186
| Expression -> " $" ^ string_of_int (num - 1 )
1210
1187
| Pattern _ -> " ${" ^ string_of_int num ^ " :_}"
1211
1188
in
1212
1189
match t with
1190
+ | TtypeT {env; path} ->
1191
+ (* Find all functions in the module that returns type t *)
1192
+ let rec fnReturnsTypeT t =
1193
+ match t.Types. desc with
1194
+ | Tlink t1
1195
+ | Tsubst t1
1196
+ | Tpoly (t1, [] )
1197
+ | Tconstr (Pident {name = "function$" } , [t1 ; _ ], _ ) ->
1198
+ fnReturnsTypeT t1
1199
+ | Tarrow _ -> (
1200
+ match TypeUtils. extractFunctionType ~env ~package: full.package t with
1201
+ | ( (Nolabel , {desc = Tconstr (Path. Pident {name = " t" }, _, _)}) :: _,
1202
+ {desc = Tconstr (Path. Pident {name = " t" }, _, _)} ) ->
1203
+ (* Filter out functions that take type t first. These are often
1204
+ @send style functions that we don't want to have here because
1205
+ they usually aren't meant to create a type t from scratch. *)
1206
+ false
1207
+ | _args , {desc = Tconstr (Path. Pident {name = "t" } , _ , _ )} -> true
1208
+ | _ -> false )
1209
+ | _ -> false
1210
+ in
1211
+ let functionsReturningTypeT =
1212
+ Hashtbl. create (Hashtbl. length env.exported.values_)
1213
+ in
1214
+ env.exported.values_
1215
+ |> Hashtbl. iter (fun name stamp ->
1216
+ match Stamps. findValue env.file.stamps stamp with
1217
+ | None -> ()
1218
+ | Some {item} -> (
1219
+ if fnReturnsTypeT item then
1220
+ let fnNname =
1221
+ TypeUtils. getPathRelativeToEnv ~debug: false
1222
+ ~env: (QueryEnv. fromFile full.file)
1223
+ ~env FromItem:env (Utils. expandPath path)
1224
+ in
1225
+
1226
+ match fnNname with
1227
+ | None -> ()
1228
+ | Some base ->
1229
+ let base =
1230
+ TypeUtils. removeOpensFromCompletionPath ~raw Opens
1231
+ ~package: full.package base
1232
+ in
1233
+ Hashtbl. add functionsReturningTypeT
1234
+ ((base |> String. concat " ." ) ^ " ." ^ name)
1235
+ item));
1236
+ Hashtbl. fold
1237
+ (fun fnName typeExpr all ->
1238
+ Completion. createWithSnippet
1239
+ ~name: (Printf. sprintf " %s()" fnName)
1240
+ ~insert Text:(fnName ^ " ($0)" ) ~kind: (Value typeExpr) ~env ()
1241
+ :: all)
1242
+ functionsReturningTypeT []
1213
1243
| Tbool env ->
1214
1244
[
1215
1245
Completion. create " true" ~kind: (Label " bool" ) ~env ;
@@ -1268,7 +1298,7 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode
1268
1298
| None -> []
1269
1299
| Some innerType ->
1270
1300
innerType
1271
- |> completeTypedValue ~full ~prefix ~completion Context ~mode
1301
+ |> completeTypedValue ~raw Opens ~ full ~prefix ~completion Context ~mode
1272
1302
|> List. map (fun (c : Completion.t ) ->
1273
1303
{
1274
1304
c with
@@ -1314,7 +1344,7 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode
1314
1344
| None -> []
1315
1345
| Some innerType ->
1316
1346
innerType
1317
- |> completeTypedValue ~full ~prefix ~completion Context ~mode
1347
+ |> completeTypedValue ~raw Opens ~ full ~prefix ~completion Context ~mode
1318
1348
|> List. map (fun (c : Completion.t ) ->
1319
1349
{
1320
1350
c with
@@ -1331,7 +1361,7 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode
1331
1361
| None -> []
1332
1362
| Some innerType ->
1333
1363
innerType
1334
- |> completeTypedValue ~full ~prefix ~completion Context ~mode
1364
+ |> completeTypedValue ~raw Opens ~ full ~prefix ~completion Context ~mode
1335
1365
|> List. map (fun (c : Completion.t ) ->
1336
1366
{
1337
1367
c with
@@ -1549,8 +1579,8 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
1549
1579
let allFiles = allFilesInPackage package in
1550
1580
let findTypeOfValue path =
1551
1581
path
1552
- |> getCompletionsForPath ~debug ~completion Context:Value ~exact: true
1553
- ~package ~opens ~ full ~pos ~env ~scope
1582
+ |> getCompletionsForPath ~debug ~completion Context:Value ~exact: true ~opens
1583
+ ~full ~pos ~env ~scope
1554
1584
|> completionsGetTypeEnv2 ~debug ~full ~opens ~raw Opens ~pos
1555
1585
in
1556
1586
match completable with
@@ -1781,8 +1811,8 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
1781
1811
| Some (typ , _env , completionContext ) ->
1782
1812
let items =
1783
1813
typ
1784
- |> completeTypedValue ~mode: (Pattern patternMode) ~full ~prefix
1785
- ~completion Context
1814
+ |> completeTypedValue ~raw Opens ~ mode: (Pattern patternMode) ~full
1815
+ ~prefix ~ completion Context
1786
1816
in
1787
1817
fallbackOrEmpty ~items () )
1788
1818
| None -> fallbackOrEmpty () )
@@ -1819,7 +1849,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
1819
1849
in
1820
1850
let items =
1821
1851
typ
1822
- |> completeTypedValue ~mode: Expression ~full ~prefix
1852
+ |> completeTypedValue ~raw Opens ~ mode:Expression ~full ~prefix
1823
1853
~completion Context
1824
1854
|> List. map (fun (c : Completion.t ) ->
1825
1855
if wrapInsertTextInBraces then
0 commit comments