Skip to content
This repository was archived by the owner on Jun 15, 2023. It is now read-only.

Commit 08029af

Browse files
committed
Add support for module comments.
Module comments are of the form: ```/*** stuff */``` or internally ```@@ns.doc(" stuff ")```
1 parent 44e0221 commit 08029af

File tree

11 files changed

+78
-12
lines changed

11 files changed

+78
-12
lines changed

src/res_comment.ml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
type style = SingleLine | MultiLine | DocComment
1+
type style = SingleLine | MultiLine | DocComment | ModuleComment
22

33
let styleToString s =
44
match s with
55
| SingleLine -> "SingleLine"
66
| MultiLine -> "MultiLine"
77
| DocComment -> "DocComment"
8+
| ModuleComment -> "ModuleComment"
89

910
type t = {
1011
txt: string;
@@ -23,6 +24,8 @@ let isSingleLineComment t = t.style = SingleLine
2324

2425
let isDocComment t = t.style = DocComment
2526

27+
let isModuleComment t = t.style = ModuleComment
28+
2629
let toString t =
2730
let {Location.loc_start; loc_end} = t.loc in
2831
Format.sprintf "(txt: %s\nstyle: %s\nlocation: %d,%d-%d,%d)" t.txt
@@ -34,11 +37,13 @@ let toString t =
3437
let makeSingleLineComment ~loc txt =
3538
{txt; loc; style = SingleLine; prevTokEndPos = Lexing.dummy_pos}
3639

37-
let makeMultiLineComment ~loc ~docComment txt =
40+
let makeMultiLineComment ~loc ~docComment ~standalone txt =
3841
{
3942
txt;
4043
loc;
41-
style = (if docComment then DocComment else MultiLine);
44+
style =
45+
(if docComment then if standalone then ModuleComment else DocComment
46+
else MultiLine);
4247
prevTokEndPos = Lexing.dummy_pos;
4348
}
4449

src/res_comment.mli

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ val setPrevTokEndPos : t -> Lexing.position -> unit
1010

1111
val isDocComment : t -> bool
1212

13+
val isModuleComment : t -> bool
14+
1315
val isSingleLineComment : t -> bool
1416

1517
val makeSingleLineComment : loc:Location.t -> string -> t
16-
val makeMultiLineComment : loc:Location.t -> docComment:bool -> string -> t
18+
val makeMultiLineComment :
19+
loc:Location.t -> docComment:bool -> standalone:bool -> string -> t
1720
val fromOcamlComment :
1821
loc:Location.t -> txt:string -> prevTokEndPos:Lexing.position -> t
1922
val trimSpaces : string -> string

src/res_core.ml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5364,6 +5364,16 @@ and parseStructureItemRegion p =
53645364
let loc = mkLoc startPos p.prevEndPos in
53655365
Parser.endRegion p;
53665366
Some {structureItem with pstr_loc = loc}
5367+
| ModuleComment (loc, s) ->
5368+
Parser.next p;
5369+
Some
5370+
(Ast_helper.Str.attribute ~loc
5371+
( {txt = "ns.doc"; loc},
5372+
PStr
5373+
[
5374+
Ast_helper.Str.eval ~loc
5375+
(Ast_helper.Exp.constant ~loc (Pconst_string (s, None)));
5376+
] ))
53675377
| AtAt ->
53685378
let attr = parseStandaloneAttribute p in
53695379
parseNewlineOrSemicolonStructure p;
@@ -6088,6 +6098,16 @@ and parseSignatureItemRegion p =
60886098
parseNewlineOrSemicolonSignature p;
60896099
let loc = mkLoc startPos p.prevEndPos in
60906100
Some (Ast_helper.Sig.attribute ~loc attr)
6101+
| ModuleComment (loc, s) ->
6102+
Parser.next p;
6103+
Some
6104+
(Ast_helper.Sig.attribute ~loc
6105+
( {txt = "ns.doc"; loc},
6106+
PStr
6107+
[
6108+
Ast_helper.Str.eval ~loc
6109+
(Ast_helper.Exp.constant ~loc (Pconst_string (s, None)));
6110+
] ))
60916111
| PercentPercent ->
60926112
let extension = parseExtension ~moduleLanguage:true p in
60936113
parseNewlineOrSemicolonSignature p;
@@ -6318,6 +6338,7 @@ and parseAttributes p =
63186338
*)
63196339
and parseStandaloneAttribute p =
63206340
let startPos = p.startPos in
6341+
(* XX *)
63216342
Parser.expect AtAt p;
63226343
let attrId = parseAttributeId ~startPos p in
63236344
let payload = parsePayload p in

src/res_parser.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ let docCommentToAttributeToken comment =
5454
let loc = Comment.loc comment in
5555
Token.DocComment (loc, txt)
5656

57+
let moduleCommentToAttributeToken comment =
58+
let txt = Comment.txt comment in
59+
let loc = Comment.loc comment in
60+
Token.ModuleComment (loc, txt)
61+
5762
(* Advance to the next non-comment token and store any encountered comment
5863
* in the parser's state. Every comment contains the end position of its
5964
* previous token to facilite comment interleaving *)
@@ -72,6 +77,11 @@ let rec next ?prevEndPos p =
7277
p.prevEndPos <- prevEndPos;
7378
p.startPos <- startPos;
7479
p.endPos <- endPos)
80+
else if Comment.isModuleComment c then (
81+
p.token <- moduleCommentToAttributeToken c;
82+
p.prevEndPos <- prevEndPos;
83+
p.startPos <- startPos;
84+
p.endPos <- endPos)
7585
else (
7686
Comment.setPrevTokEndPos c p.endPos;
7787
p.comments <- c :: p.comments;

src/res_printer.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5096,7 +5096,12 @@ and printAttribute ?(standalone = false) ~customLayout
50965096
Pstr_eval ({pexp_desc = Pexp_constant (Pconst_string (txt, _))}, _);
50975097
};
50985098
] ) ->
5099-
Doc.concat [Doc.text "/**"; Doc.text txt; Doc.text "*/"]
5099+
Doc.concat
5100+
[
5101+
Doc.text (if standalone then "/***" else "/**");
5102+
Doc.text txt;
5103+
Doc.text "*/";
5104+
]
51005105
| _ ->
51015106
Doc.group
51025107
(Doc.concat

src/res_scanner.ml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -546,12 +546,11 @@ let scanSingleLineComment scanner =
546546

547547
let scanMultiLineComment scanner =
548548
(* assumption: we're only ever using this helper in `scan` after detecting a comment *)
549-
let docComment =
550-
peek2 scanner = '*'
551-
&& peek3 scanner <> '/'
552-
(* no /**/ *) && peek3 scanner <> '*' (* no /*** *)
549+
let docComment = peek2 scanner = '*' && peek3 scanner <> '/' (* no /**/ *) in
550+
let standalone = docComment && peek3 scanner = '*' (* /*** *) in
551+
let contentStartOff =
552+
scanner.offset + if docComment then if standalone then 4 else 3 else 2
553553
in
554-
let contentStartOff = scanner.offset + if docComment then 3 else 2 in
555554
let startPos = position scanner in
556555
let rec scan ~depth =
557556
(* invariant: depth > 0 right after this match. See assumption *)
@@ -573,7 +572,7 @@ let scanMultiLineComment scanner =
573572
let length = scanner.offset - 2 - contentStartOff in
574573
let length = if length < 0 (* in case of EOF *) then 0 else length in
575574
Token.Comment
576-
(Comment.makeMultiLineComment ~docComment
575+
(Comment.makeMultiLineComment ~docComment ~standalone
577576
~loc:
578577
Location.
579578
{loc_start = startPos; loc_end = position scanner; loc_ghost = false}

src/res_token.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ type t =
9696
| Import
9797
| Export
9898
| DocComment of Location.t * string
99+
| ModuleComment of Location.t * string
99100

100101
let precedence = function
101102
| HashEqual | ColonEqual -> 1
@@ -207,6 +208,7 @@ let toString = function
207208
| Import -> "import"
208209
| Export -> "export"
209210
| DocComment (_loc, s) -> "DocComment " ^ s
211+
| ModuleComment (_loc, s) -> "ModuleComment " ^ s
210212

211213
let keywordTable = function
212214
| "and" -> And

tests/parsing/other/docComments.res

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1+
/*** This is a module comment */
2+
3+
/*** This is another module comment */
4+
15
/** This is a doc ✅ comment */
26
let z = 34
37

8+
@@ns.doc("And this is a ns.doc module annotation")
9+
410
@ns.doc("And this is a ns.doc ✅ annotation")
511
let q = 11
612

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
[@@@ns.doc " This is a module comment "]
2+
[@@@ns.doc " This is another module comment "]
13
let z = 34[@@ns.doc " This is a doc \226\156\133 comment "]
4+
[@@@ns.doc {js|And this is a ns.doc module annotation|js}]
25
let q = 11[@@ns.doc {js|And this is a ns.doc ✅ annotation|js}]
36
type nonrec h = int[@@ns.doc
47
" This\n * is a multi-line\n multiline doc comment\n "]
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1+
/*** This is a module comment */
2+
3+
/*** This is another module comment */
4+
15
/** This is a doc ✅ comment */
26
let z = 34
37

8+
@@ns.doc("And this is a ns.doc module annotation")
9+
410
@ns.doc("And this is a ns.doc ✅ annotation")
511
let q = 11
612

713
/** This
814
* is a multi-line
915
multiline doc comment
1016
*/
11-
type h = int
17+
type h = int

tests/printer/comments/expected/docComments.res.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1+
/*** This is a module comment */
2+
3+
/*** This is another module comment */
4+
15
/** This is a doc ✅ comment */
26
let z = 34
37

8+
/***And this is a ns.doc module annotation*/
9+
410
/**And this is a ns.doc ✅ annotation*/
511
let q = 11
612

0 commit comments

Comments
 (0)