Skip to content

Commit 433152a

Browse files
authored
Merge pull request #174 from mbarbin/libraries.mem-predicate
Libraries.mem predicate
2 parents be5a622 + c49b5d3 commit 433152a

33 files changed

+810
-91
lines changed

doc/docs/reference/config/dune.md

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,21 @@ Stanza:
8989

9090
It is almost identical to its *name* sibling, thus we are not documenting it in details here. A notable difference is that the suggestions for the `(is_prefix my-package.)` predicate is improved when the prefix is a package name, as *dunolint* will indeed suggests to *replace* an existing package prefix if one if present. This is a minor ergonomic detail.
9191

92+
### libraries
93+
94+
`(dune (executable (libraries _)))` is a selector for the *libraries* field of an *executable* stanza:
95+
96+
Stanza:
97+
```dune
98+
(executable
99+
(libraries <FRAGMENT>))
100+
```
101+
102+
It is identical to the [library (libraries)](#libraries) selector. See that section for details on predicates and examples.
103+
92104
### Fields shared with other stanzas
93105

94-
This stanza share some sub selectors with other stanzas. See: *has_field*, *instrumentation*, *lint*, *preprocess*.
106+
This stanza share some sub selectors with other stanzas. See: *has_field*, *instrumentation*, *libraries*, *lint*, *preprocess*.
95107

96108
For example, you can use the `(dune (executable (instrumentation _)))` syntax if you want the *instrumentation* selector to apply to the *executable* stanza only.
97109

@@ -446,12 +458,66 @@ Condition: `(enforce (dune (library PREDICATE)))`
446458
| (package (is_prefix prefix_)) | Enforcement failure |
447459
| (package (is_suffix _suffix)) | Enforcement failure |
448460

461+
### libraries
462+
463+
`(dune (library (libraries _)))` is a selector for the *libraries* field of a *library* stanza:
464+
465+
Stanza:
466+
```dune
467+
(library
468+
(libraries <FRAGMENT>))
469+
```
470+
471+
The predicates of the `libraries` selector are:
472+
473+
1. `(mem LIBRARY_NAMES)`
474+
475+
Returns *true* iff all the library names specified are present in the list of dependencies found in the fragment.
476+
477+
**Semantics**: The predicate `(mem a b c)` is best understood as the sequential application of individual membership checks: `(mem a) ; (mem b) ; (mem c)`, where `;` denotes conjunction (AND). Each library name is checked independently, and all must be present for the predicate to return *true*.
478+
479+
When enforced, *dunolint* suggests adding the library name(s) not already present. New libraries are added to the last section (when sections are delimited by comments) and sorted alphabetically within that section.
480+
481+
**Negation**: The negation `(not (mem a b c))` distributes as conjunction over the individual checks: `(not (mem a)) ; (not (mem b)) ; (not (mem c))`. This means "ensure none of the specified libraries are present" (all must be absent), not "ensure at least one is absent". When enforced, *dunolint* suggests removing all the supplied library name(s) from the fragment when present.
482+
483+
**Empty arguments**: Enforcing `(mem)` or `(not (mem))` with no arguments has no effect.
484+
485+
**Examples:**
486+
487+
Stanza:
488+
```dune
489+
(library
490+
(name mylib)
491+
(libraries base core))
492+
```
493+
494+
Condition: `(dune (library (libraries PREDICATE)))`
495+
496+
| Predicate | Result |
497+
| --------- | ------ |
498+
| (mem base core) | True |
499+
| (mem base) | True |
500+
| (mem async) | False. Suggestion: add *async*, keep existing values |
501+
| (not (mem core)) | False. Suggestion: remove *core* |
502+
449503
### Fields shared with other stanzas
450504

451-
This stanza shares some sub selectors with other stanzas. See: *instrumentation*, *lint*, *preprocess*.
505+
This stanza shares some sub selectors with other stanzas. See: *instrumentation*, *libraries*, *lint*, *preprocess*.
452506

453507
For example, you can use the `(dune (library (instrumentation _)))` syntax if you want the *instrumentation* selector to apply to the *library* stanza only.
454508

509+
## libraries
510+
511+
`(dune (libraries _))` is a selector for the *libraries* field found in stanzas *library* and *executable*.
512+
513+
Stanza:
514+
```dune
515+
(library
516+
(libraries <FRAGMENT>))
517+
```
518+
519+
Its predicates are documented in the [library (libraries)](#libraries) section above.
520+
455521
## lint
456522

457523
`(dune (lint _))` is a selector for the *lint* field found in stanzas *library*, *executable* and *executables*.

dunolint

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@
77

88
(rule (enforce (dune_workspace (dune_lang_version (>= 3.20)))))
99

10+
(rule
11+
(cond
12+
((path
13+
(or (glob src/dunolint/stdlib/**) (glob src/dunolint/vendor/**)
14+
(glob src/dunolint-lib/**) (glob src/dunolint-lib-base/**)
15+
(glob test/dunolint-lib-base/**)))
16+
return)
17+
(true (enforce (dune (library (libraries (mem dunolint_stdlib))))))))
18+
1019
(rule
1120
(cond ((path (glob test/**/src/*)) return)
1221
((path (glob test/**))

dunolint-config/src/config.ml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,25 @@ let () =
4848
(dune_lang_version (gte (Dune_workspace.Dune_lang_version.create (3, 20))))))
4949
;;
5050

51+
let () =
52+
rule
53+
(cond
54+
[ ( path
55+
(or_
56+
[ glob "src/dunolint/stdlib/**"
57+
; glob "src/dunolint/vendor/**"
58+
; glob "src/dunolint-lib/**"
59+
; glob "src/dunolint-lib-base/**"
60+
; glob "test/dunolint-lib-base/**"
61+
])
62+
, return )
63+
; ( true_
64+
, enforce
65+
(dune (library (libraries (mem [ Dune.Library.Name.v "dunolint_stdlib" ]))))
66+
)
67+
])
68+
;;
69+
5170
let () =
5271
rule
5372
(cond

dunolint-config/src/dune

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,12 @@
88
-warn-error
99
+a
1010
-open
11-
Base
12-
-open
13-
Stdio
11+
Dunolint_stdlib
1412
-open
1513
Cmdlang)
16-
(libraries base cmdlang dunolint stdio)
14+
(libraries cmdlang dunolint dunolint_stdlib)
1715
(instrumentation
1816
(backend bisect_ppx))
1917
(lint
2018
(pps ppx_js_style -allow-let-operators -check-doc-comments))
21-
(preprocess
22-
(pps
23-
-unused-code-warnings=force
24-
ppx_compare
25-
ppx_enumerate
26-
ppx_hash
27-
ppx_here
28-
ppx_let
29-
ppx_sexp_conv
30-
ppx_sexp_value)))
19+
(preprocess no_preprocessing))

dunolint-config/test/dune

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,18 @@
22
(name dunolint_dunolint_config_test)
33
(package dunolint-tests)
44
(inline_tests)
5-
(flags :standard -w +a-4-40-41-42-44-45-48-66 -warn-error +a)
6-
(libraries dunolint_dunolint_config)
5+
(flags
6+
:standard
7+
-w
8+
+a-4-40-41-42-44-45-48-66
9+
-warn-error
10+
+a
11+
-open
12+
Dunolint_stdlib)
13+
(libraries dunolint_dunolint_config dunolint_stdlib)
714
(instrumentation
815
(backend bisect_ppx))
916
(lint
1017
(pps ppx_js_style -allow-let-operators -check-doc-comments))
1118
(preprocess
12-
(pps
13-
-unused-code-warnings=force
14-
ppx_compare
15-
ppx_enumerate
16-
ppx_expect
17-
ppx_hash
18-
ppx_here
19-
ppx_let
20-
ppx_sexp_conv
21-
ppx_sexp_value)))
19+
(pps ppx_expect)))

src/dunolint-lib-base/dune.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module Compilation_mode = Dune0.Compilation_mode
2323
module Executable = Dune0.Executable
2424
module Include_subdirs = Dunolint.Dune.Include_subdirs
2525
module Instrumentation = Dune0.Instrumentation
26+
module Libraries = Dunolint.Dune.Libraries
2627
module Library = Dune0.Library
2728
module Lint = Dunolint.Dune.Lint
2829
module Package = Dune0.Package

src/dunolint-lib-base/dune.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module Compilation_mode = Dune0.Compilation_mode
2323
module Executable = Dune0.Executable
2424
module Include_subdirs = Dunolint.Dune.Include_subdirs
2525
module Instrumentation = Dune0.Instrumentation
26+
module Libraries = Dunolint.Dune.Libraries
2627
module Library = Dune0.Library
2728
module Lint = Dunolint.Dune.Lint
2829
module Package = Dune0.Package

src/dunolint-lib/dunolint/dune.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module Compilation_mode = Dune0.Compilation_mode
2323
module Executable = Dune0.Executable
2424
module Include_subdirs = Dune0.Include_subdirs
2525
module Instrumentation = Dune0.Instrumentation
26+
module Libraries = Dune0.Libraries
2627
module Library = Dune0.Library
2728
module Lint = Dune0.Lint
2829
module Package = Dune0.Package

src/dunolint-lib/dunolint/dune.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module Compilation_mode = Dune0.Compilation_mode
2323
module Executable = Dune0.Executable
2424
module Include_subdirs = Dune0.Include_subdirs
2525
module Instrumentation = Dune0.Instrumentation
26+
module Libraries = Dune0.Libraries
2627
module Library = Dune0.Library
2728
module Lint = Dune0.Lint
2829
module Package = Dune0.Package

src/dunolint-lib/dunolint/dune0/executable.ml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ module Predicate = struct
6363
type t =
6464
[ `has_field of Has_field.t
6565
| `instrumentation of Instrumentation.Predicate.t Blang.t
66+
| `libraries of Libraries.Predicate.t Blang.t
6667
| `lint of Lint.Predicate.t Blang.t
6768
| `name of Name.Predicate.t Blang.t
6869
| `preprocess of Preprocess.Predicate.t Blang.t
@@ -77,12 +78,14 @@ module Predicate = struct
7778
| `has_field va, `has_field vb -> Has_field.equal va vb
7879
| `instrumentation va, `instrumentation vb ->
7980
Blang.equal Instrumentation.Predicate.equal va vb
81+
| `libraries va, `libraries vb -> Blang.equal Libraries.Predicate.equal va vb
8082
| `lint va, `lint vb -> Blang.equal Lint.Predicate.equal va vb
8183
| `name va, `name vb -> Blang.equal Name.Predicate.equal va vb
8284
| `preprocess va, `preprocess vb -> Blang.equal Preprocess.Predicate.equal va vb
8385
| `public_name va, `public_name vb -> Blang.equal Public_name.Predicate.equal va vb
8486
| ( ( `has_field _
8587
| `instrumentation _
88+
| `libraries _
8689
| `lint _
8790
| `name _
8891
| `preprocess _
@@ -100,6 +103,11 @@ module Predicate = struct
100103
(fun sexp ->
101104
`instrumentation (Blang.t_of_sexp Instrumentation.Predicate.t_of_sexp sexp))
102105
}
106+
; { atom = "libraries"
107+
; conv =
108+
Unary
109+
(fun sexp -> `libraries (Blang.t_of_sexp Libraries.Predicate.t_of_sexp sexp))
110+
}
103111
; { atom = "lint"
104112
; conv = Unary (fun sexp -> `lint (Blang.t_of_sexp Lint.Predicate.t_of_sexp sexp))
105113
}
@@ -131,6 +139,8 @@ module Predicate = struct
131139
| `instrumentation v ->
132140
List
133141
[ Atom "instrumentation"; Blang.sexp_of_t Instrumentation.Predicate.sexp_of_t v ]
142+
| `libraries v ->
143+
List [ Atom "libraries"; Blang.sexp_of_t Libraries.Predicate.sexp_of_t v ]
134144
| `lint v -> List [ Atom "lint"; Blang.sexp_of_t Lint.Predicate.sexp_of_t v ]
135145
| `name v -> List [ Atom "name"; Blang.sexp_of_t Name.Predicate.sexp_of_t v ]
136146
| `preprocess v ->

0 commit comments

Comments
 (0)