Skip to content

Commit

Permalink
Add Location.is_none and fix loc_of_attributes
Browse files Browse the repository at this point in the history
Location.is_none provides a means to check whether a given location is
none for all supported compiler versions (as the none location changed).
We then use this is loc_of_attributes to correctly pick-up none-located,
compiler attributes like documentation comments.

Signed-off-by: Patrick Ferris <[email protected]>
  • Loading branch information
patricoferris committed Dec 8, 2024
1 parent 562a9fa commit 139d7e1
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ let loc_of_attribute { attr_name; attr_payload; attr_loc = _ } =
from older asts. *)
(* "ocaml.doc" attributes are generated with [Location.none], which is not helpful for
error messages. *)
if Poly.( = ) attr_name.loc Location.none then
if Location.is_none attr_name.loc then
loc_of_name_and_payload attr_name attr_payload
else
{
Expand All @@ -157,7 +157,7 @@ let loc_of_attribute { attr_name; attr_payload; attr_loc = _ } =
}

let loc_of_extension (name, payload) =
if Poly.( = ) name.loc Location.none then loc_of_name_and_payload name payload
if Location.is_none name.loc then loc_of_name_and_payload name payload
else
{ name.loc with loc_end = (loc_of_name_and_payload name payload).loc_end }

Expand Down
8 changes: 8 additions & 0 deletions src/location.ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ let set_filename loc fn =

let none = in_file "_none_"

let none_4_08_0_plus =
let loc =
{ pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0; pos_cnum = -1 }
in
{ loc_start = loc; loc_end = loc; loc_ghost = true }

let is_none v = Poly.( = ) v none || Poly.( = ) v none_4_08_0_plus

let init lexbuf fname =
let open Lexing in
lexbuf.lex_curr_p <-
Expand Down
6 changes: 6 additions & 0 deletions src/location.mli
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ val set_filename : t -> string -> t
val none : t
(** An arbitrary value of type [t]; describes an empty ghost range. *)

val is_none : t -> bool
(** Checks whether a given location is equal to [none].
Note that this function returns [true] for none locations from all supported
compiler versions. *)

val init : Lexing.lexbuf -> string -> unit
(** Set the file name and line number of the [lexbuf] to be the start of the
named file. *)
Expand Down
7 changes: 7 additions & 0 deletions test/location/attributes/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(executable
(name pp)
(libraries ppxlib))

(cram
(applies_to print_attr_loc)
(deps pp.exe))
18 changes: 18 additions & 0 deletions test/location/attributes/pp.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
open Ppxlib

let pp_attr str =
let iter =
object
inherit Ast_traverse.iter as super

method! attribute v =
let loc = loc_of_attribute v in
Format.printf "%a %s" Location.print loc v.attr_name.txt;
super#attribute v
end
in
iter#structure str;
str

let () = Driver.register_transformation ~impl:pp_attr "print-attributes"
let () = Ppxlib.Driver.standalone ()
15 changes: 15 additions & 0 deletions test/location/attributes/print_attr_loc.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
The compiler inserts documentation comments with their location set to
`Location.none`. The value for `Location.none` has changed in the compiler (at
4.08.0). We provide a function, `loc_of_attribute` to handle deriving better location
errors for attributes with a none location.

$ cat > test.ml << EOF
> let v = 1
> (** A documentation comment! *)
> EOF

We run an identity driver that prints the locations of attributes.

$ ./pp.exe --impl test.ml -o ignore.ml
File "test.ml", line 2, characters 0-31: ocaml.doc

0 comments on commit 139d7e1

Please sign in to comment.