Skip to content

Commit

Permalink
Fix source quotation in driver errors with OCaml 5.2
Browse files Browse the repository at this point in the history
The compiler removed some logic that was reopening the source
file based on `Location.input_name` and instead only rely on
`Location.input_lexbuf` for source quotation.

This PR changes the way we read source files to stick to what
the compiler does in `Pparse` while preserving our features
such read from stdin. We now set the input_lexbuf properly.

Signed-off-by: Nathan Rebours <[email protected]>
  • Loading branch information
NathanReb committed Mar 4, 2024
1 parent 14932c3 commit 379f004
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 15 deletions.
1 change: 1 addition & 0 deletions astlib/location.ml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
include Ocaml_common.Location

let set_input_name name = input_name := name
let set_input_lexbuf lexbuf_opt = input_lexbuf := lexbuf_opt

module Error = struct
[@@@warning "-37"]
Expand Down
3 changes: 3 additions & 0 deletions astlib/location.mli
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ with type location := t
val set_input_name : string -> unit
(** Set the name of the input source, e.g. the file name. *)

val set_input_lexbuf : Lexing.lexbuf option -> unit
(** Set the name of the input source, e.g. the file name. *)

val none : t
(** An arbitrary value of type [t]; describes an empty ghost range. *)

Expand Down
28 changes: 13 additions & 15 deletions src/utils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,19 @@ module Ast_io = struct
let input_version = (module Compiler_version : OCaml_version) in
try
(* To test if a file is an AST file, we have to read the first few bytes of the
file. If it is not, we have to parse these bytes and the rest of the file as
source code.
The compiler just does [seek_on 0] in this case, however this doesn't work when
the input is a pipe.
What we do instead is create a lexing buffer from the input channel and pre-fill
it with what we read to do the test. *)
let lexbuf = Lexing.from_channel ic in
let len = String.length prefix_read_from_source in
Bytes.blit_string ~src:prefix_read_from_source ~src_pos:0
~dst:lexbuf.lex_buffer ~dst_pos:0 ~len;
lexbuf.lex_buffer_len <- len;
lexbuf.lex_curr_p <-
{ pos_fname = input_name; pos_lnum = 1; pos_bol = 0; pos_cnum = 0 };
file. If it is not, we have to parse these bytes and the rest of the file as
source code.
The compiler just does [seek_on 0] in this case, however this doesn't work
when the input is a pipe.
What we do is we build a string of the whole source, append the prefix
and built a lexing buffer from that.
We have to put all the source into the lexing buffer at once this way
for source quotation to work in error messages.
See ocaml#12238 and ocaml/driver/pparse.ml. *)
let all_source = prefix_read_from_source ^ In_channel.input_all ic in
let lexbuf = Lexing.from_string all_source in
lexbuf.lex_curr_p <- { lexbuf.lex_curr_p with pos_fname = input_name };
Astlib.Location.set_input_lexbuf (Some lexbuf);
Skip_hash_bang.skip_hash_bang lexbuf;
let ast : Intf_or_impl.t =
match kind with
Expand Down

0 comments on commit 379f004

Please sign in to comment.