Shells, SOOCon26 and Part IIs › Ppxlib [ppxlib-merge-derivers]
Just a quick footnote about Ppxlib: I opened a PR to merge multiple instances of a deriver. I threw together this OCaml script for checking implementation and interface files. Running it on Forester, it picked up two instances which can be avoided.
open Ppxlib
let attr_compare (a1 : attribute) (a2 : attribute) =
String.compare a1.attr_name.txt a2.attr_name.txt
let has_derivings_recursively =
object
inherit [bool] Ast_traverse.fold as super
method! structure_item s acc =
match s.pstr_desc with
| Pstr_type (Recursive, (_ :: _ as tds)) ->
let attributes =
List.fold_left (fun acc td -> td.ptype_attributes @ acc) [] tds
in
let uniq = List.sort_uniq attr_compare attributes in
List.length attributes <> List.length uniq || super#structure_item s acc
| _ -> acc
method! signature_item s acc =
match s.psig_desc with
| Psig_type (Recursive, (_ :: _ as tds)) ->
let attributes =
List.fold_left (fun acc td -> td.ptype_attributes @ acc) [] tds
in
let uniq = List.sort_uniq attr_compare attributes in
List.length attributes <> List.length uniq || super#signature_item s acc
| _ -> acc
end
let main f =
let is_ml = Filename.extension f = ".ml" in
let is_mli = Filename.extension f = ".mli" in
let kind =
if is_ml then Some Ppxlib_private.Utils.Kind.Impl
else if is_mli then Some Intf
else None
in
match kind with
| None -> Format.eprintf "Skipping %s@,%!" f
| Some kind -> (
match Driver.load_input ~kind ~relocate:false ~input_name:f f with
| Error (e, _) ->
Format.eprintf "Input err %a: %s" Location.print (Location.Error.get_location e) (Location.Error.message e);
exit 127
| Ok (_, _, Impl s) ->
if has_derivings_recursively#structure s false then
Format.printf ">>> Maybe fix: %s@,%!" f
else ()
| Ok (_, _, Intf s) ->
if has_derivings_recursively#signature s false then
Format.printf ">>> Maybe fix: %s@,%!" f
else ())
Note, that given the implementation of attr_compare, this will be an overapproximation.