@@ -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,13 +541,33 @@ 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
548
550
findAllCompletions ~env ~prefix ~exact ~names Used ~completion Context
549
551
| None -> [] )
550
552
553
+ let rec digToRecordFieldsForCompletion ~debug ~package ~opens ~full ~pos ~env
554
+ ~scope path =
555
+ match
556
+ path
557
+ |> getCompletionsForPath ~debug ~completion Context:Type ~exact: true ~opens
558
+ ~full ~pos ~env ~scope
559
+ with
560
+ | {kind = Type {kind = Abstract (Some (p , _ ))} } :: _ ->
561
+ (* This case happens when what we're looking for is a type alias.
562
+ This is the case in newer rescript-react versions where
563
+ ReactDOM.domProps is an alias for JsxEvent.t. *)
564
+ let pathRev = p |> Utils. expandPath in
565
+ pathRev |> List. rev
566
+ |> digToRecordFieldsForCompletion ~debug ~package ~opens ~full ~pos ~env
567
+ ~scope
568
+ | {kind = Type {kind = Record fields } } :: _ -> Some fields
569
+ | _ -> None
570
+
551
571
let mkItem ~name ~kind ~detail ~deprecated ~docstring =
552
572
let docContent =
553
573
(match deprecated with
@@ -571,7 +591,7 @@ let mkItem ~name ~kind ~detail ~deprecated ~docstring =
571
591
detail;
572
592
documentation =
573
593
(if docContent = " " then None
574
- else Some {kind = " markdown" ; value = docContent});
594
+ else Some {kind = " markdown" ; value = docContent});
575
595
sortText = None ;
576
596
insertText = None ;
577
597
insertTextFormat = None ;
@@ -751,8 +771,8 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
751
771
| _ -> [] )
752
772
| CPId (path , completionContext ) ->
753
773
path
754
- |> getCompletionsForPath ~debug ~package ~ opens ~full ~pos ~exact
755
- ~completion Context ~ env ~scope
774
+ |> getCompletionsForPath ~debug ~opens ~full ~pos ~exact ~completion Context
775
+ ~env ~scope
756
776
| CPApply (cp , labels ) -> (
757
777
match
758
778
cp
@@ -797,7 +817,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
797
817
| CPField (CPId (path , Module), fieldName ) ->
798
818
(* M.field *)
799
819
path @ [fieldName]
800
- |> getCompletionsForPath ~debug ~package ~ opens ~full ~pos ~exact
820
+ |> getCompletionsForPath ~debug ~opens ~full ~pos ~exact
801
821
~completion Context:Field ~env ~scope
802
822
| CPField (cp , fieldName ) -> (
803
823
let completionsForCtxPath =
@@ -915,52 +935,18 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
915
935
| Tconstr (path, _typeArgs, _)
916
936
| Tlink {desc = Tconstr (path, _typeArgs, _)}
917
937
| Tsubst {desc = Tconstr (path, _typeArgs, _)}
918
- | Tpoly ({desc = Tconstr (path , _typeArgs , _ )} , [] ) -> (
938
+ | Tpoly ({desc = Tconstr (path , _typeArgs , _ )} , [] ) ->
919
939
if debug then Printf. printf " CPPipe type path:%s\n " (Path. name path);
920
- match Utils. expandPath path with
921
- | _ :: pathRev ->
922
- (* type path is relative to the completion environment
923
- express it from the root of the file *)
924
- let found, pathFromEnv =
925
- QueryEnv. pathFromEnv envFromCompletionItem (List. rev pathRev)
926
- in
927
- if debug then
928
- Printf. printf " CPPipe pathFromEnv:%s found:%b\n "
929
- (pathFromEnv |> String. concat " ." )
930
- found;
931
- if pathFromEnv = [] then None
932
- else if
933
- env.file.moduleName <> envFromCompletionItem.file.moduleName
934
- && found
935
- (* If the module names are different, then one needs to qualify the path.
936
- But only if the path belongs to the env from completion *)
937
- then Some (envFromCompletionItem.file.moduleName :: pathFromEnv)
938
- else Some pathFromEnv
939
- | _ -> None )
940
+ TypeUtils. getPathRelativeToEnv ~debug ~env
941
+ ~env FromItem:envFromCompletionItem (Utils. expandPath path)
940
942
| _ -> None )
941
943
in
942
944
match completionPath with
943
945
| Some completionPath -> (
944
- let rec removeRawOpen rawOpen modulePath =
945
- match (rawOpen, modulePath) with
946
- | [_], _ -> Some modulePath
947
- | s :: inner , first :: restPath when s = first ->
948
- removeRawOpen inner restPath
949
- | _ -> None
950
- in
951
- let rec removeRawOpens rawOpens modulePath =
952
- match rawOpens with
953
- | rawOpen :: restOpens -> (
954
- let newModulePath = removeRawOpens restOpens modulePath in
955
- match removeRawOpen rawOpen newModulePath with
956
- | None -> newModulePath
957
- | Some mp -> mp)
958
- | [] -> modulePath
959
- in
960
946
let completionPathMinusOpens =
961
- completionPath |> Utils. flattenAnyNamespaceInPath
962
- |> removeRawOpens package.opens
963
- |> removeRawOpens rawOpens |> String. concat " ."
947
+ TypeUtils. removeOpensFromCompletionPath ~raw Opens ~package
948
+ completionPath
949
+ |> String. concat " ."
964
950
in
965
951
let completionName name =
966
952
if completionPathMinusOpens = " " then name
@@ -969,7 +955,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
969
955
let completions =
970
956
completionPath @ [funNamePrefix]
971
957
|> getCompletionsForPath ~debug ~completion Context:Value ~exact: false
972
- ~package ~ opens ~full ~pos ~env ~scope
958
+ ~opens ~full ~pos ~env ~scope
973
959
in
974
960
let completions =
975
961
completions
@@ -1033,7 +1019,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
1033
1019
let findTypeOfValue path =
1034
1020
path
1035
1021
|> getCompletionsForPath ~debug ~completion Context:Value ~exact: true
1036
- ~package ~ opens ~full ~pos ~env ~scope
1022
+ ~opens ~full ~pos ~env ~scope
1037
1023
|> completionsGetTypeEnv2 ~debug ~full ~opens ~raw Opens ~pos
1038
1024
in
1039
1025
let lowercaseComponent =
@@ -1047,7 +1033,7 @@ and getCompletionsForContextPath ~debug ~full ~opens ~rawOpens ~pos ~env ~exact
1047
1033
match
1048
1034
path
1049
1035
|> getCompletionsForPath ~debug ~completion Context:Type ~exact: true
1050
- ~package ~ opens ~full ~pos ~env ~scope
1036
+ ~opens ~full ~pos ~env ~scope
1051
1037
with
1052
1038
| {kind = Type {kind = Abstract (Some (p , _ ))} } :: _ ->
1053
1039
(* This case happens when what we're looking for is a type alias.
@@ -1193,9 +1179,62 @@ let printConstructorArgs argsLen ~asSnippet =
1193
1179
1194
1180
type completionMode = Pattern of Completable .patternMode | Expression
1195
1181
1196
- let rec completeTypedValue ~full ~prefix ~completionContext ~mode
1182
+ let rec completeTypedValue ~rawOpens ~ full ~prefix ~completionContext ~mode
1197
1183
(t : SharedTypes.completionType ) =
1198
1184
match t with
1185
+ | TtypeT {env; path} ->
1186
+ (* Find all functions in the module that returns type t *)
1187
+ let rec fnReturnsTypeT t =
1188
+ match t.Types. desc with
1189
+ | Tlink t1
1190
+ | Tsubst t1
1191
+ | Tpoly (t1, [] )
1192
+ | Tconstr (Pident {name = "function$" } , [t1 ; _ ], _ ) ->
1193
+ fnReturnsTypeT t1
1194
+ | Tarrow _ -> (
1195
+ match TypeUtils. extractFunctionType ~env ~package: full.package t with
1196
+ | ( (Nolabel , {desc = Tconstr (Path. Pident {name = " t" }, _, _)}) :: _,
1197
+ {desc = Tconstr (Path. Pident {name = " t" }, _, _)} ) ->
1198
+ (* Filter out functions that take type t first. These are often
1199
+ @send style functions that we don't want to have here because
1200
+ they usually aren't meant to create a type t from scratch. *)
1201
+ false
1202
+ | _args , {desc = Tconstr (Path. Pident {name = "t" } , _ , _ )} -> true
1203
+ | _ -> false )
1204
+ | _ -> false
1205
+ in
1206
+ let functionsReturningTypeT =
1207
+ Hashtbl. create (Hashtbl. length env.exported.values_)
1208
+ in
1209
+ env.exported.values_
1210
+ |> Hashtbl. iter (fun name stamp ->
1211
+ match Stamps. findValue env.file.stamps stamp with
1212
+ | None -> ()
1213
+ | Some {item} -> (
1214
+ if fnReturnsTypeT item then
1215
+ let fnNname =
1216
+ TypeUtils. getPathRelativeToEnv ~debug: false
1217
+ ~env: (QueryEnv. fromFile full.file)
1218
+ ~env FromItem:env (Utils. expandPath path)
1219
+ in
1220
+
1221
+ match fnNname with
1222
+ | None -> ()
1223
+ | Some base ->
1224
+ let base =
1225
+ TypeUtils. removeOpensFromCompletionPath ~raw Opens
1226
+ ~package: full.package base
1227
+ in
1228
+ Hashtbl. add functionsReturningTypeT
1229
+ ((base |> String. concat " ." ) ^ " ." ^ name)
1230
+ item));
1231
+ Hashtbl. fold
1232
+ (fun fnName typeExpr all ->
1233
+ Completion. createWithSnippet
1234
+ ~name: (Printf. sprintf " %s()" fnName)
1235
+ ~insert Text:(fnName ^ " ($0)" ) ~kind: (Value typeExpr) ~env ()
1236
+ :: all)
1237
+ functionsReturningTypeT []
1199
1238
| Tbool env ->
1200
1239
[
1201
1240
Completion. create " true" ~kind: (Label " bool" ) ~env ;
@@ -1254,7 +1293,7 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode
1254
1293
| None -> []
1255
1294
| Some innerType ->
1256
1295
innerType
1257
- |> completeTypedValue ~full ~prefix ~completion Context ~mode
1296
+ |> completeTypedValue ~raw Opens ~ full ~prefix ~completion Context ~mode
1258
1297
|> List. map (fun (c : Completion.t ) ->
1259
1298
{
1260
1299
c with
@@ -1298,7 +1337,7 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode
1298
1337
| None -> []
1299
1338
| Some innerType ->
1300
1339
innerType
1301
- |> completeTypedValue ~full ~prefix ~completion Context ~mode
1340
+ |> completeTypedValue ~raw Opens ~ full ~prefix ~completion Context ~mode
1302
1341
|> List. map (fun (c : Completion.t ) ->
1303
1342
{
1304
1343
c with
@@ -1315,7 +1354,7 @@ let rec completeTypedValue ~full ~prefix ~completionContext ~mode
1315
1354
| None -> []
1316
1355
| Some innerType ->
1317
1356
innerType
1318
- |> completeTypedValue ~full ~prefix ~completion Context ~mode
1357
+ |> completeTypedValue ~raw Opens ~ full ~prefix ~completion Context ~mode
1319
1358
|> List. map (fun (c : Completion.t ) ->
1320
1359
{
1321
1360
c with
@@ -1531,8 +1570,8 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
1531
1570
let allFiles = allFilesInPackage package in
1532
1571
let findTypeOfValue path =
1533
1572
path
1534
- |> getCompletionsForPath ~debug ~completion Context:Value ~exact: true
1535
- ~package ~opens ~ full ~pos ~env ~scope
1573
+ |> getCompletionsForPath ~debug ~completion Context:Value ~exact: true ~opens
1574
+ ~full ~pos ~env ~scope
1536
1575
|> completionsGetTypeEnv2 ~debug ~full ~opens ~raw Opens ~pos
1537
1576
in
1538
1577
match completable with
@@ -1734,8 +1773,8 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
1734
1773
| Some (typ , _env , completionContext ) ->
1735
1774
let items =
1736
1775
typ
1737
- |> completeTypedValue ~mode: (Pattern patternMode) ~full ~prefix
1738
- ~completion Context
1776
+ |> completeTypedValue ~raw Opens ~ mode: (Pattern patternMode) ~full
1777
+ ~prefix ~ completion Context
1739
1778
in
1740
1779
fallbackOrEmpty ~items () )
1741
1780
| None -> fallbackOrEmpty () )
@@ -1772,7 +1811,7 @@ let rec processCompletable ~debug ~full ~scope ~env ~pos ~forHover completable =
1772
1811
in
1773
1812
let items =
1774
1813
typ
1775
- |> completeTypedValue ~mode: Expression ~full ~prefix
1814
+ |> completeTypedValue ~raw Opens ~ mode:Expression ~full ~prefix
1776
1815
~completion Context
1777
1816
|> List. map (fun (c : Completion.t ) ->
1778
1817
if wrapInsertTextInBraces then
0 commit comments