Skip to content

Commit 3226c6e

Browse files
authored
Merge pull request #439 from gpetiot/odoc.2.3.0
Upgrade mdx to use last version of odoc-parser
2 parents 526248a + abf4a61 commit 3226c6e

File tree

20 files changed

+1044
-125
lines changed

20 files changed

+1044
-125
lines changed

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
### unreleased
2+
3+
#### Added
4+
5+
- Handle the error-blocks syntax (#439, @jonludlam, @gpetiot)
6+
17
### 2.3.1
28

39
#### Added

lib/block.ml

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ type t = {
114114
os_type_enabled : bool;
115115
set_variables : (string * string) list;
116116
unset_variables : string list;
117+
delim : string option;
117118
value : value;
118119
}
119120

@@ -160,19 +161,61 @@ let rec error_padding = function
160161
let xs = error_padding xs in
161162
x :: xs
162163

163-
let pp_errors ppf t =
164+
let compute_delimiter ~base_delim outputs =
165+
let s =
166+
Format.asprintf "%a" (Format.pp_print_list (Output.pp ~pad:0)) outputs
167+
in
168+
let is_inadequate delim =
169+
Astring.String.is_infix ~affix:("]" ^ delim ^ "}") s
170+
in
171+
let rec loop n =
172+
let delim =
173+
match n with 0 -> base_delim | n -> Format.sprintf "%s_%d" base_delim n
174+
in
175+
if is_inadequate delim then loop (n + 1) else delim
176+
in
177+
loop 0
178+
179+
let pp_error ?syntax ?delim ppf outputs =
180+
match syntax with
181+
| Some Syntax.Markdown ->
182+
Fmt.pf ppf "```\n```mdx-error\n%a\n"
183+
Fmt.(list ~sep:(any "\n") Output.pp)
184+
outputs
185+
| Some Syntax.Mli | Some Syntax.Mld ->
186+
let err_delim = compute_delimiter ~base_delim:"err" outputs in
187+
Fmt.pf ppf "]%a[\n{%s@mdx-error[\n%a\n]%s}"
188+
Fmt.(option string)
189+
delim err_delim
190+
Fmt.(list ~sep:(any "\n") Output.pp)
191+
outputs err_delim
192+
| _ -> ()
193+
194+
let has_output t =
195+
match t.value with
196+
| OCaml { errors = []; _ } -> false
197+
| OCaml { errors = _; _ } -> true
198+
| _ -> false
199+
200+
let pp_value ?syntax ppf t =
201+
let delim = t.delim in
164202
match t.value with
165203
| OCaml { errors = []; _ } -> ()
166204
| OCaml { errors; _ } ->
167205
let errors = error_padding errors in
168-
Fmt.pf ppf "```mdx-error\n%a\n```\n"
169-
Fmt.(list ~sep:(any "\n") Output.pp)
170-
errors
206+
pp_error ?syntax ?delim ppf errors
171207
| _ -> ()
172208

173-
let pp_footer ?syntax ppf _ =
209+
let pp_footer ?syntax ppf t =
210+
let delim =
211+
if has_output t then (
212+
pp_value ?syntax ppf t;
213+
None)
214+
else t.delim
215+
in
174216
match syntax with
175-
| Some Syntax.Mli | Some Syntax.Mld -> Fmt.string ppf "]}"
217+
| Some Syntax.Mli | Some Syntax.Mld ->
218+
Fmt.pf ppf "]%a}" Fmt.(option string) delim
176219
| Some Syntax.Cram -> Fmt.string ppf "\n"
177220
| Some Syntax.Markdown | None -> Fmt.string ppf "```\n"
178221

@@ -216,7 +259,9 @@ let pp_header ?syntax ppf t =
216259
| [] -> ()
217260
| labels -> Fmt.pf ppf " %a" (pp_labels ?syntax) labels
218261
in
219-
Fmt.pf ppf "{%a%a[" pp_lang_header lang_headers pp_labels other_labels
262+
Fmt.pf ppf "{%a%a%a["
263+
Fmt.(option string)
264+
t.delim pp_lang_header lang_headers pp_labels other_labels
220265
| Some Syntax.Cram -> pp_labels ?syntax ppf t.labels
221266
| Some Syntax.Markdown | None ->
222267
if t.legacy_labels then
@@ -231,8 +276,7 @@ let pp_header ?syntax ppf t =
231276
let pp ?syntax ppf b =
232277
pp_header ?syntax ppf b;
233278
pp_contents ?syntax ppf b;
234-
pp_footer ?syntax ppf b;
235-
pp_errors ppf b
279+
pp_footer ?syntax ppf b
236280

237281
let directory t = t.dir
238282
let file t = match t.value with Include t -> Some t.file_included | _ -> None
@@ -415,7 +459,7 @@ let infer_block ~loc ~config ~header ~contents ~errors =
415459
let+ () = check_no_errors ~loc errors in
416460
Raw { header })
417461

418-
let mk ~loc ~section ~labels ~legacy_labels ~header ~contents ~errors =
462+
let mk ~loc ~section ~labels ~legacy_labels ~header ~delim ~contents ~errors =
419463
let block_kind =
420464
get_label (function Block_kind x -> Some x | _ -> None) labels
421465
in
@@ -442,6 +486,7 @@ let mk ~loc ~section ~labels ~legacy_labels ~header ~contents ~errors =
442486
os_type_enabled;
443487
set_variables = config.set_variables;
444488
unset_variables = config.unset_variables;
489+
delim;
445490
value;
446491
}
447492

@@ -450,7 +495,7 @@ let mk_include ~loc ~section ~labels =
450495
| Some file_inc ->
451496
let header = Header.infer_from_file file_inc in
452497
mk ~loc ~section ~labels ~legacy_labels:false ~header ~contents:[]
453-
~errors:[]
498+
~errors:[] ~delim:None
454499
| None -> label_required ~loc ~label:"file" ~kind:"include"
455500

456501
let parse_labels ~label_cmt ~legacy_labels =
@@ -476,6 +521,7 @@ let from_raw raw =
476521
in
477522
Util.Result.to_error_list
478523
@@ mk ~loc ~section ~header ~contents ~labels ~legacy_labels ~errors
524+
~delim:None
479525

480526
let is_active ?section:s t =
481527
let active =

lib/block.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ type t = {
105105
(** Whether the current os type complies with the block's version. *)
106106
set_variables : (string * string) list;
107107
unset_variables : string list;
108+
delim : string option;
108109
value : value;
109110
}
110111
(** The type for supported code blocks. *)
@@ -115,6 +116,7 @@ val mk :
115116
labels:Label.t list ->
116117
legacy_labels:bool ->
117118
header:Header.t option ->
119+
delim:string option ->
118120
contents:string list ->
119121
errors:Output.t list ->
120122
(t, [ `Msg of string ]) result

lib/mli_parser.ml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module Code_block = struct
33

44
type t = {
55
metadata : metadata option;
6+
delimiter : string option;
67
content : Location.t; (* Location of the content *)
78
code_block : Location.t; (* Location of the enclosing code block *)
89
}
@@ -44,18 +45,19 @@ let extract_code_block_info acc ~(location : Lexing.position) ~docstring =
4445
loc_ghost = false;
4546
}
4647
in
47-
fun location (metadata, { O.Loc.location = span; _ }) ->
48+
fun location
49+
{ O.Ast.meta; delimiter; content = { O.Loc.location = span; _ }; _ } ->
4850
let metadata =
4951
Option.map
50-
(fun (lang, labels) ->
51-
let language_tag = O.Loc.value lang in
52-
let labels = Option.map O.Loc.value labels in
52+
(fun { O.Ast.language; tags } ->
53+
let language_tag = O.Loc.value language in
54+
let labels = Option.map O.Loc.value tags in
5355
Code_block.{ language_tag; labels })
54-
metadata
56+
meta
5557
in
5658
let content = convert_loc span in
5759
let code_block = convert_loc location in
58-
{ metadata; content; code_block }
60+
{ metadata; delimiter; content; code_block }
5961
in
6062

6163
(* Fold over the results from odoc-parser, recurse where necessary
@@ -146,9 +148,10 @@ let make_block code_block file_contents =
146148
let len = loc.loc_end.pos_cnum - start in
147149
String.sub file_contents start len
148150
in
151+
let delim = code_block.delimiter in
149152
let contents = slice code_block.content |> String.split_on_char '\n' in
150153
Block.mk ~loc:code_block.code_block ~section:None ~labels ~header
151-
~contents ~legacy_labels:false ~errors:[]
154+
~contents ~legacy_labels:false ~errors:[] ~delim
152155
153156
(* Given the locations of the code blocks within [file_contents], then slice it up into
154157
[Text] and [Block] parts by using the starts and ends of those blocks as

test/bin/mdx-test/expect/simple-mld/test-case.mld

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,11 @@ Indentation test:
5959
val x : int = 1
6060
]}
6161

62-
62+
{delim@ocaml[
63+
let f = 1 + "2"
64+
]delim[
65+
{err@mdx-error[
66+
Line 1, characters 15-18:
67+
Error: This expression has type string but an expression was expected of type
68+
int
69+
]err}]}

test/bin/mdx-test/expect/simple-mli/test-case.mli

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,14 @@ val bar : string
4949

5050
(** {@ocaml skip[1 + 1 = 3]} *)
5151
val baz : string
52+
53+
(**
54+
{[
55+
let f = 1 + "2"
56+
][
57+
{err@mdx-error[
58+
Line 1, characters 15-18:
59+
Error: This expression has type string but an expression was expected of type
60+
int
61+
]err}]}
62+
*)

test/lib/test_block.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ let test_mk =
2323
let test_fun () =
2424
let actual =
2525
Mdx.Block.mk ~loc:Location.none ~section:None ~labels
26-
~legacy_labels:false ~header ~contents ~errors:[]
26+
~legacy_labels:false ~header ~contents ~errors:[] ~delim:None
2727
in
2828
let expected =
2929
Result.map_error

test/lib/test_dep.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ let test_of_block =
2626
| Ok labels -> (
2727
match
2828
Mdx.Block.mk ~loc:Location.none ~section:None ~labels ~header:None
29-
~contents:[] ~legacy_labels:false ~errors:[]
29+
~contents:[] ~legacy_labels:false ~errors:[] ~delim:None
3030
with
3131
| Ok block -> block
3232
| Error _ -> assert false)

0 commit comments

Comments
 (0)