[ANN] Zanuda -- OCaml linter experiment

I developed a linter for my FP course in my local university. It analyzed (mostly) typed tree and performs various checks (a.k.a. lints). The list of available lints could be found here.

The discussion about a absence of litner arise from time to time
How possible is a clippy-like linter for OCaml?
and somewhere in What are the biggest reasons newcomers give up on OCaml? I’m not sure that usage of OCaml linter for non-teaching purposes is wise, but if my work will gain some traction, nobody will be able to accuse OCaml that it doesn’t have a linter.

Questions, user reports and PRs will be appreciated.

22 Likes

I’m using this linter for teaching for two years, and I’m very happy that I implemented it. Student’s code is much less annoying to read :slight_smile:

Release 1.1.0

  • #22: Add ‘reviewer’ tool to report lint’s a Github review.
  • #13: Discourage matching a tuple using ‘match’ expression with single branch
    match x with (a,b) -> ...
    
  • #18: Warn about unneeded mutually recursive types
  • #23: Implement a trial version of the Fix module for auto-correction of lints.
    It produces a diff that could be applied later. Dune support is lacking
  • Add command line switch ‘-skip-level-allow ’ to enable/disable lints
    with level=Allow. False has higher priority than per-lint command line switch
    (for example, -no-string_concat)
  • #28: Warn about too many nested if expressions.
  • #32: Warn about constructor names that hide default constructor names
  • #35: Detect manual implementations of List.map/fold functions
  • #50: Propose eta reduction when available
  • #51: Warn about pattern matching on boolean values
  • #53: Warn about "%s" in formatted strings
  • #54: Detection of unused public declarations in .mli file.
  • #56: Simplify lint about missing license. We look for required doc-comments anywhere in the file, not only in the beginning.
  • #60: Skip some checks for some source files (configured via ‘.zanuda’ config file).
  • #15: Split ‘string_concat’ lint to check separately patterns ‘a^b^c’ (level=Allow) and ‘List.fold_left (^)’ (level=Warn).
7 Likes

I’m wondering why you are singling out tuples here, instead of generalising to any and all single-branch matches?

I guess for constructors, there is a chance that a single-constructor type can grow later and you want the diff for that growth to be small? Maybe that’s the reason?

I will add this in TODO list

1 Like

Looks like a great tool. Do you know when it will possible to build it with OCaml 5.x?

Looks great. Can I use it without Dune?

I’m not sure, @adl. The issue is that I’m using first class pattern matching to match typed tree, but with 5.x changes in the typed tree unifying interface for 4.14.2 and 5.3 would be tricky.

@mobileink, At the moment, no. I use dune to parse dune describe output and get information of cmt* files for project modules. If Bazel could provide me something like this, it should be easy to integrate.

So, you use dune as a tool to get cmt* files so you can get typedtree etc? IOW you don’t directly need dune, you need the results of a build? Or rather, results of a build with -bin-annot everywhere. (I ask because I don’t know much about linters.)

Basically, Yes. There are some analysis on non typed parse tree, but it should be easier to get them