• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Kakadu / zanuda / 54

04 Apr 2026 09:19PM UTC coverage: 82.988% (-3.2%) from 86.198%
54

push

github

Kakadu
Improve tests to be more compatible with dune >3.19

Signed-off-by: Kakadu <Kakadu@pm.me>

2161 of 2604 relevant lines covered (82.99%)

552.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.5
/src/typed/Nested_if.ml
1
[@@@ocaml.text "/*"]
2

3
(** Copyright 2021-2025, Kakadu. *)
4

5
(** SPDX-License-Identifier: LGPL-3.0-or-later *)
6

7
[@@@ocaml.text "/*"]
8

9
open Zanuda_core
10
open Zanuda_core.Utils
11

12
type input = Tast_iterator.iterator
13

14
let lint_id = "forbid_many_nested_if_expressions"
15
let level = LINT.Warn
16
let lint_source = LINT.Camelot
17

18
let documentation =
19
  {|
20
### What it does
21

22
Check too many (>= 3 levels) nested if expressions, for example
23
* `if ... then (if ... then (if ... then (if ... then ... else ...) else ...) else ...) else ...`
24

25
### Why it is important
26

27
The big problem with nested conditions is that they confuse the control flow of the code:
28
they make it almost impossible to determine what code will be executed and when.
29

30
Adopted from camelot's lint list.
31
|}
32
  |> Stdlib.String.trim
48✔
33
;;
34

35
let describe_as_json () =
36
  describe_as_clippy_json ~group:LINT.Style lint_id ~docs:documentation
1✔
37
;;
38

39
let msg ppf () =
40
  Format.fprintf
2✔
41
    ppf
42
    "Using nested if expressions more than three layers deep is a bad practice. Use let \
43
     statements or helper methods or rethinking logic.%!"
44
;;
45

46
let report filename ~loc =
47
  let module M = struct
2✔
48
    let txt ppf () = Utils.Report.txt ~filename ~loc ppf msg ()
2✔
49

50
    let rdjsonl ppf () =
51
      RDJsonl.pp
×
52
        ppf
53
        ~filename:(Config.recover_filepath loc.loc_start.pos_fname)
×
54
        ~line:loc.loc_start.pos_lnum
55
        msg
56
        ()
57
    ;;
58
  end
59
  in
60
  (module M : LINT.REPORTER)
61
;;
62

63
let run _ fallback =
64
  let pat =
60✔
65
    let open Tast_pattern in
66
    let rec nst_ite depth f =
67
      match depth with
240✔
68
      | 3 -> f
60✔
69
      | _ -> texp_ite drop f drop ||| texp_ite drop drop (some f) |> nst_ite (depth + 1)
180✔
70
    in
71
    texp_ite drop drop drop |> nst_ite 0
60✔
72
  in
73
  let open Tast_iterator in
74
  { fallback with
75
    expr =
76
      (fun self expr ->
77
        let open Typedtree in
1,607✔
78
        let loc = expr.exp_loc in
79
        Tast_pattern.parse
80
          pat
81
          loc
82
          ~on_error:(fun _desc () -> ())
1,605✔
83
          expr
84
          (fun () ->
85
            Collected_lints.add ~loc (report loc.Location.loc_start.Lexing.pos_fname ~loc))
2✔
86
          ();
87
        fallback.expr self expr)
1,607✔
88
  }
89
;;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc