@@ -320,6 +320,8 @@ let makeExternalDecl fnName loc namedArgListWithKeyAndRef namedTypeList =
320320 (List. map pluckLabelDefaultLocType namedArgListWithKeyAndRef)
321321 (makePropsType ~loc namedTypeList)
322322
323+ let unerasableIgnore loc = ({loc; txt = " warning" }, (PStr [Str. eval (Exp. constant (Pconst_string (" -16" , None )))]))
324+
323325(* TODO: some line number might still be wrong *)
324326let jsxMapper () =
325327
@@ -516,13 +518,12 @@ let jsxMapper () =
516518 | _ -> None ) in
517519
518520 recursivelyTransformNamedArgsForMake mapper expression ((arg, default, pattern, alias, pattern.ppat_loc, type_) :: list )
519-
520521 | Pexp_fun (Nolabel , _ , { ppat_desc = (Ppat_construct ({txt = Lident "()" } , _ ) | Ppat_any )} , expression ) ->
521- (expression.pexp_desc, list , None )
522+ (list , None )
522523 | Pexp_fun (Nolabel, _ , { ppat_desc = Ppat_var ({txt} )} , expression ) ->
523- (expression.pexp_desc, list , Some txt)
524+ (list , Some txt)
524525
525- | innerExpression -> (innerExpression, list , None )
526+ | _ -> (list , None )
526527 in
527528
528529
@@ -624,53 +625,80 @@ let jsxMapper () =
624625 valueBindings
625626 )
626627 } ->
628+ let fileName = filenameFromLoc pstr_loc in
629+ let emptyLoc = Location. in_file fileName in
627630 let mapBinding binding = if (hasAttrOnBinding binding) then
628631 let fnName = getFnName binding in
629- let fileName = filenameFromLoc pstr_loc in
630632 let fullModuleName = makeModuleName fileName ! nestedModules fnName in
631- let emptyLoc = Location. in_file fileName in
632- let modifiedBinding binding =
633+ let modifiedBindingOld binding =
633634 let expression = binding.pvb_expr in
634- let wrapExpressionWithBinding expressionFn expression = {(filterAttrOnBinding binding) with pvb_expr = expressionFn expression} in
635635 (* TODO: there is a long-tail of unsupported features inside of blocks - Pexp_letmodule , Pexp_letexception , Pexp_ifthenelse *)
636636 let rec spelunkForFunExpression expression = (match expression with
637637 (* let make = (~prop) => ... *)
638638 | {
639639 pexp_desc = Pexp_fun _
640- } -> (( fun expressionDesc -> { expression with pexp_desc = expressionDesc}), expression)
640+ } -> expression
641641 (* let make = {let foo = bar in (~prop) => ...} *)
642642 | {
643643 pexp_desc = Pexp_let (recursive, vbs, returnExpression)
644644 } ->
645645 (* 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
648647 (* let make = React.forwardRef((~prop) => ...) *)
649648
650649 | { 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
658651 | {
659652 pexp_desc = Pexp_sequence (wrapperExpression, innerFunctionExpression)
660653 } ->
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
668655 | _ -> raise (Invalid_argument " react.component calls can only be on function definitions or component wrappers (forwardRef, memo)." )
669656 ) in
670- let (wrapExpression, expression) = spelunkForFunExpression expression in
671- (wrapExpressionWithBinding wrapExpression, expression)
657+ spelunkForFunExpression expression
672658 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
674702 let reactComponentAttribute = try
675703 Some (List. find hasAttr binding.pvb_attributes)
676704 with | Not_found -> None in
@@ -679,41 +707,43 @@ let jsxMapper () =
679707 | None -> (emptyLoc, None ) in
680708 let props = getPropsAttr payload in
681709 (* 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
683712 let namedArgListWithKeyAndRef = (optional(" key" ), None , Pat. var {txt = " key" ; loc = emptyLoc}, " key" , emptyLoc, Some (keyType emptyLoc)) :: namedArgList in
684713 let namedArgListWithKeyAndRef = match forwardRef with
685714 | Some (_ ) -> (optional(" ref" ), None , Pat. var {txt = " key" ; loc = emptyLoc}, " ref" , emptyLoc, None ) :: namedArgListWithKeyAndRef
686715 | None -> namedArgListWithKeyAndRef
687716 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 );
698727 loc
699728 })
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+ )
701740 ) 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
717747 let innerExpressionWithRef = match (forwardRef) with
718748 | Some txt ->
719749 {innerExpression with pexp_desc = Pexp_fun (nolabel, None , {
@@ -723,51 +753,59 @@ let jsxMapper () =
723753 }, innerExpression)}
724754 | None -> innerExpression
725755 in
726- let fullExpression = ( Pexp_fun (
727- nolabel,
728- None ,
756+ let fullExpression = Exp. fun_
757+ nolabel
758+ None
729759 {
730760 ppat_desc = Ppat_constraint (
731761 makePropsName ~loc: emptyLoc props.propsName,
732762 makePropsType ~loc: emptyLoc namedTypeList
733763 );
734764 ppat_loc = emptyLoc;
735765 ppat_attributes = [] ;
736- },
737- innerExpressionWithRef
738- )) in
766+ }
767+ innerExpressionWithRef in
739768 let fullExpression = match (fullModuleName) with
740769 | ("" ) -> fullExpression
741- | (txt ) -> Pexp_let (
742- Nonrecursive ,
770+ | (txt ) -> Exp. let_
771+ Nonrecursive
743772 [Vb. mk
744773 ~loc: emptyLoc
745774 (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
751778 let newBinding = bindingWrapper fullExpression in
752- (Some externalDecl, newBinding)
779+ (Some externalDecl, binding, Some newBinding)
753780 else
754- (None , binding)
781+ (None , binding, None )
755782 in
756783 let structuresAndBinding = List. map mapBinding valueBindings in
757- let otherStructures (extern , binding ) (externs , bindings ) =
784+ let otherStructures (extern , binding , newBinding ) (externs , bindings , newBindings ) =
758785 let externs = match extern with
759786 | Some extern -> extern :: externs
760787 | 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)
762792 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 @ [ {
765795 pstr_loc;
766796 pstr_desc = Pstr_value (
767797 recFlag,
768798 bindings
769799 )
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
771809 | structure -> structure :: returnStructures in
772810
773811 let reactComponentTransform mapper structures =
0 commit comments