@@ -18,6 +18,11 @@ let isPatternHole pat =
18
18
| Ppat_extension ({txt = "rescript.patternhole" } , _ ) -> true
19
19
| _ -> false
20
20
21
+ let isPatternTuple pat =
22
+ match pat.Parsetree. ppat_desc with
23
+ | Ppat_tuple _ -> true
24
+ | _ -> false
25
+
21
26
type prop = {
22
27
name : string ;
23
28
posStart : int * int ;
@@ -233,6 +238,12 @@ let findArgCompletables ~(args : arg list) ~endPos ~posBeforeCursor
233
238
})
234
239
| _ -> loop args
235
240
241
+ let lastLocIndexBeforePos locs ~pos =
242
+ let posNum = ref (- 1 ) in
243
+ locs
244
+ |> List. iteri (fun index loc -> if pos > = Loc. start loc then posNum := index);
245
+ if ! posNum > - 1 then Some ! posNum else None
246
+
236
247
let rec exprToContextPath (e : Parsetree.expression ) =
237
248
match e.pexp_desc with
238
249
| Pexp_constant (Pconst_string _ ) -> Some Completable. CPString
@@ -504,26 +515,31 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
504
515
when ppat_loc
505
516
|> CursorPosition. classifyLoc ~pos: posBeforeCursor
506
517
= HasCursor ->
507
- (* Empty payload *)
518
+ (* Empty payload with cursor, like: Test(<com>) *)
508
519
Some
509
520
( " " ,
510
521
[
511
522
Completable. PVariantPayload
512
523
{constructorName = getUnqualifiedName txt; itemNum = 0 };
513
524
]
514
525
@ patternPath )
515
- | Ppat_construct
516
- ( {txt},
517
- Some
518
- ({
519
- ppat_loc;
520
- ppat_desc =
521
- ( Ppat_var _ | Ppat_record _ | Ppat_construct _
522
- | Ppat_variant _ );
523
- } as pat) )
524
- when ppat_loc
526
+ | Ppat_construct ({txt}, Some pat)
527
+ when posBeforeCursor > = (pat.ppat_loc |> Loc. end_)
528
+ && firstCharBeforeCursorNoWhite = Some ','
529
+ && isPatternTuple pat = false ->
530
+ (* Empty payload with trailing ',', like: Test(true, <com>) *)
531
+ Some
532
+ ( " " ,
533
+ [
534
+ Completable. PVariantPayload
535
+ {constructorName = getUnqualifiedName txt; itemNum = 1 };
536
+ ]
537
+ @ patternPath )
538
+ | Ppat_construct ({txt}, Some pat)
539
+ when pat.ppat_loc
525
540
|> CursorPosition. classifyLoc ~pos: posBeforeCursor
526
- = HasCursor ->
541
+ = HasCursor
542
+ && isPatternTuple pat = false ->
527
543
(* Single payload *)
528
544
pat
529
545
|> traversePattern
@@ -537,51 +553,75 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
537
553
({txt}, Some {ppat_loc; ppat_desc = Ppat_tuple tupleItems})
538
554
when ppat_loc
539
555
|> CursorPosition. classifyLoc ~pos: posBeforeCursor
540
- = HasCursor ->
541
- (* Multiple payloads with cursor in item *)
542
- (* TODO: New item with comma *)
556
+ = HasCursor -> (
543
557
let itemNum = ref (- 1 ) in
544
- tupleItems
545
- |> List. find_map (fun pat ->
546
- itemNum := ! itemNum + 1 ;
547
- pat
548
- |> traversePattern
549
- ~pattern Path:
550
- ([
551
- Completable. PVariantPayload
552
- {
553
- constructorName = getUnqualifiedName txt;
554
- itemNum = ! itemNum;
555
- };
556
- ]
557
- @ patternPath))
558
+ let itemWithCursor =
559
+ tupleItems
560
+ |> List. find_map (fun pat ->
561
+ itemNum := ! itemNum + 1 ;
562
+ pat
563
+ |> traversePattern
564
+ ~pattern Path:
565
+ ([
566
+ Completable. PVariantPayload
567
+ {
568
+ constructorName = getUnqualifiedName txt;
569
+ itemNum = ! itemNum;
570
+ };
571
+ ]
572
+ @ patternPath))
573
+ in
574
+ match (itemWithCursor, firstCharBeforeCursorNoWhite) with
575
+ | None , Some ',' -> (
576
+ (* No tuple item has the cursor, but there's a comma before the cursor.
577
+ Figure out what arg we're trying to complete. Example: Test(true, <com>, None) *)
578
+ let locs = tupleItems |> List. map (fun p -> p.Parsetree. ppat_loc) in
579
+ match locs |> lastLocIndexBeforePos ~pos: posBeforeCursor with
580
+ | None -> None
581
+ | Some itemNum ->
582
+ Some
583
+ ( " " ,
584
+ [
585
+ Completable. PVariantPayload
586
+ {
587
+ constructorName = getUnqualifiedName txt;
588
+ itemNum = itemNum + 1 ;
589
+ };
590
+ ]
591
+ @ patternPath ))
592
+ | v , _ -> v)
558
593
| Ppat_variant
559
594
( txt,
560
595
Some {ppat_loc; ppat_desc = Ppat_construct ({txt = Lident " ()" }, _)}
561
596
)
562
597
when ppat_loc
563
598
|> CursorPosition. classifyLoc ~pos: posBeforeCursor
564
599
= HasCursor ->
565
- (* Empty payload *)
600
+ (* Empty payload with cursor, like: #test(<com>) *)
566
601
Some
567
602
( " " ,
568
603
[
569
604
Completable. PPolyvariantPayload
570
605
{constructorName = txt; itemNum = 0 };
571
606
]
572
607
@ patternPath )
573
- | Ppat_variant
574
- ( txt,
575
- Some
576
- ({
577
- ppat_loc;
578
- ppat_desc =
579
- ( Ppat_var _ | Ppat_record _ | Ppat_construct _
580
- | Ppat_variant _ );
581
- } as pat) )
582
- when ppat_loc
608
+ | Ppat_variant (txt, Some pat)
609
+ when posBeforeCursor > = (pat.ppat_loc |> Loc. end_)
610
+ && firstCharBeforeCursorNoWhite = Some ','
611
+ && isPatternTuple pat = false ->
612
+ (* Empty payload with trailing ',', like: #test(true, <com>) *)
613
+ Some
614
+ ( " " ,
615
+ [
616
+ Completable. PPolyvariantPayload
617
+ {constructorName = txt; itemNum = 1 };
618
+ ]
619
+ @ patternPath )
620
+ | Ppat_variant (txt, Some pat)
621
+ when pat.ppat_loc
583
622
|> CursorPosition. classifyLoc ~pos: posBeforeCursor
584
- = HasCursor ->
623
+ = HasCursor
624
+ && isPatternTuple pat = false ->
585
625
(* Single payload *)
586
626
pat
587
627
|> traversePattern
@@ -594,21 +634,37 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor ~text =
594
634
| Ppat_variant (txt, Some {ppat_loc; ppat_desc = Ppat_tuple tupleItems})
595
635
when ppat_loc
596
636
|> CursorPosition. classifyLoc ~pos: posBeforeCursor
597
- = HasCursor ->
598
- (* Multiple payloads with cursor in item *)
599
- (* TODO: New item with comma *)
637
+ = HasCursor -> (
600
638
let itemNum = ref (- 1 ) in
601
- tupleItems
602
- |> List. find_map (fun pat ->
603
- itemNum := ! itemNum + 1 ;
604
- pat
605
- |> traversePattern
606
- ~pattern Path:
607
- ([
608
- Completable. PPolyvariantPayload
609
- {constructorName = txt; itemNum = ! itemNum};
610
- ]
611
- @ patternPath))
639
+ let itemWithCursor =
640
+ tupleItems
641
+ |> List. find_map (fun pat ->
642
+ itemNum := ! itemNum + 1 ;
643
+ pat
644
+ |> traversePattern
645
+ ~pattern Path:
646
+ ([
647
+ Completable. PPolyvariantPayload
648
+ {constructorName = txt; itemNum = ! itemNum};
649
+ ]
650
+ @ patternPath))
651
+ in
652
+ match (itemWithCursor, firstCharBeforeCursorNoWhite) with
653
+ | None , Some ',' -> (
654
+ (* No tuple item has the cursor, but there's a comma before the cursor.
655
+ Figure out what arg we're trying to complete. Example: #test(true, <com>, None) *)
656
+ let locs = tupleItems |> List. map (fun p -> p.Parsetree. ppat_loc) in
657
+ match locs |> lastLocIndexBeforePos ~pos: posBeforeCursor with
658
+ | None -> None
659
+ | Some itemNum ->
660
+ Some
661
+ ( " " ,
662
+ [
663
+ Completable. PPolyvariantPayload
664
+ {constructorName = txt; itemNum = itemNum + 1 };
665
+ ]
666
+ @ patternPath ))
667
+ | v , _ -> v)
612
668
| _ -> None
613
669
else None
614
670
in
0 commit comments