Skip to content

Commit 6dd74b2

Browse files
authored
atddiff: Add --backward, --forward, --types filters (#367)
* Add atddiff result filtering (--backward, --forward, --types) * Update changelog * Rephrase comment * Update atddiff howto * Rephrase doc --------- Co-authored-by: Martin Jambon <[email protected]>
1 parent 88d616f commit 6dd74b2

19 files changed

+288
-1
lines changed

CHANGES.md

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ Unreleased
44
* atdd: Fix various issues with the interoperability of user defined types,
55
used in or outside of records (#355)
66
* atdd: Generated `.d` files now have the suffix `_atd.d` (#355)
7+
* atddiff now supports options for filtering the findings based on the
8+
direction of the incompatibility (`--backward`, `--forward`) or based on the
9+
name of the affected types (`--types`) (#365)
710

811
2.13.0 (2023-10-15)
912
-------------------

atddiff/src/bin/Atddiff_main.ml

+48
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ type conf = {
99
old_file: string;
1010
new_file: string;
1111
out_file: string option;
12+
filter: Atddiff.filter;
1213
json_defaults_old: bool;
1314
json_defaults_new: bool;
1415
exit_success: bool;
@@ -38,6 +39,7 @@ let run conf =
3839
else
3940
let out_data =
4041
Atddiff.compare_files
42+
~filter:conf.filter
4143
~json_defaults_old:conf.json_defaults_old
4244
~json_defaults_new:conf.json_defaults_new
4345
conf.old_file conf.new_file in
@@ -91,6 +93,31 @@ let out_file_term : string option Term.t =
9193
in
9294
Arg.value (Arg.opt (Arg.some Arg.string) None info)
9395

96+
let backward_term : bool Term.t =
97+
let info =
98+
Arg.info ["backward"]
99+
~doc:"Ignore findings other than backward incompatibilies."
100+
in
101+
Arg.value (Arg.flag info)
102+
103+
let forward_term : bool Term.t =
104+
let info =
105+
Arg.info ["forward"]
106+
~doc:"Ignore findings other than forward incompatibilies."
107+
in
108+
Arg.value (Arg.flag info)
109+
110+
let types_term : string list option Term.t =
111+
let info =
112+
Arg.info ["types"]
113+
~docv:"TYPE_NAME1,TYPE_NAME2,..."
114+
~doc:"Select findings that affect these types. If no '--type' filter is \
115+
provided, all types are selected. For example, \
116+
'--type foo,bar' selects the findings that affect type 'foo', \
117+
type 'bar', or both."
118+
in
119+
Arg.value (Arg.opt (Arg.some (Arg.list Arg.string)) None info)
120+
94121
let json_defaults_term : bool Term.t =
95122
let info =
96123
Arg.info ["json-defaults"]
@@ -184,14 +211,32 @@ let man = [
184211
let cmdline_term run =
185212
let combine
186213
old_file new_file out_file
214+
backward forward types
187215
json_defaults json_defaults_old json_defaults_new
188216
exit_success version =
217+
let filter =
218+
let module A = Atddiff in
219+
let backward = if backward then [A.Filter (A.Backward)] else [] in
220+
let forward = if forward then [A.Filter (A.Forward)] else [] in
221+
let types =
222+
match types with
223+
| None -> []
224+
| Some types ->
225+
[A.Or
226+
(List.map (fun name ->
227+
A.Filter (A.Affected_type_name name))
228+
types)
229+
]
230+
in
231+
A.And (List.concat [backward; forward; types])
232+
in
189233
let json_defaults_old = json_defaults_old || json_defaults in
190234
let json_defaults_new = json_defaults_new || json_defaults in
191235
run {
192236
old_file;
193237
new_file;
194238
out_file;
239+
filter;
195240
json_defaults_old;
196241
json_defaults_new;
197242
exit_success;
@@ -202,6 +247,9 @@ let cmdline_term run =
202247
$ old_file_term
203248
$ new_file_term
204249
$ out_file_term
250+
$ backward_term
251+
$ forward_term
252+
$ types_term
205253
$ json_defaults_term
206254
$ json_defaults_old_term
207255
$ json_defaults_new_term

atddiff/src/lib/Atddiff.ml

+37
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,50 @@
22
Internal Atddiff library used by the 'atddiff' command.
33
*)
44

5+
type simple_filter =
6+
| Affected_type_name of string
7+
| Backward
8+
| Forward
9+
10+
type filter =
11+
| Or of filter list
12+
| And of filter list
13+
| Not of filter
14+
| Filter of simple_filter
15+
516
type output_format = Text | JSON
617

718
let version = Version.version
819

920
let format_json res : string =
1021
failwith "JSON output: not implemented"
1122

23+
let rec select_finding filter (x : Types.finding * string list) =
24+
match filter with
25+
| Or filters ->
26+
List.exists (fun filter -> select_finding filter x) filters
27+
| And filters ->
28+
List.for_all (fun filter -> select_finding filter x) filters
29+
| Not filter ->
30+
not (select_finding filter x)
31+
| Filter (Affected_type_name name) ->
32+
let _, names = x in
33+
List.mem name names
34+
| Filter Backward ->
35+
let finding, _ = x in
36+
(match finding.direction with
37+
| Backward | Both -> true
38+
| Forward -> false
39+
)
40+
| Filter Forward ->
41+
let finding, _ = x in
42+
(match finding.direction with
43+
| Forward | Both -> true
44+
| Backward -> false
45+
)
46+
1247
let compare_files
48+
?(filter = And [] (* all *))
1349
?(json_defaults_old = false)
1450
?(json_defaults_new = false)
1551
?(output_format = Text)
@@ -34,6 +70,7 @@ let compare_files
3470
match res with
3571
| [] -> Ok ()
3672
| res ->
73+
let res = List.filter (select_finding filter) res in
3774
Error (
3875
match output_format with
3976
| Text -> Format_text.to_string res

atddiff/src/lib/Atddiff.mli

+24
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,29 @@
22
Internal Atddiff library used by the 'atddiff' command.
33
*)
44

5+
type simple_filter =
6+
(* A finding reported to affect the given ATD type name.
7+
It's possible that this type name exists only in one of the two versions
8+
of the ATD file. *)
9+
| Affected_type_name of string
10+
(* Select backward incompatibilies *)
11+
| Backward
12+
(* Select forward incompatibilies *)
13+
| Forward
14+
15+
(* The type of a filter over the findings.
16+
17+
Command-line options that describe filters are translated to this type.
18+
19+
This query language isn't exposed by the CLI right now because it's
20+
overkill and it would require a special parser.
21+
*)
22+
type filter =
23+
| Or of filter list (* union; none = Or [] *)
24+
| And of filter list (* intersection; all = And [] *)
25+
| Not of filter (* set difference *)
26+
| Filter of simple_filter
27+
528
type output_format = Text | JSON
629

730
(*
@@ -13,6 +36,7 @@ type output_format = Text | JSON
1336
populated in new JSON data.
1437
*)
1538
val compare_files :
39+
?filter:filter ->
1640
?json_defaults_old:bool ->
1741
?json_defaults_new:bool ->
1842
?output_format:output_format ->

atddiff/src/lib/Types.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Type definitions used to build comparison results
33
*)
44

5-
type direction = Forward | Backward | Both
5+
type direction = Backward | Forward | Both
66

77
type incompatibility_kind =
88
| Missing_field of { field_name: string }

atddiff/test/filter/dune

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
; Generated by ./generate-dune-rules
2+
; For adding tests, read the instructions in the Makefile.
3+
(rule
4+
(targets filter.txt)
5+
(deps filter_old.atd filter_new.atd)
6+
(action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success --backward --forward --types a,b)))
7+
8+
(rule
9+
(alias runtest)
10+
(deps filter.txt)
11+
(action (diff filter.expected.txt filter.txt)))
12+
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Incompatibility in both directions:
2+
File "filter_old.atd", line 7, characters 16-20
3+
File "filter_new.atd", line 7, characters 16-23
4+
Type names 'int' and 'string' are not the same and may not be compatible.
5+
The following types are affected:
6+
a
7+
b
8+

atddiff/test/filter/filter_new.atd

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
(*
2+
Test that the command-line filters make the correct selection of findings.
3+
*)
4+
5+
type a = {
6+
added_field: int; (* backward incompatibility *)
7+
changing_type: string;
8+
}
9+
10+
type b = {
11+
uses_a: a; (* backward and forward incompatibilities *)
12+
}
13+
14+
(* Findings affecting only 'c' are ignored. *)
15+
type c = {
16+
added_field_in_ignored_type: int;
17+
}

atddiff/test/filter/filter_old.atd

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
(*
2+
Test that the command-line filters make the correct selection of findings.
3+
*)
4+
5+
type a = {
6+
deleted_field: int; (* forward incompatibility *)
7+
changing_type: int;
8+
}
9+
10+
type b = {
11+
uses_a: a; (* backward and forward incompatibilities *)
12+
}
13+
14+
(* Findings affecting only 'c' are ignored. *)
15+
type c = {
16+
deleted_field_in_ignored_type: int;
17+
}

atddiff/test/filter_backward/dune

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
; Generated by ./generate-dune-rules
2+
; For adding tests, read the instructions in the Makefile.
3+
(rule
4+
(targets filter.txt)
5+
(deps filter_old.atd filter_new.atd)
6+
(action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success --backward)))
7+
8+
(rule
9+
(alias runtest)
10+
(deps filter.txt)
11+
(action (diff filter.expected.txt filter.txt)))
12+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Backward incompatibility:
2+
File "filter_new.atd", line 6, characters 2-18
3+
Required field 'added_field' is new.
4+
The following types are affected:
5+
a
6+
b
7+
8+
Incompatibility in both directions:
9+
File "filter_old.atd", line 7, characters 16-20
10+
File "filter_new.atd", line 7, characters 16-23
11+
Type names 'int' and 'string' are not the same and may not be compatible.
12+
The following types are affected:
13+
a
14+
b
15+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(*
2+
Test that the command-line filters make the correct selection of findings.
3+
*)
4+
5+
type a = {
6+
added_field: int; (* backward incompatibility *)
7+
changing_type: string;
8+
}
9+
10+
type b = {
11+
uses_a: a; (* backward and forward incompatibilities *)
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(*
2+
Test that the command-line filters make the correct selection of findings.
3+
*)
4+
5+
type a = {
6+
deleted_field: int; (* forward incompatibility *)
7+
changing_type: int;
8+
}
9+
10+
type b = {
11+
uses_a: a; (* backward and forward incompatibilities *)
12+
}

atddiff/test/filter_forward/dune

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
; Generated by ./generate-dune-rules
2+
; For adding tests, read the instructions in the Makefile.
3+
(rule
4+
(targets filter.txt)
5+
(deps filter_old.atd filter_new.atd)
6+
(action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success --forward)))
7+
8+
(rule
9+
(alias runtest)
10+
(deps filter.txt)
11+
(action (diff filter.expected.txt filter.txt)))
12+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Forward incompatibility:
2+
File "filter_old.atd", line 6, characters 2-20
3+
Required field 'deleted_field' disappeared.
4+
The following types are affected:
5+
a
6+
b
7+
8+
Incompatibility in both directions:
9+
File "filter_old.atd", line 7, characters 16-20
10+
File "filter_new.atd", line 7, characters 16-23
11+
Type names 'int' and 'string' are not the same and may not be compatible.
12+
The following types are affected:
13+
a
14+
b
15+
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(*
2+
Test that the command-line filters make the correct selection of findings.
3+
*)
4+
5+
type a = {
6+
added_field: int; (* backward incompatibility *)
7+
changing_type: string;
8+
}
9+
10+
type b = {
11+
uses_a: a; (* backward and forward incompatibilities *)
12+
}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(*
2+
Test that the command-line filters make the correct selection of findings.
3+
*)
4+
5+
type a = {
6+
deleted_field: int; (* forward incompatibility *)
7+
changing_type: int;
8+
}
9+
10+
type b = {
11+
uses_a: a; (* backward and forward incompatibilities *)
12+
}

0 commit comments

Comments
 (0)