Skip to content

Commit 3b1014e

Browse files
authored
Add additional signature information to doc json (#1043)
* Add signature to details * Include Tsubst and Tpoly * Update processing of Tpoly
1 parent f173347 commit 3b1014e

9 files changed

+300
-2
lines changed

tools/bin/main.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Usage: rescript-tools [command]
1414

1515
Commands:
1616

17-
doc Generate documentation
17+
doc <file> Generate documentation
1818
reanalyze Reanalyze
1919
-v, --version Print version
2020
-h, --help Print help|}

tools/npm/Tools_Docgen.res

+13
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,21 @@ type constructor = {
1717
payload?: constructorPayload,
1818
}
1919

20+
type rec typeInSignature = {
21+
path: string,
22+
genericTypeParameters: array<typeInSignature>,
23+
}
24+
25+
type signatureDetais = {
26+
parameters: array<typeInSignature>,
27+
returnType: typeInSignature,
28+
}
29+
2030
@tag("kind")
2131
type detail =
2232
| @as("record") Record({items: array<field>})
2333
| @as("variant") Variant({items: array<constructor>})
34+
| @as("alias") Signature(signatureDetais)
2435

2536
type source = {
2637
filepath: string,
@@ -38,6 +49,8 @@ type rec item =
3849
name: string,
3950
deprecated?: string,
4051
source: source,
52+
/** Additional documentation of signature, if available. */
53+
detail?: detail,
4154
})
4255
| @as("type")
4356
Type({

tools/npm/Tools_Docgen.resi

+14
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,22 @@ type constructor = {
1616
deprecated?: string,
1717
payload?: constructorPayload,
1818
}
19+
20+
type rec typeInSignature = {
21+
path: string,
22+
genericTypeParameters: array<typeInSignature>,
23+
}
24+
25+
type signatureDetais = {
26+
parameters: array<typeInSignature>,
27+
returnType: typeInSignature,
28+
}
29+
1930
@tag("kind")
2031
type detail =
2132
| @as("record") Record({items: array<field>})
2233
| @as("variant") Variant({items: array<constructor>})
34+
| @as("signature") Signature(signatureDetais)
2335

2436
type source = {
2537
filepath: string,
@@ -37,6 +49,8 @@ type rec item =
3749
name: string,
3850
deprecated?: string,
3951
source: source,
52+
/** Additional documentation of signature, if available. */
53+
detail?: detail,
4054
})
4155
| @as("type")
4256
Type({

tools/src/tools.ml

+98-1
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ type constructorDoc = {
1818
items: constructorPayload option;
1919
}
2020

21+
type typeDoc = {path: string; genericParameters: typeDoc list}
22+
type valueSignature = {parameters: typeDoc list; returnType: typeDoc}
23+
2124
type source = {filepath: string; line: int; col: int}
2225

2326
type docItemDetail =
2427
| Record of {fieldDocs: fieldDoc list}
2528
| Variant of {constructorDocs: constructorDoc list}
29+
| Signature of valueSignature
2630

2731
type docItem =
2832
| Value of {
@@ -31,6 +35,7 @@ type docItem =
3135
signature: string;
3236
name: string;
3337
deprecated: string option;
38+
detail: docItemDetail option;
3439
source: source;
3540
}
3641
| Type of {
@@ -104,6 +109,19 @@ let stringifyConstructorPayload ~indentation
104109
|> array) );
105110
]
106111

112+
let rec stringifyTypeDoc ~indentation (td : typeDoc) : string =
113+
let open Protocol in
114+
let ps =
115+
match td.genericParameters with
116+
| [] -> None
117+
| ts ->
118+
ts |> List.map (stringifyTypeDoc ~indentation:(indentation + 1))
119+
|> fun ts -> Some (array ts)
120+
in
121+
122+
stringifyObject ~indentation:(indentation + 1)
123+
[("path", Some (wrapInQuotes td.path)); ("genericTypeParameters", ps)]
124+
107125
let stringifyDetail ?(indentation = 0) (detail : docItemDetail) =
108126
let open Protocol in
109127
match detail with
@@ -147,6 +165,25 @@ let stringifyDetail ?(indentation = 0) (detail : docItemDetail) =
147165
])
148166
|> array) );
149167
]
168+
| Signature {parameters; returnType} ->
169+
let ps =
170+
match parameters with
171+
| [] -> None
172+
| ps ->
173+
ps |> List.map (stringifyTypeDoc ~indentation:(indentation + 1))
174+
|> fun ps -> Some (array ps)
175+
in
176+
stringifyObject ~startOnNewline:true ~indentation
177+
[
178+
("kind", Some (wrapInQuotes "signature"));
179+
( "items",
180+
Some
181+
(stringifyObject ~startOnNewline:false ~indentation
182+
[
183+
("parameters", ps);
184+
("returnType", Some (stringifyTypeDoc ~indentation returnType));
185+
]) );
186+
]
150187

151188
let stringifySource ~indentation source =
152189
let open Protocol in
@@ -160,7 +197,7 @@ let stringifySource ~indentation source =
160197
let rec stringifyDocItem ?(indentation = 0) ~originalEnv (item : docItem) =
161198
let open Protocol in
162199
match item with
163-
| Value {id; docstring; signature; name; deprecated; source} ->
200+
| Value {id; docstring; signature; name; deprecated; source; detail} ->
164201
stringifyObject ~startOnNewline:true ~indentation
165202
[
166203
("id", Some (wrapInQuotes id));
@@ -173,6 +210,11 @@ let rec stringifyDocItem ?(indentation = 0) ~originalEnv (item : docItem) =
173210
("signature", Some (signature |> String.trim |> wrapInQuotes));
174211
("docstrings", Some (stringifyDocstrings docstring));
175212
("source", Some (stringifySource ~indentation:(indentation + 1) source));
213+
( "detail",
214+
match detail with
215+
| None -> None
216+
| Some detail ->
217+
Some (stringifyDetail ~indentation:(indentation + 1) detail) );
176218
]
177219
| Type {id; docstring; signature; name; deprecated; detail; source} ->
178220
stringifyObject ~startOnNewline:true ~indentation
@@ -310,6 +352,60 @@ let typeDetail typ ~env ~full =
310352
})
311353
| _ -> None
312354

355+
(* split a list into two parts all the items except the last one and the last item *)
356+
let splitLast l =
357+
let rec splitLast' acc = function
358+
| [] -> failwith "splitLast: empty list"
359+
| [x] -> (List.rev acc, x)
360+
| x :: xs -> splitLast' (x :: acc) xs
361+
in
362+
splitLast' [] l
363+
364+
let path_to_string path =
365+
let buf = Buffer.create 64 in
366+
let rec aux = function
367+
| Path.Pident id -> Buffer.add_string buf (Ident.name id)
368+
| Path.Pdot (p, s, _) ->
369+
aux p;
370+
Buffer.add_char buf '.';
371+
Buffer.add_string buf s
372+
| Path.Papply (p1, p2) ->
373+
aux p1;
374+
Buffer.add_char buf '(';
375+
aux p2;
376+
Buffer.add_char buf ')'
377+
in
378+
aux path;
379+
Buffer.contents buf
380+
381+
let valueDetail (typ : Types.type_expr) =
382+
let rec collectSignatureTypes (typ_desc : Types.type_desc) =
383+
match typ_desc with
384+
| Tlink t | Tsubst t | Tpoly (t, []) -> collectSignatureTypes t.desc
385+
| Tconstr (Path.Pident {name = "function$"}, [t; _], _) ->
386+
collectSignatureTypes t.desc
387+
| Tconstr (path, ts, _) -> (
388+
let p = path_to_string path in
389+
match ts with
390+
| [] -> [{path = p; genericParameters = []}]
391+
| ts ->
392+
let ts =
393+
ts
394+
|> List.concat_map (fun (t : Types.type_expr) ->
395+
collectSignatureTypes t.desc)
396+
in
397+
[{path = p; genericParameters = ts}])
398+
| Tarrow (_, t1, t2, _) ->
399+
collectSignatureTypes t1.desc @ collectSignatureTypes t2.desc
400+
| Tvar None -> [{path = "_"; genericParameters = []}]
401+
| _ -> []
402+
in
403+
match collectSignatureTypes typ.desc with
404+
| [] -> None
405+
| ts ->
406+
let parameters, returnType = splitLast ts in
407+
Some (Signature {parameters; returnType})
408+
313409
let makeId modulePath ~identifier =
314410
identifier :: modulePath |> List.rev |> SharedTypes.ident
315411

@@ -398,6 +494,7 @@ let extractDocs ~entryPointFile ~debug =
398494
^ Shared.typeToString typ;
399495
name = item.name;
400496
deprecated = item.deprecated;
497+
detail = valueDetail typ;
401498
source;
402499
})
403500
| Type (typ, _) ->

tools/tests/src/expected/DocExtraction2.res.json

+24
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@
3030
"filepath": "src/DocExtraction2.resi",
3131
"line": 7,
3232
"col": 1
33+
},
34+
"detail":
35+
{
36+
"kind": "signature",
37+
"items": {
38+
"parameters": [{
39+
"path": "unit"
40+
}],
41+
"returnType": {
42+
"path": "t"
43+
}
44+
}
3345
}
3446
},
3547
{
@@ -65,6 +77,18 @@
6577
"filepath": "src/DocExtraction2.resi",
6678
"line": 15,
6779
"col": 3
80+
},
81+
"detail":
82+
{
83+
"kind": "signature",
84+
"items": {
85+
"parameters": [{
86+
"path": "unit"
87+
}],
88+
"returnType": {
89+
"path": "t"
90+
}
91+
}
6892
}
6993
}]
7094
}]

tools/tests/src/expected/DocExtraction2.resi.json

+24
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@
3030
"filepath": "src/DocExtraction2.resi",
3131
"line": 7,
3232
"col": 1
33+
},
34+
"detail":
35+
{
36+
"kind": "signature",
37+
"items": {
38+
"parameters": [{
39+
"path": "unit"
40+
}],
41+
"returnType": {
42+
"path": "t"
43+
}
44+
}
3345
}
3446
},
3547
{
@@ -65,6 +77,18 @@
6577
"filepath": "src/DocExtraction2.resi",
6678
"line": 15,
6779
"col": 3
80+
},
81+
"detail":
82+
{
83+
"kind": "signature",
84+
"items": {
85+
"parameters": [{
86+
"path": "unit"
87+
}],
88+
"returnType": {
89+
"path": "t"
90+
}
91+
}
6892
}
6993
}]
7094
}]

0 commit comments

Comments
 (0)