@@ -320,6 +320,8 @@ let makeExternalDecl fnName loc namedArgListWithKeyAndRef namedTypeList =
320
320
(List. map pluckLabelDefaultLocType namedArgListWithKeyAndRef)
321
321
(makePropsType ~loc namedTypeList)
322
322
323
+ let unerasableIgnore loc = ({loc; txt = " warning" }, (PStr [Str. eval (Exp. constant (Pconst_string (" -16" , None )))]))
324
+
323
325
(* TODO: some line number might still be wrong *)
324
326
let jsxMapper () =
325
327
@@ -516,13 +518,12 @@ let jsxMapper () =
516
518
| _ -> None ) in
517
519
518
520
recursivelyTransformNamedArgsForMake mapper expression ((arg, default, pattern, alias, pattern.ppat_loc, type_) :: list )
519
-
520
521
| Pexp_fun (Nolabel , _ , { ppat_desc = (Ppat_construct ({txt = Lident "()" } , _ ) | Ppat_any )} , expression ) ->
521
- (expression.pexp_desc, list , None )
522
+ (list , None )
522
523
| Pexp_fun (Nolabel, _ , { ppat_desc = Ppat_var ({txt} )} , expression ) ->
523
- (expression.pexp_desc, list , Some txt)
524
+ (list , Some txt)
524
525
525
- | innerExpression -> (innerExpression, list , None )
526
+ | _ -> (list , None )
526
527
in
527
528
528
529
@@ -624,53 +625,80 @@ let jsxMapper () =
624
625
valueBindings
625
626
)
626
627
} ->
628
+ let fileName = filenameFromLoc pstr_loc in
629
+ let emptyLoc = Location. in_file fileName in
627
630
let mapBinding binding = if (hasAttrOnBinding binding) then
628
631
let fnName = getFnName binding in
629
- let fileName = filenameFromLoc pstr_loc in
630
632
let fullModuleName = makeModuleName fileName ! nestedModules fnName in
631
- let emptyLoc = Location. in_file fileName in
632
- let modifiedBinding binding =
633
+ let modifiedBindingOld binding =
633
634
let expression = binding.pvb_expr in
634
- let wrapExpressionWithBinding expressionFn expression = {(filterAttrOnBinding binding) with pvb_expr = expressionFn expression} in
635
635
(* TODO: there is a long-tail of unsupported features inside of blocks - Pexp_letmodule , Pexp_letexception , Pexp_ifthenelse *)
636
636
let rec spelunkForFunExpression expression = (match expression with
637
637
(* let make = (~prop) => ... *)
638
638
| {
639
639
pexp_desc = Pexp_fun _
640
- } -> (( fun expressionDesc -> { expression with pexp_desc = expressionDesc}), expression)
640
+ } -> expression
641
641
(* let make = {let foo = bar in (~prop) => ...} *)
642
642
| {
643
643
pexp_desc = Pexp_let (recursive, vbs, returnExpression)
644
644
} ->
645
645
(* here's where we spelunk! *)
646
- let (wrapExpression, realReturnExpression) = spelunkForFunExpression returnExpression in
647
- ((fun expressionDesc -> {expression with pexp_desc = Pexp_let (recursive, vbs, wrapExpression expressionDesc)}), realReturnExpression)
646
+ spelunkForFunExpression returnExpression
648
647
(* let make = React.forwardRef((~prop) => ...) *)
649
648
650
649
| { pexp_desc = Pexp_apply (wrapperExpression , [(Nolabel, innerFunctionExpression )]) } ->
651
- let (wrapExpression, realReturnExpression) = spelunkForFunExpression innerFunctionExpression in
652
- ((fun expressionDesc -> {
653
- expression with pexp_desc =
654
- Pexp_apply (wrapperExpression, [(nolabel, wrapExpression expressionDesc)])
655
- }),
656
- realReturnExpression
657
- )
650
+ spelunkForFunExpression innerFunctionExpression
658
651
| {
659
652
pexp_desc = Pexp_sequence (wrapperExpression, innerFunctionExpression)
660
653
} ->
661
- let (wrapExpression, realReturnExpression) = spelunkForFunExpression innerFunctionExpression in
662
- ((fun expressionDesc -> {
663
- expression with pexp_desc =
664
- Pexp_sequence (wrapperExpression, wrapExpression expressionDesc)
665
- }),
666
- realReturnExpression
667
- )
654
+ spelunkForFunExpression innerFunctionExpression
668
655
| _ -> raise (Invalid_argument " react.component calls can only be on function definitions or component wrappers (forwardRef, memo)." )
669
656
) in
670
- let (wrapExpression, expression) = spelunkForFunExpression expression in
671
- (wrapExpressionWithBinding wrapExpression, expression)
657
+ spelunkForFunExpression expression
672
658
in
673
- let (bindingWrapper, expression) = modifiedBinding binding in
659
+ let modifiedBinding binding =
660
+ let wrapExpressionWithBinding expressionFn expression = Vb. mk ~attrs: (List. filter otherAttrsPure binding.pvb_attributes) (Pat. var {loc = emptyLoc; txt = fnName}) (expressionFn expression) in
661
+ let expression = binding.pvb_expr in
662
+ let unerasableIgnoreExp exp = { exp with pexp_attributes = (unerasableIgnore emptyLoc) :: exp.pexp_attributes } in
663
+ (* TODO: there is a long-tail of unsupported features inside of blocks - Pexp_letmodule , Pexp_letexception , Pexp_ifthenelse *)
664
+ let rec spelunkForFunExpression expression = (match expression with
665
+ (* let make = (~prop) => ... with no final unit *)
666
+ | {
667
+ pexp_desc = Pexp_fun ((Labelled (_) | Optional (_) as label), default, pattern, ({pexp_desc = Pexp_fun _} as internalExpression))
668
+ } ->
669
+ let (wrap, hasUnit, exp) = spelunkForFunExpression internalExpression in
670
+ (wrap, hasUnit, unerasableIgnoreExp {expression with pexp_desc = Pexp_fun (label, default, pattern, exp)})
671
+ (* let make = (()) => ... *)
672
+ (* let make = (_) => ... *)
673
+ | {
674
+ pexp_desc = Pexp_fun (Nolabel , default, { ppat_desc = Ppat_construct ({txt = Lident " ()" }, _) | Ppat_any }, internalExpression)
675
+ } -> ((fun a -> a), true , expression)
676
+ (* let make = (~prop) => ... *)
677
+ | {
678
+ pexp_desc = Pexp_fun (label, default, pattern, internalExpression)
679
+ } -> ((fun a -> a), false , unerasableIgnoreExp expression)
680
+ (* let make = {let foo = bar in (~prop) => ...} *)
681
+ | {
682
+ pexp_desc = Pexp_let (recursive, vbs, internalExpression)
683
+ } ->
684
+ (* here's where we spelunk! *)
685
+ let (wrap, hasUnit, exp) = spelunkForFunExpression internalExpression in
686
+ (wrap, hasUnit, {expression with pexp_desc = Pexp_let (recursive, vbs, exp)})
687
+ (* let make = React.forwardRef((~prop) => ...) *)
688
+ | { pexp_desc = Pexp_apply (wrapperExpression , [(Nolabel, internalExpression )]) } ->
689
+ let (_, hasUnit, exp) = spelunkForFunExpression internalExpression in
690
+ ((fun exp -> Exp. apply wrapperExpression [(nolabel, exp)]), hasUnit, exp)
691
+ | {
692
+ pexp_desc = Pexp_sequence (wrapperExpression, internalExpression)
693
+ } ->
694
+ let (wrap, hasUnit, exp) = spelunkForFunExpression internalExpression in
695
+ (wrap, hasUnit, {expression with pexp_desc = Pexp_sequence (wrapperExpression, exp)})
696
+ | e -> ((fun a -> a), false , e)
697
+ ) in
698
+ let (wrapExpression, hasUnit, expression) = spelunkForFunExpression expression in
699
+ (wrapExpressionWithBinding wrapExpression, hasUnit, expression)
700
+ in
701
+ let (bindingWrapper, hasUnit, expression) = modifiedBinding binding in
674
702
let reactComponentAttribute = try
675
703
Some (List. find hasAttr binding.pvb_attributes)
676
704
with | Not_found -> None in
@@ -679,41 +707,43 @@ let jsxMapper () =
679
707
| None -> (emptyLoc, None ) in
680
708
let props = getPropsAttr payload in
681
709
(* do stuff here! *)
682
- let (innerFunctionExpression, namedArgList, forwardRef) = recursivelyTransformNamedArgsForMake mapper expression [] in
710
+ let (namedArgList, forwardRef) = recursivelyTransformNamedArgsForMake mapper (modifiedBindingOld binding) [] in
711
+ let binding = { binding with pvb_expr = expression; pvb_attributes = [] } in
683
712
let namedArgListWithKeyAndRef = (optional(" key" ), None , Pat. var {txt = " key" ; loc = emptyLoc}, " key" , emptyLoc, Some (keyType emptyLoc)) :: namedArgList in
684
713
let namedArgListWithKeyAndRef = match forwardRef with
685
714
| Some (_ ) -> (optional(" ref" ), None , Pat. var {txt = " key" ; loc = emptyLoc}, " ref" , emptyLoc, None ) :: namedArgListWithKeyAndRef
686
715
| None -> namedArgListWithKeyAndRef
687
716
in
688
- let namedTypeList = List. fold_left argToType [] namedArgList in
689
- let externalDecl = makeExternalDecl fnName attr_loc namedArgListWithKeyAndRef namedTypeList in
690
- let makeLet innerExpression ( label , default , pattern , _alias , loc , _type ) =
691
- let labelString = ( match label with | label when isOptional label || isLabelled label -> getLabel label | _ -> raise ( Invalid_argument " This should never happen " )) in
692
- let expression = ( Exp. apply ~ loc
693
- ( Exp. ident ~loc {txt = ( Lident " ## " ); loc })
694
- [
695
- (nolabel, Exp. ident ~loc {txt = ( Lident props.propsName); loc });
696
- (nolabel, Exp. ident ~loc {
697
- txt = (Lident labelString );
717
+ let namedArgListWithKeyAndRefForNew = match forwardRef with
718
+ | Some ( _ ) -> namedArgList @ [(nolabel, None , Pat. var {txt = " ref " ; loc = emptyLoc}, " ref " , emptyLoc, None )]
719
+ | None -> namedArgList
720
+ in
721
+ let pluckArg ( label , _ , _ , alias , loc , _ ) =
722
+ let labelString = ( match label with | label when isOptional label || isLabelled label -> getLabel label | _ -> " " ) in
723
+ (label,
724
+ ( match labelString with
725
+ | "" -> ( Exp. ident ~loc {
726
+ txt = (Lident alias );
698
727
loc
699
728
})
700
- ]
729
+ | labelString -> (Exp. apply ~loc
730
+ (Exp. ident ~loc {txt = (Lident " ##" ); loc })
731
+ [
732
+ (nolabel, Exp. ident ~loc {txt = (Lident props.propsName); loc });
733
+ (nolabel, Exp. ident ~loc {
734
+ txt = (Lident labelString);
735
+ loc
736
+ })
737
+ ]
738
+ )
739
+ )
701
740
) in
702
- let expression = match (default) with
703
- | (Some default ) -> Exp. match_ expression [
704
- Exp. case
705
- (Pat. construct {loc; txt= Lident " Some" } (Some (Pat. var ~loc {txt = labelString; loc})))
706
- (Exp. ident ~loc {txt = (Lident labelString); loc = { loc with Location. loc_ghost = true }});
707
- Exp. case
708
- (Pat. construct {loc; txt= Lident " None" } None )
709
- default
710
- ]
711
- | None -> expression in
712
- let letExpression = Vb. mk
713
- pattern
714
- expression in
715
- Exp. let_ ~loc Nonrecursive [letExpression] innerExpression in
716
- let innerExpression = List. fold_left makeLet (Exp. mk innerFunctionExpression) namedArgList in
741
+ let namedTypeList = List. fold_left argToType [] namedArgList in
742
+ let loc = emptyLoc in
743
+ let externalDecl = makeExternalDecl fnName loc namedArgListWithKeyAndRef namedTypeList in
744
+ let innerExpressionArgs = (List. map pluckArg namedArgListWithKeyAndRefForNew) @
745
+ if hasUnit then [(Nolabel , Exp. construct {loc; txt = Lident " ()" } None )] else [] in
746
+ let innerExpression = Exp. apply (Exp. ident {loc; txt = Lident (fnName)}) innerExpressionArgs in
717
747
let innerExpressionWithRef = match (forwardRef) with
718
748
| Some txt ->
719
749
{innerExpression with pexp_desc = Pexp_fun (nolabel, None , {
@@ -723,51 +753,59 @@ let jsxMapper () =
723
753
}, innerExpression)}
724
754
| None -> innerExpression
725
755
in
726
- let fullExpression = ( Pexp_fun (
727
- nolabel,
728
- None ,
756
+ let fullExpression = Exp. fun_
757
+ nolabel
758
+ None
729
759
{
730
760
ppat_desc = Ppat_constraint (
731
761
makePropsName ~loc: emptyLoc props.propsName,
732
762
makePropsType ~loc: emptyLoc namedTypeList
733
763
);
734
764
ppat_loc = emptyLoc;
735
765
ppat_attributes = [] ;
736
- },
737
- innerExpressionWithRef
738
- )) in
766
+ }
767
+ innerExpressionWithRef in
739
768
let fullExpression = match (fullModuleName) with
740
769
| ("" ) -> fullExpression
741
- | (txt ) -> Pexp_let (
742
- Nonrecursive ,
770
+ | (txt ) -> Exp. let_
771
+ Nonrecursive
743
772
[Vb. mk
744
773
~loc: emptyLoc
745
774
(Pat. var ~loc: emptyLoc {loc = emptyLoc; txt})
746
- (Exp. mk ~loc: emptyLoc fullExpression)
747
- ],
748
- (Exp. ident ~loc: emptyLoc {loc = emptyLoc; txt = Lident txt})
749
- )
750
- in
775
+ fullExpression
776
+ ]
777
+ (Exp. ident ~loc: emptyLoc {loc = emptyLoc; txt = Lident txt}) in
751
778
let newBinding = bindingWrapper fullExpression in
752
- (Some externalDecl, newBinding)
779
+ (Some externalDecl, binding, Some newBinding)
753
780
else
754
- (None , binding)
781
+ (None , binding, None )
755
782
in
756
783
let structuresAndBinding = List. map mapBinding valueBindings in
757
- let otherStructures (extern , binding ) (externs , bindings ) =
784
+ let otherStructures (extern , binding , newBinding ) (externs , bindings , newBindings ) =
758
785
let externs = match extern with
759
786
| Some extern -> extern :: externs
760
787
| None -> externs in
761
- (externs, binding :: bindings)
788
+ let newBindings = match newBinding with
789
+ | Some newBinding -> newBinding :: newBindings
790
+ | None -> newBindings in
791
+ (externs, binding :: bindings, newBindings)
762
792
in
763
- let (externs, bindings) = List. fold_right otherStructures structuresAndBinding ([] , [] ) in
764
- externs @ {
793
+ let (externs, bindings, newBindings ) = List. fold_right otherStructures structuresAndBinding ([] , [] , [] ) in
794
+ externs @ [ {
765
795
pstr_loc;
766
796
pstr_desc = Pstr_value (
767
797
recFlag,
768
798
bindings
769
799
)
770
- } :: returnStructures
800
+ }] @ (match newBindings with
801
+ | [] -> []
802
+ | newBindings -> [{
803
+ pstr_loc = emptyLoc;
804
+ pstr_desc = Pstr_value (
805
+ recFlag,
806
+ newBindings
807
+ )
808
+ }]) @ returnStructures
771
809
| structure -> structure :: returnStructures in
772
810
773
811
let reactComponentTransform mapper structures =
0 commit comments