From 51b1adffa9806d23dadf8d40944c7de388ee0975 Mon Sep 17 00:00:00 2001 From: Thomas Gazagnaire Date: Fri, 6 Dec 2024 18:10:25 +0100 Subject: [PATCH] fix errors for skipped blocks on mli --- lib/mli_parser.ml | 65 +++++++++++++++++-- mdx.opam | 2 +- .../mdx-test/expect/simple-mli/test-case.mli | 11 ++++ 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/lib/mli_parser.ml b/lib/mli_parser.ml index e67f0c96f..079520537 100644 --- a/lib/mli_parser.ml +++ b/lib/mli_parser.ml @@ -121,6 +121,59 @@ 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 no_errors = Fmt.str "]%a}" Fmt.(option string) code_block.delimiter in + if str = no_errors then [] + else + let sep = Fmt.str "]%a[\n" Fmt.(option string) code_block.delimiter in + assert (String.starts_with ~prefix:sep str); + assert (String.ends_with ~suffix:"]}" str); + 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 + 1; + }; + 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 +200,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" diff --git a/test/bin/mdx-test/expect/simple-mli/test-case.mli b/test/bin/mdx-test/expect/simple-mli/test-case.mli index ad197127a..826f53b94 100644 --- a/test/bin/mdx-test/expect/simple-mli/test-case.mli +++ b/test/bin/mdx-test/expect/simple-mli/test-case.mli @@ -60,3 +60,14 @@ Error: This expression has type string but an expression was expected of type int ]err}]} *) + +(** +{@ocaml skip[ + let f = 1 + "2" +][ +{err@mdx-error[ +Line 1, characters 15-18: +Error: This expression has type string but an expression was expected of type + int +]err}]} +*)