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.

irmin: remove Any wrapper — step/up return cursor directly

+119
+14
docs/index.html
··· 1679 1679 </div> 1680 1680 <div class="error-hint"><p>Python deps must live in a venv. Never use pip install --break-system-packages. The generate.sh wrapper should create/reuse a venv automatically.</p></div> 1681 1681 </div> 1682 + <div class="error-card" id="E900"> 1683 + <div> 1684 + <span class="error-code">E900</span> 1685 + <span class="error-title">Wire.Codec without c/ directory</span> 1686 + </div> 1687 + <div class="error-hint"><p>Add a c/ directory with gen.ml that calls Wire_3d.main to generate .3d files and C validators from the Wire codec definitions. See ocaml-clcw/c/ for the pattern.</p></div> 1688 + </div> 1689 + <div class="error-card" id="E905"> 1690 + <div> 1691 + <span class="error-code">E905</span> 1692 + <span class="error-title">Wire struct_/module_ in public API</span> 1693 + </div> 1694 + <div class="error-hint"><p>Move struct_, module_, c_stubs, ml_stubs out of the .mli. These belong in c/gen.ml where they are used to generate EverParse 3D files and C stubs. The codec is the public API; the 3D projection is a build artifact.</p></div> 1695 + </div> 1682 1696 1683 1697 <a href="#top" class="back-to-top">↑ Top</a> 1684 1698 </body>
+2
lib/data.ml
··· 70 70 E825.rule; 71 71 E830.rule; 72 72 E835.rule; 73 + E900.rule; 74 + E905.rule; 73 75 ]
+2
lib/rule.ml
··· 9 9 | Project_structure 10 10 | Testing 11 11 | Interop_testing 12 + | Code_generation 12 13 13 14 type example = { is_good : bool; code : string } 14 15 ··· 47 48 | Project_structure -> "Project Structure" 48 49 | Testing -> "Test Quality" 49 50 | Interop_testing -> "Interop Testing" 51 + | Code_generation -> "Code Generation" 50 52 51 53 let is_file_scoped (T desc) = 52 54 match desc.check with File _ -> true | Project _ -> false
+1
lib/rule.mli
··· 10 10 | Project_structure 11 11 | Testing 12 12 | Interop_testing 13 + | Code_generation 13 14 14 15 type example = { 15 16 is_good : bool; (** true for good examples, false for bad examples. *)
+55
lib/rules/e900.ml
··· 1 + (** E900: Wire.Codec without c/ directory *) 2 + 3 + type payload = { package : string } 4 + 5 + let check (ctx : Context.project) = 6 + let desc = Context.dune_describe ctx in 7 + let libs = Dune.libraries desc in 8 + let issues = ref [] in 9 + List.iter 10 + (fun (lib : Dune.library_info) -> 11 + let has_wire = 12 + List.exists 13 + (fun f -> 14 + Fpath.has_ext ".ml" f 15 + && 16 + try 17 + let content = 18 + In_channel.with_open_text (Fpath.to_string f) 19 + In_channel.input_all 20 + in 21 + Astring.String.is_infix ~affix:"Wire.Codec" content 22 + || Astring.String.is_infix ~affix:"Wire.Field" content 23 + with _ -> false) 24 + lib.files 25 + in 26 + if has_wire then 27 + let lib_dir = 28 + match lib.files with f :: _ -> Fpath.parent f | [] -> Fpath.v "." 29 + in 30 + let pkg_dir = 31 + if Fpath.basename lib_dir = "lib" then Fpath.parent lib_dir 32 + else lib_dir 33 + in 34 + let c_dir = Fpath.(pkg_dir / "c") in 35 + if 36 + not 37 + (Sys.file_exists (Fpath.to_string c_dir) 38 + && Sys.is_directory (Fpath.to_string c_dir)) 39 + then issues := Issue.v { package = Fpath.to_string pkg_dir } :: !issues) 40 + libs; 41 + !issues 42 + 43 + let pp ppf { package } = 44 + Fmt.pf ppf 45 + "%s uses Wire.Codec but has no c/ directory for EverParse 3D generation" 46 + package 47 + 48 + let rule = 49 + Rule.v ~code:"E900" ~title:"Wire.Codec without c/ directory" 50 + ~category:Code_generation 51 + ~hint: 52 + "Add a c/ directory with gen.ml that calls Wire_3d.main to generate .3d \ 53 + files and C validators from the Wire codec definitions. See \ 54 + ocaml-clcw/c/ for the pattern." 55 + ~examples:[] ~pp (Project check)
+45
lib/rules/e905.ml
··· 1 + (** E905: Wire struct_/module_ exposed in public API *) 2 + 3 + type payload = { file : string; symbol : string } 4 + 5 + let wire_symbols = [ "struct_"; "module_"; "c_stubs"; "ml_stubs" ] 6 + 7 + let check (ctx : Context.project) = 8 + let desc = Context.dune_describe ctx in 9 + let libs = Dune.libraries desc in 10 + let issues = ref [] in 11 + List.iter 12 + (fun (lib : Dune.library_info) -> 13 + List.iter 14 + (fun f -> 15 + if Fpath.has_ext ".mli" f then 16 + try 17 + let content = 18 + In_channel.with_open_text (Fpath.to_string f) 19 + In_channel.input_all 20 + in 21 + List.iter 22 + (fun sym -> 23 + let pattern = "val " ^ sym in 24 + if Astring.String.is_infix ~affix:pattern content then 25 + issues := 26 + Issue.v { file = Fpath.to_string f; symbol = sym } 27 + :: !issues) 28 + wire_symbols 29 + with _ -> ()) 30 + lib.files) 31 + libs; 32 + !issues 33 + 34 + let pp ppf { file; symbol } = 35 + Fmt.pf ppf "%s exposes Wire EverParse symbol `%s` in public API" file symbol 36 + 37 + let rule = 38 + Rule.v ~code:"E905" ~title:"Wire struct_/module_ in public API" 39 + ~category:Code_generation 40 + ~hint: 41 + "Move struct_, module_, c_stubs, ml_stubs out of the .mli. These belong \ 42 + in c/gen.ml where they are used to generate EverParse 3D files and C \ 43 + stubs. The codec is the public API; the 3D projection is a build \ 44 + artifact." 45 + ~examples:[] ~pp (Project check)