Skip to content

Commit 16a3a9b

Browse files
committed
Create interface file: add support for JSX V4.
1 parent a3c5538 commit 16a3a9b

File tree

6 files changed

+98
-19
lines changed

6 files changed

+98
-19
lines changed

analysis/src/CreateInterface.ml

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ let printSignature ~extractor ~signature =
164164

165165
let buf = Buffer.create 10 in
166166

167-
let getComponentType (typ : Types.type_expr) =
167+
let getComponentTypeV3 (typ : Types.type_expr) =
168168
let reactElement =
169169
Ctype.newconstr (Pdot (Pident (Ident.create "React"), "element", 0)) []
170170
in
@@ -183,6 +183,29 @@ let printSignature ~extractor ~signature =
183183
| _ -> None
184184
in
185185

186+
let getComponentTypeV4 (typ : Types.type_expr) =
187+
let reactElement =
188+
Ctype.newconstr (Pdot (Pident (Ident.create "React"), "element", 0)) []
189+
in
190+
match typ.desc with
191+
| Tarrow (_, {desc = Tconstr (Path.Pident propsId, typeArgs, _)}, retType, _)
192+
when Ident.name propsId = "props" ->
193+
Some (typeArgs, retType)
194+
| Tconstr
195+
( Pdot (Pident {name = "React"}, "component", _),
196+
[{desc = Tconstr (Path.Pident propsId, typeArgs, _)}],
197+
_ )
198+
when Ident.name propsId = "props" ->
199+
Some (typeArgs, reactElement)
200+
| Tconstr
201+
( Pdot (Pident {name = "React"}, "componentLike", _),
202+
[{desc = Tconstr (Path.Pident propsId, typeArgs, _)}; retType],
203+
_ )
204+
when Ident.name propsId = "props" ->
205+
Some (typeArgs, retType)
206+
| _ -> None
207+
in
208+
186209
let rec processSignature ~indent (signature : Types.signature) : unit =
187210
match signature with
188211
| Sig_value
@@ -193,14 +216,14 @@ let printSignature ~extractor ~signature =
193216
when Ident.name makePropsId = Ident.name makeId ^ "Props"
194217
&& ((* from implementation *) makePropsLoc.loc_ghost
195218
|| (* from interface *) makePropsLoc = makeValueDesc.val_loc)
196-
&& getComponentType makeValueDesc.val_type <> None ->
219+
&& getComponentTypeV3 makeValueDesc.val_type <> None ->
197220
(*
198221
{"name": string} => retType ~~> (~name:string) => retType
199222
React.component<{"name": string}> ~~> (~name:string) => React.element
200223
React.componentLike<{"name": string}, retType> ~~> (~name:string) => retType
201224
*)
202225
let tObj, retType =
203-
match getComponentType makeValueDesc.val_type with
226+
match getComponentTypeV3 makeValueDesc.val_type with
204227
| None -> assert false
205228
| Some (tObj, retType) -> (tObj, retType)
206229
in
@@ -213,6 +236,60 @@ let printSignature ~extractor ~signature =
213236
Buffer.add_string buf (indent ^ "@react.component\n");
214237
Buffer.add_string buf (indent ^ newItemStr ^ "\n");
215238
processSignature ~indent rest
239+
| Sig_type
240+
( propsId,
241+
{
242+
type_params;
243+
type_kind = Type_record (labelDecls, Record_optional_labels optLbls);
244+
},
245+
_ )
246+
:: Sig_value (makeId (* make *), makeValueDesc)
247+
:: rest
248+
when Ident.name propsId = "props"
249+
&& getComponentTypeV4 makeValueDesc.val_type <> None
250+
&& optLbls |> List.mem "key" ->
251+
(* PPX V4 component declaration:
252+
type props = {..., key?: _}
253+
let v = ...
254+
*)
255+
let newItemStr =
256+
let typeArgs, retType =
257+
match getComponentTypeV4 makeValueDesc.val_type with
258+
| Some x -> x
259+
| None -> assert false
260+
in
261+
let rec mkFunType (labelDecls : Types.label_declaration list) =
262+
match labelDecls with
263+
| [] -> retType
264+
| labelDecl :: rest ->
265+
let propType =
266+
CompletionBackEnd.instantiateType ~typeParams:type_params
267+
~typeArgs labelDecl.ld_type
268+
in
269+
let lblName = labelDecl.ld_id |> Ident.name in
270+
let lbl =
271+
if List.mem lblName optLbls then Asttypes.Optional lblName
272+
else Labelled lblName
273+
in
274+
if lblName = "key" then mkFunType rest
275+
else
276+
{retType with desc = Tarrow (lbl, propType, mkFunType rest, Cok)}
277+
in
278+
let funType =
279+
if List.length labelDecls = 1 (* No props: only "key "*) then
280+
let tUnit =
281+
Ctype.newconstr (Path.Pident (Ident.create "unit")) []
282+
in
283+
{retType with desc = Tarrow (Nolabel, tUnit, retType, Cok)}
284+
else mkFunType labelDecls
285+
in
286+
sigItemToString
287+
(Printtyp.tree_of_value_description makeId
288+
{makeValueDesc with val_type = funType})
289+
in
290+
Buffer.add_string buf (indent ^ "@react.component\n");
291+
Buffer.add_string buf (indent ^ newItemStr ^ "\n");
292+
processSignature ~indent rest
216293
| Sig_module (id, modDecl, recStatus) :: rest ->
217294
let colonOrEquals =
218295
match modDecl.md_type with

analysis/vendor/compiler-libs-406/includecore.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ let type_declarations ?(equality = false) ~loc env name decl1 id decl2 =
306306
let err = compare_records ~loc env decl1.type_params decl2.type_params
307307
1 labels1 labels2 in
308308
if err <> [] || rep1 = rep2 then err else
309-
[Record_representation (rep2 = Record_float)]
309+
[Record_representation (rep2 = Record_float_unused)]
310310
| (Type_open, Type_open) -> []
311311
| (_, _) -> [Kind]
312312
in

analysis/vendor/compiler-libs-406/typecore.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -780,7 +780,7 @@ module Label = NameChoice (struct
780780
let unbound_name_error = Typetexp.unbound_label_error
781781
let in_env lbl =
782782
match lbl.lbl_repres with
783-
| Record_regular | Record_float | Record_unboxed false -> true
783+
| Record_regular | Record_optional_labels _ | Record_float_unused | Record_unboxed false -> true
784784
| Record_unboxed true | Record_inlined _ | Record_extension -> false
785785
end)
786786

@@ -2015,9 +2015,9 @@ struct
20152015
| Texp_record { fields = es; extended_expression = eo;
20162016
representation = rep } ->
20172017
let use = match rep with
2018-
| Record_float -> Use.inspect
2018+
| Record_float_unused -> Use.inspect
20192019
| Record_unboxed _ -> (fun x -> x)
2020-
| Record_regular | Record_inlined _
2020+
| Record_regular | Record_optional_labels _ | Record_inlined _
20212021
| Record_extension -> Use.guard
20222022
in
20232023
let field env = function

analysis/vendor/compiler-libs-406/typedecl.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ let transl_declaration env sdecl id =
495495
let rep =
496496
if unbox then Record_unboxed false
497497
else if List.for_all (fun l -> is_float env l.Types.ld_type) lbls'
498-
then Record_float
498+
then Record_float_unused
499499
else Record_regular
500500
in
501501
Ttype_record lbls, Type_record(lbls', rep)

analysis/vendor/compiler-libs-406/types.ml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,12 @@ and type_kind =
159159
| Type_open
160160

161161
and record_representation =
162-
Record_regular (* All fields are boxed / tagged *)
163-
| Record_float (* All fields are floats *)
164-
| Record_unboxed of bool (* Unboxed single-field record, inlined or not *)
165-
| Record_inlined of int (* Inlined record *)
166-
| Record_extension (* Inlined record under extension *)
162+
| Record_regular (* All fields are boxed / tagged *)
163+
| Record_float_unused (* Was: all fields are floats. Now: unused *)
164+
| Record_unboxed of bool (* Unboxed single-field record, inlined or not *)
165+
| Record_inlined of int (* Inlined record *)
166+
| Record_extension (* Inlined record under extension *)
167+
| Record_optional_labels of string list (* List of optional labels *)
167168

168169
and label_declaration =
169170
{
@@ -346,4 +347,4 @@ type label_description =
346347
lbl_private: private_flag; (* Read-only field? *)
347348
lbl_loc: Location.t;
348349
lbl_attributes: Parsetree.attributes;
349-
}
350+
}

analysis/vendor/compiler-libs-406/types.mli

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -305,11 +305,12 @@ and type_kind =
305305
| Type_open
306306

307307
and record_representation =
308-
Record_regular (* All fields are boxed / tagged *)
309-
| Record_float (* All fields are floats *)
310-
| Record_unboxed of bool (* Unboxed single-field record, inlined or not *)
311-
| Record_inlined of int (* Inlined record *)
312-
| Record_extension (* Inlined record under extension *)
308+
| Record_regular (* All fields are boxed / tagged *)
309+
| Record_float_unused (* Was: all fields are floats. Now: unused *)
310+
| Record_unboxed of bool (* Unboxed single-field record, inlined or not *)
311+
| Record_inlined of int (* Inlined record *)
312+
| Record_extension (* Inlined record under extension *)
313+
| Record_optional_labels of string list (* List of optional labels *)
313314

314315
and label_declaration =
315316
{

0 commit comments

Comments
 (0)