@@ -85,6 +85,17 @@ let longident_of_segments = function
8585 | head :: rest ->
8686 List. fold_left (fun acc name -> Ldot (acc, name)) (Lident head) rest
8787
88+ (* [nested_modules] is the same stack as [config.nested_modules] while inside a
89+ nested [module M: { ... }]: outermost submodule name is at the tail. *)
90+ let props_longident_for_nested_module nested_modules =
91+ match List. rev nested_modules with
92+ | [] -> Lident " props"
93+ | m :: rest ->
94+ let mod_path =
95+ List. fold_left (fun acc name -> Ldot (acc, name)) (Lident m) rest
96+ in
97+ Ldot (mod_path, " props" )
98+
8899let make_hoisted_component_binding ~empty_loc ~full_module_name nested_modules =
89100 let path =
90101 nested_modules |> List. rev |> longident_of_segments |> fun txt ->
@@ -140,6 +151,44 @@ let maybe_hoist_nested_make_component ~(config : Jsx_common.jsx_config)
140151 :: config.hoisted_structure_items
141152 | _ -> ()
142153
154+ let make_hoisted_component_signature ~empty_loc ~full_module_name
155+ (component_type : Parsetree.core_type ) =
156+ let marker_name = full_module_name ^ " $jsx" in
157+ let bool_ty =
158+ Typ. constr ~loc: empty_loc {loc = empty_loc; txt = Lident " bool" } []
159+ in
160+ let full_sig =
161+ {
162+ psig_loc = empty_loc;
163+ psig_desc =
164+ Psig_value
165+ (Val. mk ~loc: empty_loc
166+ {loc = empty_loc; txt = full_module_name}
167+ component_type);
168+ }
169+ in
170+ let jsx_sig =
171+ {
172+ psig_loc = empty_loc;
173+ psig_desc =
174+ Psig_value
175+ (Val. mk ~loc: empty_loc {loc = empty_loc; txt = marker_name} bool_ty);
176+ }
177+ in
178+ (full_sig, jsx_sig)
179+
180+ let maybe_hoist_nested_make_signature ~(config : Jsx_common.jsx_config )
181+ ~empty_loc ~full_module_name ~component_type fn_name =
182+ match (fn_name, config.nested_modules, config.functor_depth) with
183+ | "make" , _ :: _ , 0 ->
184+ let full_sig, jsx_sig =
185+ make_hoisted_component_signature ~empty_loc ~full_module_name
186+ component_type
187+ in
188+ config.hoisted_signature_items < -
189+ jsx_sig :: full_sig :: config.hoisted_signature_items
190+ | _ -> ()
191+
143192(* Build a string representation of a module name with segments separated by $ *)
144193let make_module_name file_name nested_modules fn_name =
145194 let file_name = unnamespace_module_name file_name in
@@ -1101,7 +1150,8 @@ let transform_signature_item ~config item =
11011150 match item with
11021151 | {
11031152 psig_loc;
1104- psig_desc = Psig_value ({pval_attributes; pval_type} as psig_desc);
1153+ psig_desc =
1154+ Psig_value ({pval_attributes; pval_type; pval_name} as psig_desc);
11051155 } as psig -> (
11061156 match List. filter Jsx_common. has_attr pval_attributes with
11071157 | [] -> [item]
@@ -1117,15 +1167,25 @@ let transform_signature_item ~config item =
11171167 in
11181168 let prop_types = collect_prop_types [] pval_type in
11191169 let named_type_list = List. fold_left arg_to_concrete_type [] prop_types in
1170+ let props_type_args =
1171+ match core_type_of_attr with
1172+ | None -> make_props_type_params named_type_list
1173+ | Some _ -> (
1174+ match typ_vars_of_core_type with
1175+ | [] -> []
1176+ | _ -> [Typ. any () ])
1177+ in
11201178 let ret_props_type =
11211179 Typ. constr
11221180 (Location. mkloc (Lident " props" ) psig_loc)
1123- (match core_type_of_attr with
1124- | None -> make_props_type_params named_type_list
1125- | Some _ -> (
1126- match typ_vars_of_core_type with
1127- | [] -> []
1128- | _ -> [Typ. any () ]))
1181+ props_type_args
1182+ in
1183+ let ret_props_type_for_hoist =
1184+ Typ. constr
1185+ (Location. mkloc
1186+ (props_longident_for_nested_module config.nested_modules)
1187+ psig_loc)
1188+ props_type_args
11291189 in
11301190 let external_ = psig_desc.pval_prim <> [] in
11311191 let props_record_type =
@@ -1138,6 +1198,11 @@ let transform_signature_item ~config item =
11381198 ( {loc = psig_loc; txt = module_access_name config " component" },
11391199 [ret_props_type] )
11401200 in
1201+ let new_external_type_for_hoist =
1202+ Ptyp_constr
1203+ ( {loc = psig_loc; txt = module_access_name config " component" },
1204+ [ret_props_type_for_hoist] )
1205+ in
11411206 let new_structure =
11421207 {
11431208 psig with
@@ -1150,6 +1215,16 @@ let transform_signature_item ~config item =
11501215 };
11511216 }
11521217 in
1218+ let file_name = filename_from_loc psig_loc in
1219+ let empty_loc = Location. in_file file_name in
1220+ let full_module_name =
1221+ make_module_name file_name config.nested_modules pval_name.txt
1222+ in
1223+ let component_type =
1224+ {pval_type with ptyp_desc = new_external_type_for_hoist}
1225+ in
1226+ maybe_hoist_nested_make_signature ~config ~empty_loc ~full_module_name
1227+ ~component_type pval_name.txt;
11531228 [props_record_type; new_structure]
11541229 | _ ->
11551230 Jsx_common. raise_error ~loc: psig_loc
0 commit comments