Skip to content

Commit 3f28e6e

Browse files
authored
fix(graindoc): Avoid singletons when building ordered comments (#1208)
1 parent db1fa4e commit 3f28e6e

File tree

3 files changed

+70
-38
lines changed

3 files changed

+70
-38
lines changed

compiler/graindoc/docblock.re

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,13 @@ let string_of_type_expr = out_type => {
105105
Option.map(to_string, out_type);
106106
};
107107

108-
let for_value_description = (~ident: Ident.t, vd: Types.value_description) => {
108+
let for_value_description =
109+
(~comments, ~ident: Ident.t, vd: Types.value_description) => {
109110
let module_name = module_name_of_location(vd.val_loc);
110111
let name = title_for_api(~module_name, ident);
111112
let type_sig = string_of_value_description(~ident, vd);
112113
let comment =
113-
Comments.Doc.ending_on_lnum(vd.val_loc.loc_start.pos_lnum - 1);
114+
Comments.Doc.ending_on(~lnum=vd.val_loc.loc_start.pos_lnum - 1, comments);
114115

115116
let (description, attributes) =
116117
switch (comment) {
@@ -137,12 +138,16 @@ let for_value_description = (~ident: Ident.t, vd: Types.value_description) => {
137138
{module_name, name, type_sig, description, attributes};
138139
};
139140

140-
let for_type_declaration = (~ident: Ident.t, td: Types.type_declaration) => {
141+
let for_type_declaration =
142+
(~comments, ~ident: Ident.t, td: Types.type_declaration) => {
141143
let module_name = module_name_of_location(td.type_loc);
142144
let name = title_for_api(~module_name, ident);
143145
let type_sig = string_of_type_declaration(~ident, td);
144146
let comment =
145-
Comments.Doc.ending_on_lnum(td.type_loc.loc_start.pos_lnum - 1);
147+
Comments.Doc.ending_on(
148+
~lnum=td.type_loc.loc_start.pos_lnum - 1,
149+
comments,
150+
);
146151

147152
let (description, attributes) =
148153
switch (comment) {
@@ -153,15 +158,16 @@ let for_type_declaration = (~ident: Ident.t, td: Types.type_declaration) => {
153158
{module_name, name, type_sig, description, attributes};
154159
};
155160

156-
let for_signature_item = (~env: Env.t, sig_item: Types.signature_item) => {
161+
let for_signature_item =
162+
(~env: Env.t, ~comments, sig_item: Types.signature_item) => {
157163
switch (sig_item) {
158164
| TSigValue(ident, vd) =>
159165
let vd = Env.find_value(vd.val_fullpath, env);
160-
let docblock = for_value_description(~ident, vd);
166+
let docblock = for_value_description(~comments, ~ident, vd);
161167
Some(docblock);
162168
| TSigType(ident, td, _rec) =>
163169
let td = Env.find_type(td.type_path, env);
164-
let docblock = for_type_declaration(~ident, td);
170+
let docblock = for_type_declaration(~comments, ~ident, td);
165171
Some(docblock);
166172
| _ => None
167173
};

compiler/graindoc/graindoc.re

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,13 @@ let compile_typed = (opts: params) => {
101101

102102
let generate_docs =
103103
({current_version, output}: params, program: Typedtree.typed_program) => {
104-
Comments.setup_comments(program.comments);
104+
let comments = Comments.to_ordered(program.comments);
105105

106106
let env = program.env;
107107
let signature_items = program.signature.cmi_sign;
108108

109109
let buf = Buffer.create(0);
110-
let module_comment = Comments.Doc.find_module();
110+
let module_comment = Comments.Doc.find_module(comments);
111111
switch (module_comment) {
112112
| Some((_, desc, attrs)) =>
113113
// TODO: Should we fail if more than one `@module` attribute?
@@ -181,7 +181,7 @@ let generate_docs =
181181
};
182182

183183
let add_docblock = sig_item => {
184-
let docblock = Docblock.for_signature_item(~env, sig_item);
184+
let docblock = Docblock.for_signature_item(~env, ~comments, sig_item);
185185
switch (docblock) {
186186
| Some(docblock) =>
187187
Buffer.add_buffer(
@@ -192,7 +192,7 @@ let generate_docs =
192192
};
193193
};
194194

195-
let section_comments = Comments.Doc.find_sections();
195+
let section_comments = Comments.Doc.find_sections(comments);
196196
if (List.length(section_comments) == 0) {
197197
List.iter(add_docblock, signature_items);
198198
} else {

compiler/src/diagnostics/comments.re

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -280,18 +280,35 @@ module Attribute = {
280280
type description = option(string);
281281
type attributes = list(Attribute.t);
282282

283-
module IntMap = Map.Make(Int);
283+
module type OrderedComments = {
284+
type comment = (Typedtree.comment, description, attributes);
284285

285-
type comments = {
286-
mutable by_start_lnum:
287-
IntMap.t((Typedtree.comment, description, attributes)),
288-
mutable by_end_lnum:
289-
IntMap.t((Typedtree.comment, description, attributes)),
286+
type comments;
287+
288+
let comments: comments;
289+
290+
let find_starting_on_lnum: int => option(comment);
291+
let find_ending_on_lnum: int => option(comment);
292+
293+
let iter: ((int, comment) => unit) => unit;
290294
};
291295

292-
let comments = {by_start_lnum: IntMap.empty, by_end_lnum: IntMap.empty};
296+
module MakeOrderedComments =
297+
(Raw: {let comments: list(Typedtree.comment);})
298+
: OrderedComments => {
299+
module IntMap = Map.Make(Int);
300+
301+
type comment = (Typedtree.comment, description, attributes);
302+
303+
type comments = {
304+
mutable by_start_lnum:
305+
IntMap.t((Typedtree.comment, description, attributes)),
306+
mutable by_end_lnum:
307+
IntMap.t((Typedtree.comment, description, attributes)),
308+
};
309+
310+
let comments = {by_start_lnum: IntMap.empty, by_end_lnum: IntMap.empty};
293311

294-
let setup_comments = (raw_comments: list(Typedtree.comment)) => {
295312
List.iter(
296313
(comment: Typedtree.comment) => {
297314
let (start_lnum, end_lnum, data) =
@@ -310,10 +327,23 @@ let setup_comments = (raw_comments: list(Typedtree.comment)) => {
310327
IntMap.add(start_lnum, data, comments.by_start_lnum);
311328
comments.by_end_lnum = IntMap.add(end_lnum, data, comments.by_end_lnum);
312329
},
313-
raw_comments,
330+
Raw.comments,
314331
);
332+
333+
let find_starting_on_lnum = lnum =>
334+
IntMap.find_opt(lnum, comments.by_start_lnum);
335+
let find_ending_on_lnum = lnum =>
336+
IntMap.find_opt(lnum, comments.by_end_lnum);
337+
338+
let iter = fn => IntMap.iter(fn, comments.by_start_lnum);
315339
};
316340

341+
let to_ordered = (comments): (module OrderedComments) =>
342+
(module
343+
MakeOrderedComments({
344+
let comments = comments;
345+
}));
346+
317347
let start_line = (comment: Typedtree.comment) => {
318348
switch (comment) {
319349
| Line({cmt_loc})
@@ -333,17 +363,17 @@ let end_line = (comment: Typedtree.comment) => {
333363
};
334364

335365
module Doc = {
336-
let starting_on_lnum = lnum => {
337-
let data = IntMap.find_opt(lnum, comments.by_start_lnum);
366+
let starting_on = (~lnum, module C: OrderedComments) => {
367+
let data = C.find_starting_on_lnum(lnum);
338368
switch (data) {
339369
| Some((Doc({cmt_content}), _, _)) => data
340370
| _ => None
341371
};
342372
};
343373

344-
let ending_on_lnum = lnum => {
374+
let ending_on = (~lnum, module C: OrderedComments) => {
345375
let rec ending_on_lnum_help = (lnum, check_prev) => {
346-
let data = IntMap.find_opt(lnum, comments.by_end_lnum);
376+
let data = C.find_ending_on_lnum(lnum);
347377
switch (data) {
348378
| Some((Doc({cmt_content}), _, _)) => data
349379
// Hack to handle code that has an attribute on the line before, such as `@disableGC`
@@ -354,14 +384,12 @@ module Doc = {
354384
ending_on_lnum_help(lnum, true);
355385
};
356386

357-
let find_module = () => {
387+
let find_module = (module C: OrderedComments) => {
358388
let module_comments = ref([]);
359-
IntMap.iter(
360-
(_, (_comment, _desc, attrs) as comment) =>
361-
if (List.exists(Attribute.is_module, attrs)) {
362-
module_comments := [comment, ...module_comments^];
363-
},
364-
comments.by_start_lnum,
389+
C.iter((_, (_comment, _desc, attrs) as comment) =>
390+
if (List.exists(Attribute.is_module, attrs)) {
391+
module_comments := [comment, ...module_comments^];
392+
}
365393
);
366394
if (List.length(module_comments^) > 1) {
367395
failwith("More than one @module block is not supported");
@@ -370,14 +398,12 @@ module Doc = {
370398
};
371399
};
372400

373-
let find_sections = () => {
401+
let find_sections = (module C: OrderedComments) => {
374402
let section_comments = ref([]);
375-
IntMap.iter(
376-
(_, (_comment, _desc, attrs) as comment) =>
377-
if (List.exists(Attribute.is_section, attrs)) {
378-
section_comments := [comment, ...section_comments^];
379-
},
380-
comments.by_start_lnum,
403+
C.iter((_, (_comment, _desc, attrs) as comment) =>
404+
if (List.exists(Attribute.is_section, attrs)) {
405+
section_comments := [comment, ...section_comments^];
406+
}
381407
);
382408
List.rev(section_comments^);
383409
};

0 commit comments

Comments
 (0)