From c1ab08b61b8919d42ddec4bce710d334c33ad0e5 Mon Sep 17 00:00:00 2001 From: Thomas Gazagnaire Date: Fri, 6 Dec 2024 18:10:25 +0100 Subject: [PATCH] WIP: fix errors for skipped blocks on mli --- lib/mli_parser.ml | 74 ++++++++++++++++++++++++++++++++++++++++++----- mdx.opam | 2 +- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/lib/mli_parser.ml b/lib/mli_parser.ml index e67f0c96f..7ac7955e3 100644 --- a/lib/mli_parser.ml +++ b/lib/mli_parser.ml @@ -121,6 +121,68 @@ let docstring_code_blocks str = in loop [] |> List.rev) +(* + Should extract "Error: expected int, got string" from: + {delim@ocaml[ + let x = 1 + "a string is not an int" + ]delim[ + {@mdx-error[ + Error: expected int, got string + ]} + ]} + *) + +let output_of_line x = + match String.trim x with "..." -> `Ellipsis | _ -> `Output x + +let slice file_contents (loc : Location.t) = + let start = loc.loc_start.pos_cnum in + let len = loc.loc_end.pos_cnum - start in + String.sub file_contents start len + +let slice_error (code_block : Code_block.t) file_contents = + let starts = code_block.content.loc_end.pos_cnum in + let ends = code_block.code_block.loc_end.pos_cnum in + let len = ends - starts in + let str = String.sub file_contents starts len in + let empty = + match code_block.delimiter with + | None -> "]}" + | Some delim -> Fmt.str "]%s}" delim + in + if str = empty then [] + else + let sep = + match code_block.delimiter with + | None -> "][\n" + | Some delim -> Fmt.str "]%s[\n" delim + in + assert (String.starts_with ~prefix:sep str); + assert (String.ends_with ~suffix:"]}" str); + assert (String.length str > 2); + let str = + String.sub str (String.length sep) + (String.length str - String.length sep - 2) + in + let loc = + Location. + { + loc_start = + { + code_block.content.loc_end with + pos_cnum = starts + String.length sep; + }; + loc_end = { code_block.code_block.loc_end with pos_cnum = ends - 2 }; + loc_ghost = code_block.code_block.loc_ghost; + } + in + let location = loc.loc_start in + match extract_code_block_info [] ~location ~docstring:str with + | [ x ] -> + x.content |> slice file_contents |> String.split_on_char '\n' + |> List.map output_of_line + | _ -> assert false + (* Given code block metadata and the original file, this function splices the contents of the code block from the original text and creates an Mdx Block.t, or reports the error (e.g., from invalid tags) *) @@ -147,15 +209,13 @@ let make_block code_block file_contents = match handle_header code_block.Code_block.metadata with | Error _ as e -> e | Ok (header, labels) -> - let slice (loc : Location.t) = - let start = loc.loc_start.pos_cnum in - let len = loc.loc_end.pos_cnum - start in - String.sub file_contents start len - in let delim = code_block.delimiter in - let contents = slice code_block.content |> String.split_on_char '\n' in + let contents = + slice file_contents code_block.content |> String.split_on_char '\n' + in + let errors = slice_error code_block file_contents in Block.mk ~loc:code_block.code_block ~section:None ~labels ~header - ~contents ~legacy_labels:false ~errors:[] ~delim + ~contents ~legacy_labels:false ~errors ~delim (* Given the locations of the code blocks within [file_contents], then slice it up into [Text] and [Block] parts by using the starts and ends of those blocks as diff --git a/mdx.opam b/mdx.opam index 744279d19..833e964d8 100644 --- a/mdx.opam +++ b/mdx.opam @@ -28,7 +28,7 @@ depends: [ "logs" {>= "0.7.0"} "cmdliner" {>= "1.1.0"} "re" {>= "1.7.2"} - "ocaml-version" {>= "3.6.5"} + "ocaml-version" {>= "2.3.0"} "lwt" {with-test} "camlp-streams" "result"