Revision 9d08a76fb50773e0b6b1afad31f37dfb821fee75 authored by Benjamin Gregoire on 24 November 2022, 16:10:02 UTC, committed by Benjamin Gregoire on 24 November 2022, 16:10:02 UTC
1 parent 69c9c2e
Raw File
ppx_lint.ml
(* -------------------------------------------------------------------- *)
open Ast_mapper
open Parsetree

(* -------------------------------------------------------------------- *)
type error =
| CatchAllInTryWith
| CatchAllInMatch

exception Error of Location.t * error

(* -------------------------------------------------------------------- *)
let string_of_error = function
  | CatchAllInTryWith -> "catch all in try...with..."
  | CatchAllInMatch   -> "catch all in match...with"

(* -------------------------------------------------------------------- *)
let error_of_exn = function
  | Error (loc, error) ->
      Some (Location.error ~loc (string_of_error error))
  | _ -> None

(* -------------------------------------------------------------------- *)
let () = Location.register_error_of_exn error_of_exn

(* -------------------------------------------------------------------- *)
let rec is_wild_pattern (p : pattern) =
  match p.ppat_desc with
  | Ppat_any   -> true
  | Ppat_var _ -> true

  | Ppat_alias (p, _) ->
      is_wild_pattern p

  | Ppat_or (p1, p2) ->
      is_wild_pattern p1 || is_wild_pattern p2

  | Ppat_constraint (p, _) ->
      is_wild_pattern p

  | Ppat_extension ({ Asttypes.txt = "catchall" }, _) ->
      false

  | Ppat_extension (_, PPat (p, _)) ->
     is_wild_pattern p

  | _ -> false

(* -------------------------------------------------------------------- *)
let is_wild_case (c : case) =
  is_wild_pattern c.pc_lhs

(* -------------------------------------------------------------------- *)
let rec catchall_mapper =
  { default_mapper with
      expr = fun mapper expr ->
        match expr.pexp_desc with
        | Pexp_try (e, clauses) ->
            if List.exists is_wild_case clauses then
              Format.eprintf "Lint: %a %s\n%!"
                Location.print_loc expr.pexp_loc
                (string_of_error CatchAllInTryWith);
          let e = catchall_mapper.expr mapper e in
          let clauses = catchall_mapper.cases mapper clauses in
          { expr with pexp_desc = Pexp_try (e, clauses) }
        | _ -> default_mapper.expr mapper expr }

(* -------------------------------------------------------------------- *)
let () = register "catchall" (fun _ -> catchall_mapper)
back to top