@@ -46,6 +46,38 @@ let ref_type loc =
4646 {loc; txt = Ldot (Ldot (Lident " Js" , " Nullable" ), " t" )}
4747 [ref_type_var loc]
4848
49+ let jsx_element_type ~loc =
50+ Typ. constr ~loc {loc; txt = Ldot (Lident " Jsx" , " element" )} []
51+
52+ let jsx_element_constraint ~loc expr =
53+ Exp. constraint_ ~loc expr (jsx_element_type ~loc )
54+
55+ let rec constrain_jsx_return ~loc expr =
56+ match expr.pexp_desc with
57+ | Pexp_fun ({rhs} as desc ) ->
58+ {
59+ expr with
60+ pexp_desc = Pexp_fun {desc with rhs = constrain_jsx_return ~loc rhs};
61+ }
62+ | Pexp_newtype (param , inner ) ->
63+ {
64+ expr with
65+ pexp_desc = Pexp_newtype (param, constrain_jsx_return ~loc inner);
66+ }
67+ | Pexp_constraint (inner , _ ) ->
68+ jsx_element_constraint ~loc (constrain_jsx_return ~loc inner)
69+ | Pexp_let (rec_flag , bindings , body ) ->
70+ {
71+ expr with
72+ pexp_desc = Pexp_let (rec_flag, bindings, constrain_jsx_return ~loc body);
73+ }
74+ | Pexp_sequence (first , second ) ->
75+ {
76+ expr with
77+ pexp_desc = Pexp_sequence (first, constrain_jsx_return ~loc second);
78+ }
79+ | _ -> jsx_element_constraint ~loc expr
80+
4981let merlin_focus = ({loc = Location. none; txt = " merlin.focus" }, PStr [] )
5082
5183(* Helper method to filter out any attribute that isn't [@react.component] *)
@@ -713,6 +745,10 @@ let map_binding ~config ~empty_loc ~pstr_loc ~file_name ~rec_flag binding =
713745 vb_match_expr named_arg_list expression
714746 else expression
715747 in
748+ let expression =
749+ Exp. constraint_ ~loc: binding_loc expression
750+ (jsx_element_type ~loc: binding_loc)
751+ in
716752 (* (ref) => expr *)
717753 let expression =
718754 List. fold_left
@@ -784,6 +820,7 @@ let map_binding ~config ~empty_loc ~pstr_loc ~file_name ~rec_flag binding =
784820 (Some props_record_type, binding, new_binding))
785821 else if Jsx_common. has_attr_on_binding Jsx_common. has_attr_with_props binding
786822 then
823+ let binding_loc = binding.pvb_loc in
787824 let modified_binding =
788825 {
789826 binding with
@@ -839,21 +876,28 @@ let map_binding ~config ~empty_loc ~pstr_loc ~file_name ~rec_flag binding =
839876 | _ -> Pat. var {txt = " props" ; loc}
840877 in
841878
879+ let applied_expression =
880+ Exp. apply
881+ (Exp. ident
882+ {
883+ txt =
884+ Lident
885+ (match rec_flag with
886+ | Recursive -> internal_fn_name
887+ | Nonrecursive -> fn_name);
888+ loc;
889+ })
890+ [(Nolabel , Exp. ident {txt = Lident " props" ; loc})]
891+ in
892+ let applied_expression =
893+ Jsx_common. async_component ~async: is_async applied_expression
894+ in
895+ let applied_expression =
896+ Exp. constraint_ ~loc applied_expression (jsx_element_type ~loc )
897+ in
842898 let wrapper_expr =
843899 Exp. fun_ ~arity: None Nolabel None props_pattern
844- ~attrs: binding.pvb_expr.pexp_attributes
845- (Jsx_common. async_component ~async: is_async
846- (Exp. apply
847- (Exp. ident
848- {
849- txt =
850- Lident
851- (match rec_flag with
852- | Recursive -> internal_fn_name
853- | Nonrecursive -> fn_name);
854- loc;
855- })
856- [(Nolabel , Exp. ident {txt = Lident " props" ; loc})]))
900+ ~attrs: binding.pvb_expr.pexp_attributes applied_expression
857901 in
858902
859903 let wrapper_expr = Ast_uncurried. uncurried_fun ~arity: 1 wrapper_expr in
@@ -874,18 +918,20 @@ let map_binding ~config ~empty_loc ~pstr_loc ~file_name ~rec_flag binding =
874918 | Recursive -> None
875919 | Nonrecursive ->
876920 Some
877- (make_new_binding ~loc: empty_loc ~full_module_name modified_binding)
921+ (make_new_binding ~loc: binding_loc ~full_module_name modified_binding)
878922 in
879923 ( None ,
880924 {
881925 binding with
882926 pvb_attributes = binding.pvb_attributes |> List. filter other_attrs_pure;
883927 pvb_expr =
884- {
885- binding.pvb_expr with
886- (* moved to wrapper_expr *)
887- pexp_attributes = [] ;
888- };
928+ ( binding.pvb_expr |> fun expr ->
929+ {
930+ expr with
931+ (* moved to wrapper_expr *)
932+ pexp_attributes = [] ;
933+ }
934+ |> constrain_jsx_return ~loc: binding_loc );
889935 },
890936 new_binding )
891937 else (None , binding, None )
@@ -934,7 +980,7 @@ let transform_structure_item ~config item =
934980 (arg.lbl, arg.attrs, return_value.ptyp_loc, arg.typ) :: types )
935981 | _ -> (full_type, types)
936982 in
937- let inner_type , prop_types = get_prop_types [] pval_type in
983+ let _ , prop_types = get_prop_types [] pval_type in
938984 let named_type_list = List. fold_left arg_to_concrete_type [] prop_types in
939985 let ret_props_type =
940986 Typ. constr ~loc: pstr_loc
@@ -955,7 +1001,7 @@ let transform_structure_item ~config item =
9551001 let new_external_type =
9561002 Ptyp_constr
9571003 ( {loc = pstr_loc; txt = module_access_name config " componentLike" },
958- [ret_props_type; inner_type ] )
1004+ [ret_props_type; jsx_element_type ~loc: pstr_loc ] )
9591005 in
9601006 let new_structure =
9611007 {
@@ -1046,7 +1092,7 @@ let transform_signature_item ~config item =
10461092 (arg.lbl, arg.attrs, return_value.ptyp_loc, arg.typ) :: types )
10471093 | _ -> (full_type, types)
10481094 in
1049- let inner_type , prop_types = get_prop_types [] pval_type in
1095+ let _ , prop_types = get_prop_types [] pval_type in
10501096 let named_type_list = List. fold_left arg_to_concrete_type [] prop_types in
10511097 let ret_props_type =
10521098 Typ. constr
@@ -1067,7 +1113,7 @@ let transform_signature_item ~config item =
10671113 let new_external_type =
10681114 Ptyp_constr
10691115 ( {loc = psig_loc; txt = module_access_name config " componentLike" },
1070- [ret_props_type; inner_type ] )
1116+ [ret_props_type; jsx_element_type ~loc: psig_loc ] )
10711117 in
10721118 let new_structure =
10731119 {
0 commit comments