Skip to content

Commit 934b0cb

Browse files
An-Tucristianoc
andauthored
Fix interface generation if @inline is present (#473)
* Fix interface generation if @inline is present * Improve interface generation if @inline is present * Simplify attributes extraction * Intarface generation if @inline is present. Fixes after review. * tiny simplification * use match Co-authored-by: Cristiano Calcagno <[email protected]>
1 parent 6628c8d commit 934b0cb

File tree

3 files changed

+112
-4
lines changed

3 files changed

+112
-4
lines changed

analysis/src/CreateInterface.ml

Lines changed: 89 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,73 @@ module SourceFileExtractor = struct
3131
!res)
3232
end
3333

34+
module AttributesUtils : sig
35+
type t
36+
37+
val make : string list -> t
38+
39+
val contains : string -> t -> bool
40+
41+
val toString : t -> string
42+
end = struct
43+
type attribute = {line: int; offset: int; name: string}
44+
type t = attribute list
45+
type parseState = Search | Collect of int
46+
47+
let make lines =
48+
let makeAttr lineIdx attrOffsetStart attrOffsetEnd line =
49+
{
50+
line = lineIdx;
51+
offset = attrOffsetStart;
52+
name = String.sub line attrOffsetStart (attrOffsetEnd - attrOffsetStart);
53+
}
54+
in
55+
let res = ref [] in
56+
lines
57+
|> List.iteri (fun lineIdx line ->
58+
let state = ref Search in
59+
for i = 0 to String.length line - 1 do
60+
let ch = line.[i] in
61+
match (!state, ch) with
62+
| Search, '@' -> state := Collect i
63+
| Collect attrOffset, ' ' ->
64+
res := makeAttr lineIdx attrOffset i line :: !res;
65+
state := Search
66+
| Search, _ | Collect _, _ -> ()
67+
done;
68+
69+
match !state with
70+
| Collect attrOffset ->
71+
res :=
72+
makeAttr lineIdx attrOffset (String.length line) line :: !res
73+
| _ -> ());
74+
!res |> List.rev
75+
76+
let contains attributeForSearch t =
77+
t |> List.exists (fun {name} -> name = attributeForSearch)
78+
79+
let toString t =
80+
match t with
81+
| [] -> ""
82+
| {line} :: _ ->
83+
let prevLine = ref line in
84+
let buffer = ref "" in
85+
let res = ref [] in
86+
t
87+
|> List.iter (fun attr ->
88+
let {line; offset; name} = attr in
89+
90+
if line <> !prevLine then (
91+
res := !buffer :: !res;
92+
buffer := "";
93+
prevLine := line);
94+
95+
let indent = String.make (offset - String.length !buffer) ' ' in
96+
buffer := !buffer ^ indent ^ name);
97+
res := !buffer :: !res;
98+
!res |> List.rev |> String.concat "\n"
99+
end
100+
34101
let printSignature ~extractor ~signature =
35102
let objectPropsToFun objTyp ~rhs ~makePropsType =
36103
let propsTbl = Hashtbl.create 1 in
@@ -84,6 +151,17 @@ let printSignature ~extractor ~signature =
84151
|> Res_doc.toString ~width:!Res_cli.ResClflags.width
85152
in
86153

154+
let genSigStrForInlineAttr lines attributes id vd =
155+
let divider = if List.length lines > 1 then "\n" else " " in
156+
157+
let sigStr =
158+
sigItemToString
159+
(Printtyp.tree_of_value_description id {vd with val_kind = Val_reg})
160+
in
161+
162+
(attributes |> AttributesUtils.toString) ^ divider ^ sigStr ^ "\n"
163+
in
164+
87165
let buf = Buffer.create 10 in
88166

89167
let getComponentType (typ : Types.type_expr) =
@@ -162,15 +240,22 @@ let printSignature ~extractor ~signature =
162240
Buffer.add_string buf "\n"
163241
in
164242
processSignature ~indent rest
165-
| Sig_value (_id, {val_kind = Val_prim prim; val_loc}) :: items
243+
| Sig_value (id, ({val_kind = Val_prim prim; val_loc} as vd)) :: items
166244
when prim.prim_native_name <> "" && prim.prim_native_name.[0] = '\132' ->
167-
(* Rescript primitive name, e.g. @val external ...
168-
Copy the external declaration verbatim from the implementation file *)
245+
(* Rescript primitive name, e.g. @val external ... *)
169246
let lines =
170247
let posStart, posEnd = Loc.range val_loc in
171248
extractor |> SourceFileExtractor.extract ~posStart ~posEnd
172249
in
173-
Buffer.add_string buf ((lines |> String.concat "\n") ^ "\n");
250+
let attributes = AttributesUtils.make lines in
251+
252+
if AttributesUtils.contains "@inline" attributes then
253+
(* Generate type signature for @inline declaration *)
254+
Buffer.add_string buf (genSigStrForInlineAttr lines attributes id vd)
255+
else
256+
(* Copy the external declaration verbatim from the implementation file *)
257+
Buffer.add_string buf ((lines |> String.concat "\n") ^ "\n");
258+
174259
processSignature ~indent items
175260
| Sig_value (id, vd) :: items ->
176261
let newItemStr =

analysis/tests/src/CreateInterface.res

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,20 @@ external padLeft: (
3535
],
3636
) => string = "padLeft"
3737

38+
@inline
39+
let f1 = 10
40+
41+
@inline let f2 = "some string"
42+
43+
@genType
44+
@inline
45+
let f3 = 10
46+
47+
@genType @inline
48+
let f4 = "some string"
49+
50+
@genType @inline let f5 = 5.5
51+
3852
module RFS = {
3953
@module("fs")
4054
external readFileSync: (

analysis/tests/src/expected/CreateInterface.res.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ external padLeft: (
2525
| #Int(int)
2626
],
2727
) => string = "padLeft"
28+
@inline
29+
let f1: int
30+
@inline let f2: string
31+
@genType
32+
@inline
33+
let f3: int
34+
@genType @inline
35+
let f4: string
36+
@genType @inline let f5: float
2837
module RFS: {
2938
@module("fs")
3039
external readFileSync: (

0 commit comments

Comments
 (0)