Opinionated OCaml linter with Merlin integration for code quality, naming conventions, and style checks
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

monopam, merlint: migrate to ocaml-opam + ocaml-meta

Replaces the opam-file-format and findlib library dependencies with
the in-tree streaming codecs:

- opam-file-format -> opam + opam.bytesrw
- Fl_metascanner + Fl_split -> meta + meta.bytesrw

All file reads go through Bytesrw.Bytes.Reader (via
Bytesrw_eio.bytes_reader_of_flow for Eio paths, or of_in_channel for
plain channels) so the parser sees slices directly — no upfront
slurp-the-whole-file that would defeat the streaming design.

Sites touched:

- monopam/lib/opam_repo.ml: load_package, scan_opam_files_for_deps
- monopam/lib/forks.ml: scan_verse_opam_repo dev-repo lookup
- monopam/lib/lint.ml: opam_depends_of_reader, scan_opam_files,
load_meta / scan_meta_dir, check_package,
reexports_of_pkg. in_words replaces
Fl_split.in_words for value tokenization.
- merlint/lib/rules/e915.ml: read_tags uses Opam_bytesrw.field_reader
for true streaming single-field lookup.

dune-project and *.opam regenerated: drops opam-file-format, adds opam,
meta, bytesrw-eio as appropriate.

All 406 monopam tests + merlint suite pass; merlint reports 0
regressions on the migrated files.

+18 -22
+1 -1
dune-project
··· 28 28 fmt 29 29 astring 30 30 sexp 31 - opam-file-format 31 + opam 32 32 tty 33 33 vlog 34 34 (alcotest :with-test)))
+3 -1
lib/dune
··· 16 16 tty 17 17 jsont 18 18 jsont.bytesrw 19 - opam-file-format 19 + opam 20 + opam.bytesrw 21 + bytesrw 20 22 sexp)) 21 23 22 24 (rule
+13 -20
lib/rules/e915.ml
··· 15 15 16 16 let dir_exists path = try Sys.is_directory path with Sys_error _ -> false 17 17 18 - (** Extract the list of tags from an opam file using the official 19 - [opam-file-format] parser. Handles both list ([tags: ["a" "b"]]) and 20 - single-string ([tags: "a"]) forms, as well as multi-line values. 18 + (** Extract the list of tags from an opam file. Handles both list 19 + ([tags: ["a" "b"]]) and single-string ([tags: "a"]) forms. 21 20 22 21 Returns [None] if no [tags:] field is found or the file cannot be parsed. *) 23 22 let read_tags path = 24 - let open OpamParserTypes.FullPos in 25 - let string_of_value v = 26 - match v.pelem with String s -> Some s | _ -> None 27 - in 23 + let string_of_value = function Opam.Value.String s -> Some s | _ -> None in 28 24 try 29 - let file = OpamParser.FullPos.file path in 30 - let rec find = function 31 - | [] -> None 32 - | item :: rest -> ( 33 - match item.pelem with 34 - | Variable (name, value) when name.pelem = "tags" -> ( 35 - match value.pelem with 36 - | String s -> Some [ s ] 37 - | List l -> Some (List.filter_map string_of_value l.pelem) 38 - | _ -> Some []) 39 - | _ -> find rest) 40 - in 41 - find file.file_contents 25 + let ic = open_in path in 26 + Fun.protect 27 + ~finally:(fun () -> close_in ic) 28 + (fun () -> 29 + let r = Bytesrw.Bytes.Reader.of_in_channel ic in 30 + match Opam_bytesrw.field_reader ~file:path "tags" r with 31 + | None -> None 32 + | Some (Opam.Value.String s) -> Some [ s ] 33 + | Some (Opam.Value.List l) -> Some (List.filter_map string_of_value l) 34 + | Some _ -> Some []) 42 35 with _ -> None 43 36 44 37 let check_opam_file ~topics pkg_dir opam_name =
+1
merlint.opam
··· 23 23 "fmt" 24 24 "astring" 25 25 "sexp" 26 + "opam" 26 27 "tty" 27 28 "vlog" 28 29 "alcotest" {with-test}