package dunolint

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file dunolint_lang_version.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
(*********************************************************************************)
(*  Dunolint - A tool to lint and help manage files in dune projects             *)
(*  Copyright (C) 2024-2025 Mathieu Barbin <mathieu.barbin@gmail.com>            *)
(*                                                                               *)
(*  This file is part of Dunolint.                                               *)
(*                                                                               *)
(*  Dunolint is free software; you can redistribute it and/or modify it          *)
(*  under the terms of the GNU Lesser General Public License as published by     *)
(*  the Free Software Foundation either version 3 of the License, or any later   *)
(*  version, with the LGPL-3.0 Linking Exception.                                *)
(*                                                                               *)
(*  Dunolint is distributed in the hope that it will be useful, but WITHOUT      *)
(*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or        *)
(*  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License  *)
(*  and the file `NOTICE.md` at the root of this repository for more details.    *)
(*                                                                               *)
(*  You should have received a copy of the GNU Lesser General Public License     *)
(*  and the LGPL-3.0 Linking Exception along with this library. If not, see      *)
(*  <http://www.gnu.org/licenses/> and <https://spdx.org>, respectively.         *)
(*********************************************************************************)

let field_name = "lang"

type t = { mutable dunolint_lang_version : Dunolint0.Dunolint_lang_version.t }
[@@deriving sexp_of]

let create ~dunolint_lang_version = { dunolint_lang_version }
let dunolint_lang_version t = t.dunolint_lang_version

let set_dunolint_lang_version t ~dunolint_lang_version =
  t.dunolint_lang_version <- dunolint_lang_version
;;

let read ~sexps_rewriter ~field =
  match (field : Sexp.t) with
  | List [ Atom "lang"; (Atom lang as atom_lang); (Atom version_string as atom) ] ->
    (match String.equal lang "dunolint" with
     | false ->
       Err.raise
         ~loc:(Sexps_rewriter.loc sexps_rewriter atom_lang)
         [ Pp.text "Expected (lang dunolint VERSION) format." ]
     | true ->
       (match String.split version_string ~on:'.' with
        | [ major_str; minor_str ] ->
          (match Int.of_string major_str, Int.of_string minor_str with
           | major, minor ->
             { dunolint_lang_version =
                 Dunolint0.Dunolint_lang_version.create (major, minor)
             }
           | exception _ ->
             Err.raise
               ~loc:(Sexps_rewriter.loc sexps_rewriter atom)
               [ Pp.textf "Invalid version format: %S." version_string ])
        | _ ->
          Err.raise
            ~loc:(Sexps_rewriter.loc sexps_rewriter atom)
            [ Pp.textf "Expected VERSION.MINOR format, got: %S." version_string ]))
  | _ ->
    Err.raise
      ~loc:(Sexps_rewriter.loc sexps_rewriter field)
      [ Pp.text "Expected (lang dunolint VERSION) format." ]
;;

let write t =
  let version_string =
    Dunolint0.Dunolint_lang_version.to_string t.dunolint_lang_version
  in
  Sexp.List [ Sexp.Atom "lang"; Sexp.Atom "dunolint"; Sexp.Atom version_string ]
;;

let rewrite t ~sexps_rewriter ~field =
  let new_field = write t in
  Dunolinter.Sexp_handler.replace_field ~sexps_rewriter ~field ~new_field
;;

type predicate = Dunolint0.Dunolint_lang_version.Predicate.t

let eval t ~predicate =
  (match (predicate : predicate) with
   | `eq version -> Dunolint0.Dunolint_lang_version.equal version t.dunolint_lang_version
   | `gt version ->
     Dunolint0.Dunolint_lang_version.compare t.dunolint_lang_version version > 0
   | `gte version ->
     Dunolint0.Dunolint_lang_version.compare t.dunolint_lang_version version >= 0
   | `lt version ->
     Dunolint0.Dunolint_lang_version.compare t.dunolint_lang_version version < 0
   | `lte version ->
     Dunolint0.Dunolint_lang_version.compare t.dunolint_lang_version version <= 0
   | `neq version ->
     not (Dunolint0.Dunolint_lang_version.equal version t.dunolint_lang_version))
  |> Dunolint.Trilang.const
;;

let enforce =
  Dunolinter.Linter.enforce
    (module Dunolint0.Dunolint_lang_version.Predicate)
    ~eval
    ~enforce:(fun t predicate ->
      match predicate with
      | T (`eq version) | Not (`neq version) ->
        t.dunolint_lang_version <- version;
        Ok
      | T (`gt _) | Not (`lte _) -> Eval
      | T (`gte version) | Not (`lt version) ->
        if Dunolint0.Dunolint_lang_version.compare t.dunolint_lang_version version < 0
        then t.dunolint_lang_version <- version;
        Ok
      | T (`lt _) | Not (`gte _) -> Eval
      | T (`lte version) | Not (`gt version) ->
        if Dunolint0.Dunolint_lang_version.compare t.dunolint_lang_version version > 0
        then t.dunolint_lang_version <- version;
        Ok
      | T (`neq _) | Not (`eq _) -> Eval)
;;

module Top = struct
  type nonrec t = t

  let eval = eval
  let enforce = enforce
end

module Linter = struct
  type t = Top.t
  type predicate = Dunolint0.Predicate.t

  let eval (t : t) ~predicate =
    match (predicate : Dunolint0.Predicate.t) with
    | `dunolint_lang_version condition ->
      Dunolint.Trilang.eval condition ~f:(fun predicate -> Top.eval t ~predicate)
  ;;

  let enforce =
    Dunolinter.Linter.enforce
      (module Dunolint0.Predicate)
      ~eval
      ~enforce:(fun t predicate ->
        match predicate with
        | Not _ -> Eval
        | T condition ->
          (match condition with
           | `dunolint_lang_version condition ->
             Top.enforce t ~condition;
             Ok))
  ;;
end