@@ -258,6 +258,25 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
258
258
Utils. flattenLongIdent ~cut AtOffset ~jsx lid.txt
259
259
in
260
260
261
+ let currentCtxPath = ref None in
262
+ let setCurrentCtxPath ctxPath =
263
+ if ! Cfg. debugFollowCtxPath then
264
+ Printf. printf " setting current ctxPath: %s\n "
265
+ (Completable. contextPathToString ctxPath);
266
+ currentCtxPath := Some ctxPath
267
+ in
268
+ let resetCurrentCtxPath ctxPath =
269
+ (match (! currentCtxPath, ctxPath) with
270
+ | None , None -> ()
271
+ | _ ->
272
+ if ! Cfg. debugFollowCtxPath then
273
+ Printf. printf " resetting current ctxPath to: %s\n "
274
+ (match ctxPath with
275
+ | None -> " None"
276
+ | Some ctxPath -> Completable. contextPathToString ctxPath));
277
+ currentCtxPath := ctxPath
278
+ in
279
+
261
280
let found = ref false in
262
281
let result = ref None in
263
282
let scope = ref (Scope. create () ) in
@@ -443,7 +462,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
443
462
444
463
let case (iterator : Ast_iterator.iterator ) (case : Parsetree.case ) =
445
464
let oldScope = ! scope in
446
- scopePattern case.pc_lhs;
465
+ scopePattern ?contextPath: ! currentCtxPath case.pc_lhs;
447
466
completePattern case.pc_lhs;
448
467
Ast_iterator. default_iterator.case iterator case;
449
468
scope := oldScope
@@ -619,7 +638,34 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
619
638
| _ -> () );
620
639
Ast_iterator. default_iterator.attribute iterator (id, payload)
621
640
in
622
- let expr (iterator : Ast_iterator.iterator ) (expr : Parsetree.expression ) =
641
+ let rec iterateFnArguments ~args ~iterator ~isPipe
642
+ (argCompletable : Completable.t option ) =
643
+ match argCompletable with
644
+ | None -> (
645
+ match ! currentCtxPath with
646
+ | None -> ()
647
+ | Some functionContextPath ->
648
+ let currentUnlabelledCount = ref (if isPipe then 1 else 0 ) in
649
+ args
650
+ |> List. iter (fun (arg : arg ) ->
651
+ let previousCtxPath = ! currentCtxPath in
652
+ setCurrentCtxPath
653
+ (CArgument
654
+ {
655
+ functionContextPath;
656
+ argumentLabel =
657
+ (match arg with
658
+ | {label = None } ->
659
+ let current = ! currentUnlabelledCount in
660
+ currentUnlabelledCount := current + 1 ;
661
+ Unlabelled {argumentPosition = current}
662
+ | {label = Some {name; opt = true } } -> Optional name
663
+ | {label = Some {name; opt = false } } -> Labelled name);
664
+ });
665
+ expr iterator arg.exp;
666
+ resetCurrentCtxPath previousCtxPath))
667
+ | Some argCompletable -> setResult argCompletable
668
+ and expr (iterator : Ast_iterator.iterator ) (expr : Parsetree.expression ) =
623
669
let oldInJsxContext = ! inJsxContext in
624
670
let processed = ref false in
625
671
let setFound () =
@@ -773,7 +819,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
773
819
But it should not fire in foo(~a)<---there *)
774
820
not
775
821
(Loc. end_ expr.pexp_loc = posCursor
776
- && charBeforeCursor = Some ')' ) ->
822
+ && charBeforeCursor = Some ')' ) -> (
777
823
(* Complete fn argument values and named args when the fn call is piped. E.g. someVar->someFn(<com>). *)
778
824
let args = extractExpApplyArgs ~args in
779
825
let argCompletable =
@@ -786,15 +832,23 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
786
832
~first CharBeforeCursorNoWhite
787
833
| None -> None
788
834
in
789
-
790
- setResultOpt argCompletable
835
+ match argCompletable with
836
+ | None -> (
837
+ match exprToContextPath funExpr with
838
+ | None -> ()
839
+ | Some funCtxPath ->
840
+ let oldCtxPath = ! currentCtxPath in
841
+ setCurrentCtxPath funCtxPath;
842
+ argCompletable |> iterateFnArguments ~is Pipe:true ~args ~iterator ;
843
+ resetCurrentCtxPath oldCtxPath)
844
+ | Some argCompletable -> setResult argCompletable)
791
845
| Pexp_apply ({pexp_desc = Pexp_ident {txt = Lident "|." } } , [_; _]) ->
792
846
(* Ignore any other pipe. *)
793
847
()
794
848
| Pexp_apply (funExpr, args)
795
849
when not
796
850
(Loc. end_ expr.pexp_loc = posCursor
797
- && charBeforeCursor = Some ')' ) ->
851
+ && charBeforeCursor = Some ')' ) -> (
798
852
(* Complete fn argument values and named args when the fn call is _not_ piped. E.g. someFn(<com>). *)
799
853
let args = extractExpApplyArgs ~args in
800
854
if debug then
@@ -822,8 +876,16 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
822
876
~first CharBeforeCursorNoWhite
823
877
| None -> None
824
878
in
825
-
826
- setResultOpt argCompletable
879
+ match argCompletable with
880
+ | None -> (
881
+ match exprToContextPath funExpr with
882
+ | None -> ()
883
+ | Some funCtxPath ->
884
+ let oldCtxPath = ! currentCtxPath in
885
+ setCurrentCtxPath funCtxPath;
886
+ argCompletable |> iterateFnArguments ~is Pipe:false ~args ~iterator ;
887
+ resetCurrentCtxPath oldCtxPath)
888
+ | Some argCompletable -> setResult argCompletable)
827
889
| Pexp_send (lhs , {txt; loc} ) -> (
828
890
(* e["txt"]
829
891
If the string for txt is not closed, it could go over several lines.
@@ -850,16 +912,33 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
850
912
match exprToContextPath lhs with
851
913
| Some contextPath -> setResult (Cpath (CPObj (contextPath, label)))
852
914
| None -> () )
853
- | Pexp_fun (_lbl , defaultExpOpt , pat , e ) ->
915
+ | Pexp_fun (lbl , defaultExpOpt , pat , e ) ->
854
916
let oldScope = ! scope in
917
+ let oldCtxPath = ! currentCtxPath in
918
+ (* TODO: Haven't figured out how to count unlabelled args here yet... *)
919
+ (* TODO: This is broken *)
920
+ (match ! currentCtxPath with
921
+ | None -> ()
922
+ | Some ctxPath ->
923
+ setCurrentCtxPath
924
+ (CArgument
925
+ {
926
+ functionContextPath = ctxPath;
927
+ argumentLabel =
928
+ (match lbl with
929
+ | Nolabel -> Unlabelled {argumentPosition = 0 }
930
+ | Optional name -> Optional name
931
+ | Labelled name -> Labelled name);
932
+ }));
855
933
(match defaultExpOpt with
856
934
| None -> ()
857
935
| Some defaultExp -> iterator.expr iterator defaultExp);
858
- scopePattern pat;
936
+ scopePattern ?contextPath: ! currentCtxPath pat;
859
937
completePattern pat;
860
938
iterator.pat iterator pat;
861
939
iterator.expr iterator e;
862
940
scope := oldScope;
941
+ resetCurrentCtxPath oldCtxPath;
863
942
processed := true
864
943
| Pexp_let (recFlag , bindings , e ) ->
865
944
let oldScope = ! scope in
0 commit comments