diff options
author | Stephane Glondu <steph@glondu.net> | 2024-02-18 11:27:09 +0100 |
---|---|---|
committer | Stephane Glondu <steph@glondu.net> | 2024-02-18 11:27:09 +0100 |
commit | d0b346d9ba0914a86575396b2a638fcd279837b1 (patch) | |
tree | fdbe5383b39eddc5862116f49c25da69a4a5af2a | |
parent | c69566cd93471dd2eb9c1f516b32c2f690877bf8 (diff) |
New upstream version 2.15.0
75 files changed, 795 insertions, 475 deletions
@@ -1,3 +1,12 @@ +2.15.0 (2023-10-26) +------------------- + +* atddiff: Breaking changes in the JSON output format of atddiff (#382) +* atddiff: Fix `atddiff --version` output (#379) +* atddiff: New experimental option `--no-locations` aimed at + producing more stable results that allow diffing successive + atddiff reports to spot new findings and ignore old ones (#377) + 2.14.1 (2023-10-20) ------------------- @@ -1,4 +1,4 @@ -version: "2.14.1" +version: "2.15.0" # This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: "Parser for the ATD data format description language" diff --git a/atd/src/version.ml b/atd/src/version.ml index ab1c248..ba7c4aa 100644 --- a/atd/src/version.ml +++ b/atd/src/version.ml @@ -1,3 +1,3 @@ (* The version string is replaced by the actual version at release time by 'dune release'. *) -let version = "2.14.1" +let version = "2.15.0" @@ -1,4 +1,4 @@ -version: "2.14.1" +version: "2.15.0" # This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: "DLang code generation for ATD APIs" diff --git a/atdd/src/lib/Version.ml b/atdd/src/lib/Version.ml index ab1c248..ba7c4aa 100644 --- a/atdd/src/lib/Version.ml +++ b/atdd/src/lib/Version.ml @@ -1,3 +1,3 @@ (* The version string is replaced by the actual version at release time by 'dune release'. *) -let version = "2.14.1" +let version = "2.15.0" diff --git a/atddiff/src/bin/Atddiff_main.ml b/atddiff/src/bin/Atddiff_main.ml index c3f5629..b052e8c 100644 --- a/atddiff/src/bin/Atddiff_main.ml +++ b/atddiff/src/bin/Atddiff_main.ml @@ -12,6 +12,7 @@ type conf = { filter: Atddiff.filter; json_defaults_old: bool; json_defaults_new: bool; + with_locations: bool; output_format: Atddiff.output_format; exit_success: bool; version: bool; @@ -32,11 +33,13 @@ let exit_info = [ finding_exit, "atddiff successfully found one or more issues to report."; ] |> List.map (fun (code, doc) -> Cmd.Exit.info ~doc code) +let print_version_and_exit () = + print_endline Atddiff.version; + exit ok_exit + let run conf = - if conf.version then ( - print_endline Atddiff.version; - exit ok_exit - ) + if conf.version then + print_version_and_exit () else let out_data = Atddiff.compare_files @@ -44,6 +47,7 @@ let run conf = ~json_defaults_old:conf.json_defaults_old ~json_defaults_new:conf.json_defaults_new ~output_format:conf.output_format + ~with_locations:conf.with_locations conf.old_file conf.new_file in let exit_code, data = match out_data with @@ -166,6 +170,24 @@ let output_format_term : Atddiff.output_format Term.t = "json", Atddiff.JSON]) Atddiff.Text info) +let no_locations_term : bool Term.t = + let info = + Arg.info ["no-locations"] + ~doc:"[EXPERIMENTAL] \ + Omit file/line/column information when printing findings. \ + This is intended for maximizing the stability of the atddiff \ + reports so that diffing successive reports gives meaningful \ + results. This causes the results to be sorted by hash rather \ + than by location. The hex hash of each result is shown in both \ + text and JSON output. It is guaranteed to be the same for \ + a given version of atddiff compiled with a given version of \ + OCaml. In practice, it is not expected to change \ + often and can be used to track findings over time. Distinct \ + findings will have the same hash if they have \ + the same error message up to location." + in + Arg.value (Arg.flag info) + let exit_success_term : bool Term.t = let info = Arg.info ["exit-success"] @@ -228,7 +250,7 @@ let cmdline_term run = old_file new_file out_file backward forward types json_defaults json_defaults_old json_defaults_new - output_format + output_format no_locations exit_success version = let filter = let module A = Atddiff in @@ -256,6 +278,7 @@ let cmdline_term run = json_defaults_old; json_defaults_new; output_format; + with_locations = not no_locations; exit_success; version; } @@ -271,19 +294,25 @@ let cmdline_term run = $ json_defaults_old_term $ json_defaults_new_term $ output_format_term + $ no_locations_term $ exit_success_term $ version_term ) let parse_command_line_and_run run = - let info = - Cmd.info - ~doc - ~exits:exit_info - ~man - "atddiff" - in - Cmd.v info (cmdline_term run) |> Cmd.eval |> exit + match Sys.argv with + (* gross, but avoids complaints about missing input files *) + | [| _; "--version" |] -> + print_version_and_exit () + | _ -> + let info = + Cmd.info + ~doc + ~exits:exit_info + ~man + "atddiff" + in + Cmd.v info (cmdline_term run) |> Cmd.eval |> exit let safe_run conf = try run conf diff --git a/atddiff/src/lib/Atddiff.ml b/atddiff/src/lib/Atddiff.ml index 836a137..97eb411 100644 --- a/atddiff/src/lib/Atddiff.ml +++ b/atddiff/src/lib/Atddiff.ml @@ -19,7 +19,7 @@ type output_format = Text | JSON let version = Version.version -let rec select_finding filter (x : T.full_finding) = +let rec select_finding filter (x : T.finding) = match filter with | Or filters -> List.exists (fun filter -> select_finding filter x) filters @@ -30,12 +30,12 @@ let rec select_finding filter (x : T.full_finding) = | Filter (Affected_type_name name) -> List.mem name x.affected_types | Filter Backward -> - (match x.finding.direction with + (match x.direction with | Backward | Both -> true | Forward -> false ) | Filter Forward -> - (match x.finding.direction with + (match x.direction with | Forward | Both -> true | Backward -> false ) @@ -45,6 +45,7 @@ let compare_files ?(json_defaults_old = false) ?(json_defaults_new = false) ?(output_format = Text) + ?(with_locations = true) old_file new_file = let load_file atd_file = atd_file @@ -59,7 +60,8 @@ let compare_files let res = let options : Compare.options = { json_defaults_old; - json_defaults_new + json_defaults_new; + sort_by = (if with_locations then Location else Hash); } in Compare.asts options ast1 ast2 in @@ -70,6 +72,6 @@ let compare_files { findings = List.filter (select_finding filter) findings } in Error ( match output_format with - | Text -> Format_text.to_string res - | JSON -> Format_JSON.to_string res ^ "\n" + | Text -> Format_text.to_string ~with_locations res + | JSON -> Format_JSON.to_string ~with_locations res ^ "\n" ) diff --git a/atddiff/src/lib/Atddiff.mli b/atddiff/src/lib/Atddiff.mli index dddf5d4..27b08e7 100644 --- a/atddiff/src/lib/Atddiff.mli +++ b/atddiff/src/lib/Atddiff.mli @@ -40,6 +40,7 @@ val compare_files : ?json_defaults_old:bool -> ?json_defaults_new:bool -> ?output_format:output_format -> + ?with_locations:bool -> string -> string -> (unit, string) Result.t (* Version of the atddiff library and executable *) diff --git a/atddiff/src/lib/Atddiff_output.atd b/atddiff/src/lib/Atddiff_output.atd index 227f20c..28580bf 100644 --- a/atddiff/src/lib/Atddiff_output.atd +++ b/atddiff/src/lib/Atddiff_output.atd @@ -76,6 +76,11 @@ type incompatibility_kind = [ different findings at the same location(s). *) type finding = { + (* A hexadecimal hash of all the other fields excluding location fields. + It is not necessarily unique but should be unique in most cases. + It's used for sorting, tracking, and referring to findings. *) + hash: string; + direction: direction; kind: incompatibility_kind; location_old: location option; @@ -84,10 +89,7 @@ type finding = { (* The description should not mention the affected root type definition so as to allow the deduplication of findings. *) description: string; -} -type full_finding = { - finding: finding; affected_types: string list; } @@ -95,5 +97,5 @@ type full_finding = { A result is a list of unique findings. *) type result = { - findings: full_finding list; + findings: finding list; } diff --git a/atddiff/src/lib/Atddiff_output_t.ml b/atddiff/src/lib/Atddiff_output_t.ml index c096bd9..fbb2bbe 100644 --- a/atddiff/src/lib/Atddiff_output_t.ml +++ b/atddiff/src/lib/Atddiff_output_t.ml @@ -22,13 +22,13 @@ type incompatibility_kind = type direction = Backward | Forward | Both type finding = { + hash: string; direction: direction; kind: incompatibility_kind; location_old: location option; location_new: location option; - description: string + description: string; + affected_types: string list } -type full_finding = { finding: finding; affected_types: string list } - -type result = { findings: full_finding list } +type result = { findings: finding list } diff --git a/atddiff/src/lib/Atddiff_output_t.mli b/atddiff/src/lib/Atddiff_output_t.mli index c096bd9..fbb2bbe 100644 --- a/atddiff/src/lib/Atddiff_output_t.mli +++ b/atddiff/src/lib/Atddiff_output_t.mli @@ -22,13 +22,13 @@ type incompatibility_kind = type direction = Backward | Forward | Both type finding = { + hash: string; direction: direction; kind: incompatibility_kind; location_old: location option; location_new: location option; - description: string + description: string; + affected_types: string list } -type full_finding = { finding: finding; affected_types: string list } - -type result = { findings: full_finding list } +type result = { findings: finding list } diff --git a/atddiff/src/lib/Compare.ml b/atddiff/src/lib/Compare.ml index 75b8feb..5e4f665 100644 --- a/atddiff/src/lib/Compare.ml +++ b/atddiff/src/lib/Compare.ml @@ -39,11 +39,14 @@ module Strings = Set.Make(String) (* This is used for instanciating type variables. *) module Env = Map.Make(String) +type sort_by = Location | Hash + type options = { (* Are fields with defaults always populated in old JSON data? *) json_defaults_old : bool; (* Are fields with defaults always populated in new JSON data? *) json_defaults_new : bool; + sort_by: sort_by; } let is_builtin_name = @@ -94,18 +97,43 @@ let split_types types1 types2 = let b = Strings.of_list types2 in Strings.diff a b, Strings.inter a b, Strings.diff b a +let create_finding + ~direction ~kind ?location_old ?location_new ~description () = + { + hash = ""; (* computed later *) + direction; + kind; + location_old; + location_new; + description; + affected_types = []; (* computed later *) + } + +let complete_finding (x : finding) ~affected_types = + let x = { x with affected_types } in + let hash = + (* Make the hash function use all the data by using very large + parameters *) + Hashtbl.hash_param 1_000_000 1_000_000 + (x.direction, x.kind, x.description, x.affected_types) + |> Printf.sprintf "%08x" + in + { x with hash } + let report_deleted_types defs name_set = List.filter_map (fun (loc, (name, _param, _an), _expr) -> if Strings.mem name name_set then - Some (([name], []), { - direction = Backward; - kind = Deleted_type; - location_old = Some (loc |> Loc.of_atd_loc); - location_new = None; - description = - sprintf "The definition for type '%s' no longer exists." - name - }) + Some (([name], []), + create_finding + ~direction:Backward + ~kind:Deleted_type + ~location_old: (loc |> Loc.of_atd_loc) + ~description:( + sprintf "The definition for type '%s' no longer exists." + name + ) + () + ) else None ) defs @@ -113,13 +141,14 @@ let report_deleted_types defs name_set = let report_added_types defs name_set = List.filter_map (fun (loc, (name, _param, _an), _expr) -> if Strings.mem name name_set then - Some (([], [name]), { - direction = Forward; - kind = Deleted_type; - location_old = None; - location_new = Some (loc |> Loc.of_atd_loc); - description = sprintf "There is a new type named '%s'." name - }) + Some (([], [name]), + create_finding + ~direction:Forward + ~kind:Deleted_type + ~location_new:(loc |> Loc.of_atd_loc) + ~description:(sprintf "There is a new type named '%s'." name) + () + ) else None ) defs @@ -333,8 +362,18 @@ let report_structural_mismatches options def_tbl1 def_tbl2 shared_types : let key = (def_name, e1, e2) in Hashtbl.replace visited_tbl key () in - let add stacks x = - findings := (stacks, x) :: !findings in + let add + ~direction ~kind ?location_old ?location_new ~description stacks = + let finding = + create_finding + ~direction + ~kind + ?location_old + ?location_new + ~description + () + in + findings := (stacks, finding) :: !findings in (* 'stacks' is the pair of stacks of type names visited starting from the root definition. They're the type names affected by the finding. @@ -365,16 +404,16 @@ let report_structural_mismatches options def_tbl1 def_tbl2 shared_types : | Name (_, (loc1, name1, args1), _an1), Name (_, (loc2, name2, args2), _an2) -> if name1 <> name2 then - add stacks { - direction = Both; - kind = Incompatible_type; - location_old = Some (loc1 |> Loc.of_atd_loc); - location_new = Some (loc2 |> Loc.of_atd_loc); - description = + add stacks + ~direction:Both + ~kind:Incompatible_type + ~location_old:(loc1 |> Loc.of_atd_loc) + ~location_new:(loc2 |> Loc.of_atd_loc) + ~description:( sprintf "Type names '%s' and '%s' are not the same and \ may not be compatible." - name1 name2; - } + name1 name2 + ) else () | Wrap _, _ | _, Wrap _ -> assert false @@ -382,14 +421,14 @@ let report_structural_mismatches options def_tbl1 def_tbl2 shared_types : (* Type variables were normalized so they can be compared directly. *) if var1 <> var2 then - add stacks { - direction = Both; - kind = Incompatible_type; - location_old = Some (loc1 |> Loc.of_atd_loc); - location_new = Some (loc2 |> Loc.of_atd_loc); - description = + add stacks + ~direction:Both + ~kind:Incompatible_type + ~location_old:(loc1 |> Loc.of_atd_loc) + ~location_new:(loc2 |> Loc.of_atd_loc) + ~description:( sprintf "Incompatible type variables are being used."; - } + ) | (Sum _ | Record _ | Tuple _ @@ -399,15 +438,15 @@ let report_structural_mismatches options def_tbl1 def_tbl2 shared_types : | Shared _ | Name _ | Tvar _) as e1, e2 -> - add stacks { - direction = Both; - kind = Incompatible_type; - location_old = Some (A.loc_of_type_expr e1 |> Loc.of_atd_loc); - location_new = Some (A.loc_of_type_expr e2 |> Loc.of_atd_loc); - description = + add stacks + ~direction:Both + ~kind:Incompatible_type + ~location_old:(A.loc_of_type_expr e1 |> Loc.of_atd_loc) + ~location_new:(A.loc_of_type_expr e2 |> Loc.of_atd_loc) + ~description:( sprintf "Incompatible kinds of types: %s is now %s." - (kind_of_expr e1) (a_kind_of_expr e2); - } + (kind_of_expr e1) (a_kind_of_expr e2) + ) and cmp_variants stacks loc1 loc2 cases1 cases2 = let with_names cases = cases @@ -429,24 +468,20 @@ let report_structural_mismatches options def_tbl1 def_tbl2 shared_types : left_only |> List.iter (fun json_name -> let loc, (_name, _an), _opt_e = List.assoc json_name named1 in - add stacks { - direction = Backward; - kind = Missing_variant { variant_name = json_name }; - location_old = Some (loc |> Loc.of_atd_loc); - location_new = None; - description = sprintf "Case '%s' disappeared." json_name - } + add stacks + ~direction:Backward + ~kind:(Missing_variant { variant_name = json_name }) + ~location_old:(loc |> Loc.of_atd_loc) + ~description:(sprintf "Case '%s' disappeared." json_name) ); right_only |> List.iter (fun json_name -> let loc, (_name, _an), _opt_e = List.assoc json_name named2 in - add stacks { - direction = Forward; - kind = Missing_variant { variant_name = json_name }; - location_old = None; - location_new = Some (loc |> Loc.of_atd_loc); - description = sprintf "Case '%s' is new." json_name - } + add stacks + ~direction:Forward + ~kind:(Missing_variant { variant_name = json_name }) + ~location_new:(loc |> Loc.of_atd_loc) + ~description:(sprintf "Case '%s' is new." json_name) ); shared |> List.iter (fun json_name -> @@ -457,23 +492,23 @@ let report_structural_mismatches options def_tbl1 def_tbl2 shared_types : | Some e1, Some e2 -> cmp_expr stacks e1 e2 | Some _, None -> - add stacks { - direction = Both; - kind = Missing_variant_argument { variant_name = json_name }; - location_old = Some (loc1 |> Loc.of_atd_loc); - location_new = Some (loc2 |> Loc.of_atd_loc); - description = + add stacks + ~direction:Both + ~kind:(Missing_variant_argument { variant_name = json_name }) + ~location_old:(loc1 |> Loc.of_atd_loc) + ~location_new:(loc2 |> Loc.of_atd_loc) + ~description:( sprintf "Case '%s' no longer has an argument." json_name - } + ) | None, Some _ -> - add stacks { - direction = Both; - kind = Missing_variant_argument { variant_name = json_name }; - location_old = Some (loc1 |> Loc.of_atd_loc); - location_new = Some (loc2 |> Loc.of_atd_loc); - description = + add stacks + ~direction:Both + ~kind:(Missing_variant_argument { variant_name = json_name }) + ~location_old:(loc1 |> Loc.of_atd_loc) + ~location_new:(loc2 |> Loc.of_atd_loc) + ~description:( sprintf "Case '%s' used to not have an argument." json_name - } + ) ) and cmp_fields stacks loc1 loc2 fields1 fields2 = let with_names fields = @@ -500,13 +535,13 @@ let report_structural_mismatches options def_tbl1 def_tbl2 shared_types : | Optional | With_default -> () | Required -> - add stacks { - direction = Forward; - kind = Missing_field { field_name = json_name }; - location_old = Some (loc |> Loc.of_atd_loc); - location_new = None; - description = sprintf "Required field '%s' disappeared." json_name - } + add stacks + ~direction:Forward + ~kind:(Missing_field { field_name = json_name }) + ~location_old:(loc |> Loc.of_atd_loc) + ~description:( + sprintf "Required field '%s' disappeared." json_name + ) ); right_only |> List.iter (fun json_name -> @@ -515,13 +550,13 @@ let report_structural_mismatches options def_tbl1 def_tbl2 shared_types : | Optional | With_default -> () | Required -> - add stacks { - direction = Backward; - kind = Missing_field { field_name = json_name }; - location_old = None; - location_new = Some (loc |> Loc.of_atd_loc); - description = sprintf "Required field '%s' is new." json_name - } + add stacks + ~direction:Backward + ~kind:(Missing_field { field_name = json_name }) + ~location_new:(loc |> Loc.of_atd_loc) + ~description:( + sprintf "Required field '%s' is new." json_name + ) ); shared |> List.iter (fun json_name -> @@ -537,57 +572,57 @@ let report_structural_mismatches options def_tbl1 def_tbl2 shared_types : | Required, With_default when options.json_defaults_new -> () | Required, With_default -> - add stacks { - direction = Forward; - kind = Default_required { field_name = json_name }; - location_old = Some (loc1 |> Loc.of_atd_loc); - location_new = Some (loc2 |> Loc.of_atd_loc); - description = - sprintf "\ + add stacks + ~direction:Forward + ~kind:(Default_required { field_name = json_name }) + ~location_old:(loc1 |> Loc.of_atd_loc) + ~location_new:(loc2 |> Loc.of_atd_loc) + ~description:( + sprintf "\ Formerly required field '%s' is now optional but has a default value. You must ensure that new implementations always populate the JSON field with a value (using atdgen's option -j-defaults or equivalent) so that older implementations can read newer data. If this is already the case, use 'atddiff --json-defaults-new' to disable this warning." - json_name - } + json_name + ) | Required, Optional -> - add stacks { - direction = Forward; - kind = Missing_field { field_name = json_name }; - location_old = Some (loc1 |> Loc.of_atd_loc); - location_new = Some (loc2 |> Loc.of_atd_loc); - description = - sprintf "Formerly required field '%s' is now optional." - json_name - } + add stacks + ~direction:Forward + ~kind:(Missing_field { field_name = json_name }) + ~location_old:(loc1 |> Loc.of_atd_loc) + ~location_new:(loc2 |> Loc.of_atd_loc) + ~description:( + sprintf "Formerly required field '%s' is now optional." + json_name + ) | With_default, Required when options.json_defaults_old -> () | With_default, Required -> - add stacks { - direction = Backward; - kind = Default_required { field_name = json_name }; - location_old = Some (loc1 |> Loc.of_atd_loc); - location_new = Some (loc2 |> Loc.of_atd_loc); - description = - sprintf "\ + add stacks + ~direction:Backward + ~kind:(Default_required { field_name = json_name }) + ~location_old:(loc1 |> Loc.of_atd_loc) + ~location_new:(loc2 |> Loc.of_atd_loc) + ~description:( + sprintf "\ Newly required field '%s' was optional but had a default value. If old implementations in use always populate the JSON field with a value (using atdgen's option -j-defaults or equivalent), then there's no problem and you should use 'atddiff --json-defaults-old' to disable this warning." - json_name - } + json_name + ) | Optional, Required -> - add stacks { - direction = Backward; - kind = Missing_field { field_name = json_name }; - location_old = Some (loc1 |> Loc.of_atd_loc); - location_new = Some (loc2 |> Loc.of_atd_loc); - description = - sprintf "Formerly optional field '%s' is now required." - json_name - } + add stacks + ~direction:Backward + ~kind:(Missing_field { field_name = json_name }) + ~location_old:(loc1 |> Loc.of_atd_loc) + ~location_new:(loc2 |> Loc.of_atd_loc) + ~description:( + sprintf "Formerly optional field '%s' is now required." + json_name + ) ); cmp_expr stacks e1 e2 ) @@ -596,13 +631,12 @@ then there's no problem and you should use let n1 = List.length cells1 in let n2 = List.length cells2 in if n1 <> n2 then - add stacks { - direction = Both; - kind = Incompatible_type; - location_old = Some (A.loc_of_type_expr e1 |> Loc.of_atd_loc); - location_new = Some (A.loc_of_type_expr e2 |> Loc.of_atd_loc); - description = sprintf "Incompatible tuple lengths"; - } + add stacks + ~direction:Both + ~kind:Incompatible_type + ~location_old:(A.loc_of_type_expr e1 |> Loc.of_atd_loc) + ~location_new:(A.loc_of_type_expr e2 |> Loc.of_atd_loc) + ~description:"Incompatible tuple lengths" else List.iter2 (fun (_loc1, e1, _an1) (_loc2, e2, _an2) -> cmp_expr stacks e1 e2 @@ -643,7 +677,7 @@ let compare_opt_location (a : Loc.t option) (b : Loc.t option) = 3b. Position in the new file 4. Everything else (expected to not occur) *) -let compare_findings (a : finding) (b : finding) = +let compare_findings_by_location (a : finding) (b : finding) = (* sort by left-only, right-only, both *) let c = Int.compare (finding_group a) (finding_group b) in if c <> 0 then c @@ -656,7 +690,13 @@ let compare_findings (a : finding) (b : finding) = if c <> 0 then c else Stdlib.compare a b -let group_and_sort_findings xs : full_finding list = +let compare_findings_by_hash (a : finding) (b : finding) = + let c = String.compare a.hash b.hash in + if c <> 0 then c + else + compare_findings_by_location a b + +let group_and_sort_findings ~sort_by xs : finding list = let tbl = Hashtbl.create 100 in xs |> List.iter (fun ((affected_names1, affected_names2), finding) -> @@ -669,17 +709,25 @@ let group_and_sort_findings xs : full_finding list = r := (Strings.union (Strings.of_list affected_names1) acc1, Strings.union (Strings.of_list affected_names2) acc2) ); - Hashtbl.fold (fun finding r acc -> - let affected_names1, affected_names2 = !r in - (* For now, we report old and new type names as a single list. - We could be more precise about equivalence between old - and new names. Would it help the user? *) - let all_affected_names = Strings.union affected_names1 affected_names2 in - { finding; - affected_types = Strings.elements all_affected_names } - :: acc) - tbl [] - |> List.sort (fun a b -> compare_findings a.finding b.finding) + let findings = + Hashtbl.fold (fun finding r acc -> + let affected_names1, affected_names2 = !r in + (* For now, we report old and new type names as a single list. + We could be more precise about equivalence between old + and new names. Would it help the user? *) + let all_affected_names = Strings.union affected_names1 affected_names2 in + assert (finding.affected_types = []); + complete_finding finding + ~affected_types:(Strings.elements all_affected_names) + :: acc) + tbl [] + in + let compare_findings = + match sort_by with + | Location -> compare_findings_by_location + | Hash -> compare_findings_by_hash + in + List.sort compare_findings findings (* Expectations: @@ -727,6 +775,6 @@ let asts options (ast1 : A.full_module) (ast2 : A.full_module) : result = in let findings = findings - |> group_and_sort_findings + |> group_and_sort_findings ~sort_by:options.sort_by in { findings } diff --git a/atddiff/src/lib/Compare.mli b/atddiff/src/lib/Compare.mli index a2d0a27..6c88267 100644 --- a/atddiff/src/lib/Compare.mli +++ b/atddiff/src/lib/Compare.mli @@ -4,11 +4,14 @@ The findings are sorted nicely. *) +type sort_by = Location | Hash + type options = { (* Are fields with defaults always populated in old JSON data? *) json_defaults_old : bool; (* Are fields with defaults always populated in new JSON data? *) json_defaults_new : bool; + sort_by: sort_by; } val asts : diff --git a/atddiff/src/lib/Format_JSON.ml b/atddiff/src/lib/Format_JSON.ml index ceaf5a1..cd1a468 100644 --- a/atddiff/src/lib/Format_JSON.ml +++ b/atddiff/src/lib/Format_JSON.ml @@ -51,28 +51,29 @@ let fmt_location (x : location) : json = "end", fmt_position x.end_; ] -let fmt_finding (x : finding) : json = +let fmt_finding ~with_locations (x : finding) : json = + let x = + if with_locations then x + else + { x with location_old = None; location_new = None } + in `Assoc (remove_null_fields [ + "hash", `String x.hash; "direction", fmt_direction x.direction; "kind", fmt_kind x.kind; "location_old", option fmt_location x.location_old; "location_new", option fmt_location x.location_new; "description", `String x.description; - ]) - -let fmt_full_finding (x : full_finding) : json = - `Assoc [ - "finding", fmt_finding x.finding; "affected_types", `List (List.map string x.affected_types); - ] + ]) -let to_yojson (x : result) : json = +let to_yojson ~with_locations (x : result) : json = `Assoc [ - "findings", `List (List.map fmt_full_finding x.findings) + "findings", `List (List.map (fmt_finding ~with_locations) x.findings) ] -let to_string x = +let to_string ~with_locations x = x - |> to_yojson + |> to_yojson ~with_locations |> Yojson.Safe.to_string |> Yojson.Safe.prettify diff --git a/atddiff/src/lib/Format_JSON.mli b/atddiff/src/lib/Format_JSON.mli index 360d12e..d7ca9e6 100644 --- a/atddiff/src/lib/Format_JSON.mli +++ b/atddiff/src/lib/Format_JSON.mli @@ -2,4 +2,6 @@ Convert (tediously) the atddiff findings to JSON. *) -val to_string : Atddiff_output_t.result -> string +val to_string : + with_locations:bool -> + Atddiff_output_t.result -> string diff --git a/atddiff/src/lib/Format_text.ml b/atddiff/src/lib/Format_text.ml index 53da6f9..0432b33 100644 --- a/atddiff/src/lib/Format_text.ml +++ b/atddiff/src/lib/Format_text.ml @@ -15,8 +15,7 @@ let format_loc_text opt_loc1 opt_loc2 = (Loc.to_string loc1) (Loc.to_string loc2) -let format_incompatibility_text buf (x : T.full_finding) = - let finding = x.finding in +let format_incompatibility_text ~with_locations buf (finding : T.finding) = let is_certain = (* TODO: more clearly distinguish Warning from Error? *) match finding.kind with @@ -37,23 +36,23 @@ let format_incompatibility_text buf (x : T.full_finding) = | Backward, false -> "Possible backward incompatibility" | Both, false -> "Possible forward and backward incompatibility" in + bprintf buf "[%s] %s:\n" finding.hash dir; + if with_locations then + bprintf buf "%s:\n" + (format_loc_text finding.location_old finding.location_new); bprintf buf "\ -%s: -%s: %s The following types are affected:%s " - dir - (format_loc_text finding.location_old finding.location_new) finding.description - (x.affected_types + (finding.affected_types |> List.map (fun name -> "\n " ^ name) |> String.concat "") -let to_string (res : T.result) : string = +let to_string ~with_locations (res : T.result) : string = let buf = Buffer.create 1000 in List.iter (fun x -> - format_incompatibility_text buf x; + format_incompatibility_text ~with_locations buf x; Buffer.add_char buf '\n' ) res.findings; Buffer.contents buf diff --git a/atddiff/src/lib/Format_text.mli b/atddiff/src/lib/Format_text.mli index 4467723..6310fc2 100644 --- a/atddiff/src/lib/Format_text.mli +++ b/atddiff/src/lib/Format_text.mli @@ -2,4 +2,6 @@ Format comparison results in a human-readable form *) -val to_string : Atddiff_output_t.result -> string +val to_string : + with_locations:bool -> + Atddiff_output_t.result -> string diff --git a/atddiff/src/lib/Version.ml b/atddiff/src/lib/Version.ml index ab1c248..ba7c4aa 100644 --- a/atddiff/src/lib/Version.ml +++ b/atddiff/src/lib/Version.ml @@ -1,3 +1,3 @@ (* The version string is replaced by the actual version at release time by 'dune release'. *) -let version = "2.14.1" +let version = "2.15.0" diff --git a/atddiff/test/default/backward_incompatible_record.expected.txt b/atddiff/test/default/backward_incompatible_record.expected.txt index bbdc3d4..dc2af28 100644 --- a/atddiff/test/default/backward_incompatible_record.expected.txt +++ b/atddiff/test/default/backward_incompatible_record.expected.txt @@ -1,10 +1,10 @@ -Backward incompatibility: +[2283db51] Backward incompatibility: File "backward_incompatible_record_new.atd", line 2, characters 2-18: Required field 'added_field' is new. The following types are affected: backward_incompatible_record -Backward incompatibility: +[3c1ae3e6] Backward incompatibility: File "backward_incompatible_record_old.atd", line 2, characters 2-31 File "backward_incompatible_record_new.atd", line 3, characters 2-23: Formerly optional field 'becomes_required' is now required. diff --git a/atddiff/test/default/backward_incompatible_record_if_implicit_defaults.expected.txt b/atddiff/test/default/backward_incompatible_record_if_implicit_defaults.expected.txt index 12d75a8..540b391 100644 --- a/atddiff/test/default/backward_incompatible_record_if_implicit_defaults.expected.txt +++ b/atddiff/test/default/backward_incompatible_record_if_implicit_defaults.expected.txt @@ -1,4 +1,4 @@ -Possible backward incompatibility: +[1963da34] Possible backward incompatibility: File "backward_incompatible_record_if_implicit_defaults_old.atd", line 2, characters 2-24 File "backward_incompatible_record_if_implicit_defaults_new.atd", line 2, characters 2-23: Newly required field 'becomes_required' was optional but had a default value. diff --git a/atddiff/test/default/backward_incompatible_variant.expected.txt b/atddiff/test/default/backward_incompatible_variant.expected.txt index e955fd8..9b11357 100644 --- a/atddiff/test/default/backward_incompatible_variant.expected.txt +++ b/atddiff/test/default/backward_incompatible_variant.expected.txt @@ -1,4 +1,4 @@ -Backward incompatibility: +[2e6e3829] Backward incompatibility: File "backward_incompatible_variant_old.atd", line 1, characters 43-44: Case 'B' disappeared. The following types are affected: diff --git a/atddiff/test/default/changed_renamed.expected.txt b/atddiff/test/default/changed_renamed.expected.txt index 4198137..2544056 100644 --- a/atddiff/test/default/changed_renamed.expected.txt +++ b/atddiff/test/default/changed_renamed.expected.txt @@ -1,4 +1,4 @@ -Incompatibility in both directions: +[214e5646] Incompatibility in both directions: File "changed_renamed_old.atd", line 10, characters 22-26 File "changed_renamed_new.atd", line 10, characters 22-28: Type names 'int' and 'float' are not the same and may not be compatible. diff --git a/atddiff/test/default/dune b/atddiff/test/default/dune index 5ce778b..a8b118c 100644 --- a/atddiff/test/default/dune +++ b/atddiff/test/default/dune @@ -3,7 +3,7 @@ (rule (targets backward_incompatible_record_if_implicit_defaults.txt) (deps backward_incompatible_record_if_implicit_defaults_old.atd backward_incompatible_record_if_implicit_defaults_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -13,7 +13,7 @@ (rule (targets backward_incompatible_record.txt) (deps backward_incompatible_record_old.atd backward_incompatible_record_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -23,7 +23,7 @@ (rule (targets backward_incompatible_variant.txt) (deps backward_incompatible_variant_old.atd backward_incompatible_variant_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -33,7 +33,7 @@ (rule (targets changed_renamed.txt) (deps changed_renamed_old.atd changed_renamed_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -43,7 +43,7 @@ (rule (targets forward_incompatible_record_if_implicit_defaults.txt) (deps forward_incompatible_record_if_implicit_defaults_old.atd forward_incompatible_record_if_implicit_defaults_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -53,7 +53,7 @@ (rule (targets forward_incompatible_record.txt) (deps forward_incompatible_record_old.atd forward_incompatible_record_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -63,7 +63,7 @@ (rule (targets forward_incompatible_variant.txt) (deps forward_incompatible_variant_old.atd forward_incompatible_variant_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -73,7 +73,7 @@ (rule (targets ignored_type_parameters_are_ok.txt) (deps ignored_type_parameters_are_ok_old.atd ignored_type_parameters_are_ok_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -83,7 +83,7 @@ (rule (targets json_field_name_change.txt) (deps json_field_name_change_old.atd json_field_name_change_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -93,7 +93,7 @@ (rule (targets json_repr_change.txt) (deps json_repr_change_old.atd json_repr_change_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -103,7 +103,7 @@ (rule (targets json_variant_name_change.txt) (deps json_variant_name_change_old.atd json_variant_name_change_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -113,7 +113,7 @@ (rule (targets recursive.txt) (deps recursive_old.atd recursive_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -123,7 +123,7 @@ (rule (targets recursive_types.txt) (deps recursive_types_old.atd recursive_types_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -133,7 +133,7 @@ (rule (targets swapped_type_parameters.txt) (deps swapped_type_parameters_old.atd swapped_type_parameters_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -143,7 +143,7 @@ (rule (targets type_arity_change.txt) (deps type_arity_change_old.atd type_arity_change_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -153,7 +153,7 @@ (rule (targets type_name_change.txt) (deps type_name_change_old.atd type_name_change_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -163,7 +163,7 @@ (rule (targets unchanged.txt) (deps unchanged_old.atd unchanged_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) @@ -173,7 +173,7 @@ (rule (targets unchanged_renamed_nonroot_type.txt) (deps unchanged_renamed_nonroot_type_old.atd unchanged_renamed_nonroot_type_new.atd) - (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success))) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success ))) (rule (alias runtest) diff --git a/atddiff/test/default/forward_incompatible_record.expected.txt b/atddiff/test/default/forward_incompatible_record.expected.txt index 893bd50..59f76c1 100644 --- a/atddiff/test/default/forward_incompatible_record.expected.txt +++ b/atddiff/test/default/forward_incompatible_record.expected.txt @@ -1,10 +1,10 @@ -Forward incompatibility: +[381a0845] Forward incompatibility: File "forward_incompatible_record_old.atd", line 2, characters 2-20: Required field 'removed_field' disappeared. The following types are affected: forward_incompatible_record -Forward incompatibility: +[06b4c346] Forward incompatibility: File "forward_incompatible_record_old.atd", line 3, characters 2-23 File "forward_incompatible_record_new.atd", line 2, characters 2-31: Formerly required field 'becomes_optional' is now optional. diff --git a/atddiff/test/default/forward_incompatible_record_if_implicit_defaults.expected.txt b/atddiff/test/default/forward_incompatible_record_if_implicit_defaults.expected.txt index 3e9eadb..1af5bbd 100644 --- a/atddiff/test/default/forward_incompatible_record_if_implicit_defaults.expected.txt +++ b/atddiff/test/default/forward_incompatible_record_if_implicit_defaults.expected.txt @@ -1,4 +1,4 @@ -Possible forward incompatibility: +[2e39bd55] Possible forward incompatibility: File "forward_incompatible_record_if_implicit_defaults_old.atd", line 2, characters 2-23 File "forward_incompatible_record_if_implicit_defaults_new.atd", line 2, characters 2-24: Formerly required field 'becomes_optional' is now optional but has a default value. diff --git a/atddiff/test/default/forward_incompatible_variant.expected.txt b/atddiff/test/default/forward_incompatible_variant.expected.txt index 2f69a8e..96f700a 100644 --- a/atddiff/test/default/forward_incompatible_variant.expected.txt +++ b/atddiff/test/default/forward_incompatible_variant.expected.txt @@ -1,4 +1,4 @@ -Forward incompatibility: +[24b8e793] Forward incompatibility: File "forward_incompatible_variant_new.atd", line 1, characters 42-43: Case 'B' is new. The following types are affected: diff --git a/atddiff/test/default/json_field_name_change.expected.txt b/atddiff/test/default/json_field_name_change.expected.txt index 5375b25..7c1ed72 100644 --- a/atddiff/test/default/json_field_name_change.expected.txt +++ b/atddiff/test/default/json_field_name_change.expected.txt @@ -1,22 +1,22 @@ -Forward incompatibility: +[2befd23c] Forward incompatibility: File "json_field_name_change_old.atd", line 2, characters 2-26: Required field 'a!' disappeared. The following types are affected: with_field_renames -Forward incompatibility: +[1dad2f90] Forward incompatibility: File "json_field_name_change_old.atd", line 3, characters 2-9: Required field 'b' disappeared. The following types are affected: with_field_renames -Backward incompatibility: +[0948d4d7] Backward incompatibility: File "json_field_name_change_new.atd", line 2, characters 2-9: Required field 'a' is new. The following types are affected: with_field_renames -Backward incompatibility: +[2f0c378c] Backward incompatibility: File "json_field_name_change_new.atd", line 3, characters 2-27: Required field 'bee' is new. The following types are affected: diff --git a/atddiff/test/default/json_repr_change.expected.txt b/atddiff/test/default/json_repr_change.expected.txt index faa42ba..b0e1059 100644 --- a/atddiff/test/default/json_repr_change.expected.txt +++ b/atddiff/test/default/json_repr_change.expected.txt @@ -1,4 +1,4 @@ -Incompatibility in both directions: +[0667c515] Incompatibility in both directions: File "json_repr_change_old.atd", line 2, characters 21-40 File "json_repr_change_new.atd", line 2, characters 21-61: Incompatible kinds of types: list/array is now a map. diff --git a/atddiff/test/default/json_variant_name_change.expected.txt b/atddiff/test/default/json_variant_name_change.expected.txt index ad4a99f..06b0e31 100644 --- a/atddiff/test/default/json_variant_name_change.expected.txt +++ b/atddiff/test/default/json_variant_name_change.expected.txt @@ -1,46 +1,46 @@ -Backward incompatibility: +[142bf58a] Backward incompatibility: File "json_variant_name_change_old.atd", line 2, characters 4-5: Case 'A' disappeared. The following types are affected: with_constructor_renames -Backward incompatibility: +[148d17a6] Backward incompatibility: File "json_variant_name_change_old.atd", line 3, characters 4-12: Case 'B' disappeared. The following types are affected: with_constructor_renames -Backward incompatibility: +[3451ab10] Backward incompatibility: File "json_variant_name_change_old.atd", line 4, characters 4-23: Case 'cee' disappeared. The following types are affected: with_constructor_renames -Backward incompatibility: +[2ee9a5f5] Backward incompatibility: File "json_variant_name_change_old.atd", line 5, characters 4-30: Case 'dee' disappeared. The following types are affected: with_constructor_renames -Forward incompatibility: +[02dc524b] Forward incompatibility: File "json_variant_name_change_new.atd", line 2, characters 4-22: Case 'a!' is new. The following types are affected: with_constructor_renames -Forward incompatibility: +[3f5c23f4] Forward incompatibility: File "json_variant_name_change_new.atd", line 3, characters 4-29: Case 'b!' is new. The following types are affected: with_constructor_renames -Forward incompatibility: +[189456fd] Forward incompatibility: File "json_variant_name_change_new.atd", line 4, characters 4-5: Case 'C' is new. The following types are affected: with_constructor_renames -Forward incompatibility: +[1da9d4ce] Forward incompatibility: File "json_variant_name_change_new.atd", line 5, characters 4-12: Case 'D' is new. The following types are affected: diff --git a/atddiff/test/default/recursive.expected.txt b/atddiff/test/default/recursive.expected.txt index 0ec0696..aa4235c 100644 --- a/atddiff/test/default/recursive.expected.txt +++ b/atddiff/test/default/recursive.expected.txt @@ -1,4 +1,4 @@ -Forward incompatibility: +[0ad2992b] Forward incompatibility: File "recursive_new.atd", line 9, characters 52-53: Case 'B' is new. The following types are affected: diff --git a/atddiff/test/default/swapped_type_parameters.expected.txt b/atddiff/test/default/swapped_type_parameters.expected.txt index 264e800..4b06109 100644 --- a/atddiff/test/default/swapped_type_parameters.expected.txt +++ b/atddiff/test/default/swapped_type_parameters.expected.txt @@ -1,4 +1,4 @@ -Incompatibility in both directions: +[29041e94] Incompatibility in both directions: File "swapped_type_parameters_old.atd", line 3, characters 0-61 File "swapped_type_parameters_new.atd", line 3, characters 0-61: Incompatible type variables are being used. diff --git a/atddiff/test/default/type_arity_change.expected.txt b/atddiff/test/default/type_arity_change.expected.txt index 9fa1d0f..c06cf3c 100644 --- a/atddiff/test/default/type_arity_change.expected.txt +++ b/atddiff/test/default/type_arity_change.expected.txt @@ -1,4 +1,4 @@ -Incompatibility in both directions: +[319de7a2] Incompatibility in both directions: File "type_arity_change_old.atd", line 1, characters 0-48 File "type_arity_change_new.atd", line 1, characters 0-42: Incompatible type variables are being used. diff --git a/atddiff/test/default/type_name_change.expected.txt b/atddiff/test/default/type_name_change.expected.txt index 3980191..2f0a9d2 100644 --- a/atddiff/test/default/type_name_change.expected.txt +++ b/atddiff/test/default/type_name_change.expected.txt @@ -1,22 +1,22 @@ -Possible backward incompatibility: +[20f6af79] Possible backward incompatibility: File "type_name_change_old.atd", line 2, characters 0-33: The definition for type 'old_name_for_root_type' no longer exists. The following types are affected: old_name_for_root_type -Possible backward incompatibility: +[23b8d853] Possible backward incompatibility: File "type_name_change_old.atd", line 5, character 0 to line 7, character 1: The definition for type 'old_name_for_root_type_with_changes' no longer exists. The following types are affected: old_name_for_root_type_with_changes -Possible forward incompatibility: +[3ad32ed9] Possible forward incompatibility: File "type_name_change_new.atd", line 2, characters 0-33: There is a new type named 'new_name_for_root_type'. The following types are affected: new_name_for_root_type -Possible forward incompatibility: +[1b1d2804] Possible forward incompatibility: File "type_name_change_new.atd", line 5, character 0 to line 7, character 1: There is a new type named 'new_name_for_root_type_with_changes'. The following types are affected: diff --git a/atddiff/test/filter/filter.expected.txt b/atddiff/test/filter/filter.expected.txt index 9420112..f3da6e4 100644 --- a/atddiff/test/filter/filter.expected.txt +++ b/atddiff/test/filter/filter.expected.txt @@ -1,4 +1,4 @@ -Incompatibility in both directions: +[099be5a3] Incompatibility in both directions: File "filter_old.atd", line 7, characters 16-20 File "filter_new.atd", line 7, characters 16-23: Type names 'int' and 'string' are not the same and may not be compatible. diff --git a/atddiff/test/filter_backward/filter.expected.txt b/atddiff/test/filter_backward/filter.expected.txt index cf55878..d04a701 100644 --- a/atddiff/test/filter_backward/filter.expected.txt +++ b/atddiff/test/filter_backward/filter.expected.txt @@ -1,11 +1,11 @@ -Backward incompatibility: +[1c4525c6] Backward incompatibility: File "filter_new.atd", line 6, characters 2-18: Required field 'added_field' is new. The following types are affected: a b -Incompatibility in both directions: +[099be5a3] Incompatibility in both directions: File "filter_old.atd", line 7, characters 16-20 File "filter_new.atd", line 7, characters 16-23: Type names 'int' and 'string' are not the same and may not be compatible. diff --git a/atddiff/test/filter_forward/filter.expected.txt b/atddiff/test/filter_forward/filter.expected.txt index d2d468d..f86ea63 100644 --- a/atddiff/test/filter_forward/filter.expected.txt +++ b/atddiff/test/filter_forward/filter.expected.txt @@ -1,11 +1,11 @@ -Forward incompatibility: +[3d596659] Forward incompatibility: File "filter_old.atd", line 6, characters 2-20: Required field 'deleted_field' disappeared. The following types are affected: a b -Incompatibility in both directions: +[099be5a3] Incompatibility in both directions: File "filter_old.atd", line 7, characters 16-20 File "filter_new.atd", line 7, characters 16-23: Type names 'int' and 'string' are not the same and may not be compatible. diff --git a/atddiff/test/generate-dune-rules b/atddiff/test/generate-dune-rules index da2a00c..569e729 100755 --- a/atddiff/test/generate-dune-rules +++ b/atddiff/test/generate-dune-rules @@ -53,33 +53,41 @@ folders=" json_defaults_old json_defaults_new json_output + no_locations_text + no_locations_json " for folder in $folders; do - atddiff_options="--exit-success" + atddiff_options="--exit-success " case "$folder" in default) ;; filter) - atddiff_options="--exit-success --backward --forward --types a,b" + atddiff_options+="--backward --forward --types a,b" ;; filter_backward) - atddiff_options="--exit-success --backward" + atddiff_options+="--backward" ;; filter_forward) - atddiff_options="--exit-success --forward" + atddiff_options+="--forward" ;; json_defaults) - atddiff_options="--exit-success --json-defaults" + atddiff_options+="--json-defaults" ;; json_defaults_old) - atddiff_options="--exit-success --json-defaults-old" + atddiff_options+="--json-defaults-old" ;; json_defaults_new) - atddiff_options="--exit-success --json-defaults-new" + atddiff_options+="--json-defaults-new" ;; json_output) - atddiff_options="--exit-success --output-format json" + atddiff_options+="--output-format json" + ;; + no_locations_text) + atddiff_options+="--no-locations -f text" + ;; + no_locations_json) + atddiff_options+="--no-locations -f json" ;; *) echo "Error: Unknown atddiff command for test folder $folder" >&2 diff --git a/atddiff/test/json_defaults_new/backward_incompatible_record_if_implicit_defaults.expected.txt b/atddiff/test/json_defaults_new/backward_incompatible_record_if_implicit_defaults.expected.txt index 12d75a8..540b391 100644 --- a/atddiff/test/json_defaults_new/backward_incompatible_record_if_implicit_defaults.expected.txt +++ b/atddiff/test/json_defaults_new/backward_incompatible_record_if_implicit_defaults.expected.txt @@ -1,4 +1,4 @@ -Possible backward incompatibility: +[1963da34] Possible backward incompatibility: File "backward_incompatible_record_if_implicit_defaults_old.atd", line 2, characters 2-24 File "backward_incompatible_record_if_implicit_defaults_new.atd", line 2, characters 2-23: Newly required field 'becomes_required' was optional but had a default value. diff --git a/atddiff/test/json_defaults_old/forward_incompatible_record_if_implicit_defaults.expected.txt b/atddiff/test/json_defaults_old/forward_incompatible_record_if_implicit_defaults.expected.txt index 3e9eadb..1af5bbd 100644 --- a/atddiff/test/json_defaults_old/forward_incompatible_record_if_implicit_defaults.expected.txt +++ b/atddiff/test/json_defaults_old/forward_incompatible_record_if_implicit_defaults.expected.txt @@ -1,4 +1,4 @@ -Possible forward incompatibility: +[2e39bd55] Possible forward incompatibility: File "forward_incompatible_record_if_implicit_defaults_old.atd", line 2, characters 2-23 File "forward_incompatible_record_if_implicit_defaults_new.atd", line 2, characters 2-24: Formerly required field 'becomes_optional' is now optional but has a default value. diff --git a/atddiff/test/json_output/all_errors.expected.txt b/atddiff/test/json_output/all_errors.expected.txt index 24eca06..02977cb 100644 --- a/atddiff/test/json_output/all_errors.expected.txt +++ b/atddiff/test/json_output/all_errors.expected.txt @@ -1,281 +1,256 @@ { "findings": [ { - "finding": { - "direction": "Backward", - "kind": "Deleted_type", - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 1, "column": 0 }, - "end": { "path": "all_errors_old.atd", "line": 1, "column": 18 } - }, - "description": "The definition for type 'deleted' no longer exists." + "hash": "1b6b514f", + "direction": "Backward", + "kind": "Deleted_type", + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 1, "column": 0 }, + "end": { "path": "all_errors_old.atd", "line": 1, "column": 18 } }, + "description": "The definition for type 'deleted' no longer exists.", "affected_types": [ "deleted" ] }, { - "finding": { - "direction": "Forward", - "kind": [ "Missing_field", { "field_name": "deleted_field" } ], - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 4, "column": 2 }, - "end": { "path": "all_errors_old.atd", "line": 4, "column": 20 } - }, - "description": "Required field 'deleted_field' disappeared." + "hash": "158ae3ef", + "direction": "Forward", + "kind": [ "Missing_field", { "field_name": "deleted_field" } ], + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 4, "column": 2 }, + "end": { "path": "all_errors_old.atd", "line": 4, "column": 20 } }, + "description": "Required field 'deleted_field' disappeared.", "affected_types": [ "changed_record", "indirect_changes" ] }, { - "finding": { - "direction": "Forward", - "kind": [ "Missing_field", { "field_name": "renamed_field" } ], - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 9, "column": 2 }, - "end": { "path": "all_errors_old.atd", "line": 9, "column": 20 } - }, - "description": "Required field 'renamed_field' disappeared." + "hash": "15e4e116", + "direction": "Forward", + "kind": [ "Missing_field", { "field_name": "renamed_field" } ], + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 9, "column": 2 }, + "end": { "path": "all_errors_old.atd", "line": 9, "column": 20 } }, + "description": "Required field 'renamed_field' disappeared.", "affected_types": [ "changed_record", "indirect_changes" ] }, { - "finding": { - "direction": "Backward", - "kind": [ "Missing_variant", { "variant_name": "Deleted_case" } ], - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 13, "column": 4 }, - "end": { "path": "all_errors_old.atd", "line": 13, "column": 16 } - }, - "description": "Case 'Deleted_case' disappeared." + "hash": "31591865", + "direction": "Backward", + "kind": [ "Missing_variant", { "variant_name": "Deleted_case" } ], + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 13, "column": 4 }, + "end": { "path": "all_errors_old.atd", "line": 13, "column": 16 } }, + "description": "Case 'Deleted_case' disappeared.", "affected_types": [ "changed_variant", "indirect_changes" ] }, { - "finding": { - "direction": "Backward", - "kind": [ - "Missing_variant", { "variant_name": "Deleted_case_with_arg" } - ], - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 14, "column": 4 }, - "end": { "path": "all_errors_old.atd", "line": 14, "column": 35 } - }, - "description": "Case 'Deleted_case_with_arg' disappeared." + "hash": "3d0bf6cf", + "direction": "Backward", + "kind": [ + "Missing_variant", { "variant_name": "Deleted_case_with_arg" } + ], + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 14, "column": 4 }, + "end": { "path": "all_errors_old.atd", "line": 14, "column": 35 } }, + "description": "Case 'Deleted_case_with_arg' disappeared.", "affected_types": [ "changed_variant", "indirect_changes" ] }, { - "finding": { - "direction": "Forward", - "kind": "Deleted_type", - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 1, "column": 0 }, - "end": { "path": "all_errors_new.atd", "line": 1, "column": 18 } - }, - "description": "There is a new type named 'created'." + "hash": "3669ce41", + "direction": "Forward", + "kind": "Deleted_type", + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 1, "column": 0 }, + "end": { "path": "all_errors_new.atd", "line": 1, "column": 18 } }, + "description": "There is a new type named 'created'.", "affected_types": [ "created" ] }, { - "finding": { - "direction": "Backward", - "kind": [ "Missing_field", { "field_name": "new_field" } ], - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 4, "column": 2 }, - "end": { "path": "all_errors_new.atd", "line": 4, "column": 16 } - }, - "description": "Required field 'new_field' is new." + "hash": "29c893c7", + "direction": "Backward", + "kind": [ "Missing_field", { "field_name": "new_field" } ], + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 4, "column": 2 }, + "end": { "path": "all_errors_new.atd", "line": 4, "column": 16 } }, + "description": "Required field 'new_field' is new.", "affected_types": [ "changed_record", "indirect_changes" ] }, { - "finding": { - "direction": "Backward", - "kind": [ "Missing_field", { "field_name": "RENAMED_FIELD" } ], - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 9, "column": 2 }, - "end": { "path": "all_errors_new.atd", "line": 9, "column": 48 } - }, - "description": "Required field 'RENAMED_FIELD' is new." + "hash": "144944d4", + "direction": "Backward", + "kind": [ "Missing_field", { "field_name": "RENAMED_FIELD" } ], + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 9, "column": 2 }, + "end": { "path": "all_errors_new.atd", "line": 9, "column": 48 } }, + "description": "Required field 'RENAMED_FIELD' is new.", "affected_types": [ "changed_record", "indirect_changes" ] }, { - "finding": { - "direction": "Forward", - "kind": [ "Missing_variant", { "variant_name": "New_case" } ], - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 13, "column": 4 }, - "end": { "path": "all_errors_new.atd", "line": 13, "column": 12 } - }, - "description": "Case 'New_case' is new." + "hash": "2517ca31", + "direction": "Forward", + "kind": [ "Missing_variant", { "variant_name": "New_case" } ], + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 13, "column": 4 }, + "end": { "path": "all_errors_new.atd", "line": 13, "column": 12 } }, + "description": "Case 'New_case' is new.", "affected_types": [ "changed_variant", "indirect_changes" ] }, { - "finding": { - "direction": "Forward", - "kind": [ - "Missing_variant", { "variant_name": "New_case_with_arg" } - ], - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 14, "column": 4 }, - "end": { "path": "all_errors_new.atd", "line": 14, "column": 28 } - }, - "description": "Case 'New_case_with_arg' is new." + "hash": "17632fe1", + "direction": "Forward", + "kind": [ "Missing_variant", { "variant_name": "New_case_with_arg" } ], + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 14, "column": 4 }, + "end": { "path": "all_errors_new.atd", "line": 14, "column": 28 } }, + "description": "Case 'New_case_with_arg' is new.", "affected_types": [ "changed_variant", "indirect_changes" ] }, { - "finding": { - "direction": "Forward", - "kind": [ "Missing_field", { "field_name": "becomes_optional" } ], - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 5, "column": 2 }, - "end": { "path": "all_errors_old.atd", "line": 5, "column": 23 } - }, - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 5, "column": 2 }, - "end": { "path": "all_errors_new.atd", "line": 5, "column": 31 } - }, - "description": "Formerly required field 'becomes_optional' is now optional." + "hash": "3f56a184", + "direction": "Forward", + "kind": [ "Missing_field", { "field_name": "becomes_optional" } ], + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 5, "column": 2 }, + "end": { "path": "all_errors_old.atd", "line": 5, "column": 23 } }, + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 5, "column": 2 }, + "end": { "path": "all_errors_new.atd", "line": 5, "column": 31 } + }, + "description": "Formerly required field 'becomes_optional' is now optional.", "affected_types": [ "changed_record", "indirect_changes" ] }, { - "finding": { - "direction": "Forward", - "kind": [ - "Default_required", - { "field_name": "becomes_optional_with_default" } - ], - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 6, "column": 2 }, - "end": { "path": "all_errors_old.atd", "line": 6, "column": 36 } - }, - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 6, "column": 2 }, - "end": { "path": "all_errors_new.atd", "line": 6, "column": 37 } - }, - "description": "Formerly required field 'becomes_optional_with_default' is now optional but has a default value.\nYou must ensure that new implementations always populate the JSON field\nwith a value (using atdgen's option -j-defaults or equivalent) so that older\nimplementations can read newer data. If this is already the case, use\n'atddiff --json-defaults-new' to disable this warning." + "hash": "190e42a9", + "direction": "Forward", + "kind": [ + "Default_required", { "field_name": "becomes_optional_with_default" } + ], + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 6, "column": 2 }, + "end": { "path": "all_errors_old.atd", "line": 6, "column": 36 } + }, + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 6, "column": 2 }, + "end": { "path": "all_errors_new.atd", "line": 6, "column": 37 } }, + "description": "Formerly required field 'becomes_optional_with_default' is now optional but has a default value.\nYou must ensure that new implementations always populate the JSON field\nwith a value (using atdgen's option -j-defaults or equivalent) so that older\nimplementations can read newer data. If this is already the case, use\n'atddiff --json-defaults-new' to disable this warning.", "affected_types": [ "changed_record", "indirect_changes" ] }, { - "finding": { - "direction": "Backward", - "kind": [ "Missing_field", { "field_name": "becomes_required" } ], - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 7, "column": 2 }, - "end": { "path": "all_errors_old.atd", "line": 7, "column": 31 } - }, - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 7, "column": 2 }, - "end": { "path": "all_errors_new.atd", "line": 7, "column": 23 } - }, - "description": "Formerly optional field 'becomes_required' is now required." + "hash": "2483323d", + "direction": "Backward", + "kind": [ "Missing_field", { "field_name": "becomes_required" } ], + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 7, "column": 2 }, + "end": { "path": "all_errors_old.atd", "line": 7, "column": 31 } + }, + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 7, "column": 2 }, + "end": { "path": "all_errors_new.atd", "line": 7, "column": 23 } }, + "description": "Formerly optional field 'becomes_required' is now required.", "affected_types": [ "changed_record", "indirect_changes" ] }, { - "finding": { - "direction": "Backward", - "kind": [ - "Default_required", - { "field_name": "with_default_becomes_required" } - ], - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 8, "column": 2 }, - "end": { "path": "all_errors_old.atd", "line": 8, "column": 37 } - }, - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 8, "column": 2 }, - "end": { "path": "all_errors_new.atd", "line": 8, "column": 36 } - }, - "description": "Newly required field 'with_default_becomes_required' was optional but had a default value.\nIf old implementations in use always populate the JSON field\nwith a value (using atdgen's option -j-defaults or equivalent),\nthen there's no problem and you should use\n'atddiff --json-defaults-old' to disable this warning." + "hash": "029d6a0f", + "direction": "Backward", + "kind": [ + "Default_required", { "field_name": "with_default_becomes_required" } + ], + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 8, "column": 2 }, + "end": { "path": "all_errors_old.atd", "line": 8, "column": 37 } }, + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 8, "column": 2 }, + "end": { "path": "all_errors_new.atd", "line": 8, "column": 36 } + }, + "description": "Newly required field 'with_default_becomes_required' was optional but had a default value.\nIf old implementations in use always populate the JSON field\nwith a value (using atdgen's option -j-defaults or equivalent),\nthen there's no problem and you should use\n'atddiff --json-defaults-old' to disable this warning.", "affected_types": [ "changed_record", "indirect_changes" ] }, { - "finding": { - "direction": "Both", - "kind": [ - "Missing_variant_argument", { "variant_name": "Added_arg" } - ], - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 15, "column": 4 }, - "end": { "path": "all_errors_old.atd", "line": 15, "column": 13 } - }, - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 15, "column": 4 }, - "end": { "path": "all_errors_new.atd", "line": 15, "column": 22 } - }, - "description": "Case 'Added_arg' used to not have an argument." + "hash": "14e1a0cb", + "direction": "Both", + "kind": [ "Missing_variant_argument", { "variant_name": "Added_arg" } ], + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 15, "column": 4 }, + "end": { "path": "all_errors_old.atd", "line": 15, "column": 13 } + }, + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 15, "column": 4 }, + "end": { "path": "all_errors_new.atd", "line": 15, "column": 22 } }, + "description": "Case 'Added_arg' used to not have an argument.", "affected_types": [ "changed_variant", "indirect_changes" ] }, { - "finding": { - "direction": "Both", - "kind": [ - "Missing_variant_argument", { "variant_name": "Removed_arg" } - ], - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 16, "column": 4 }, - "end": { "path": "all_errors_old.atd", "line": 16, "column": 22 } - }, - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 16, "column": 4 }, - "end": { "path": "all_errors_new.atd", "line": 16, "column": 15 } - }, - "description": "Case 'Removed_arg' no longer has an argument." + "hash": "0e0c3d69", + "direction": "Both", + "kind": [ + "Missing_variant_argument", { "variant_name": "Removed_arg" } + ], + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 16, "column": 4 }, + "end": { "path": "all_errors_old.atd", "line": 16, "column": 22 } }, + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 16, "column": 4 }, + "end": { "path": "all_errors_new.atd", "line": 16, "column": 15 } + }, + "description": "Case 'Removed_arg' no longer has an argument.", "affected_types": [ "changed_variant", "indirect_changes" ] }, { - "finding": { - "direction": "Both", - "kind": "Incompatible_type", - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 17, "column": 18 }, - "end": { "path": "all_errors_old.atd", "line": 17, "column": 22 } - }, - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 17, "column": 18 }, - "end": { "path": "all_errors_new.atd", "line": 17, "column": 23 } - }, - "description": "Type names 'int' and 'bool' are not the same and may not be compatible." + "hash": "01efeb01", + "direction": "Both", + "kind": "Incompatible_type", + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 17, "column": 18 }, + "end": { "path": "all_errors_old.atd", "line": 17, "column": 22 } + }, + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 17, "column": 18 }, + "end": { "path": "all_errors_new.atd", "line": 17, "column": 23 } }, + "description": "Type names 'int' and 'bool' are not the same and may not be compatible.", "affected_types": [ "changed_variant", "indirect_changes" ] }, { - "finding": { - "direction": "Both", - "kind": "Incompatible_type", - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 26, "column": 20 }, - "end": { "path": "all_errors_old.atd", "line": 26, "column": 60 } - }, - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 26, "column": 20 }, - "end": { "path": "all_errors_new.atd", "line": 26, "column": 39 } - }, - "description": "Incompatible kinds of types: map is now a list/array." + "hash": "09d11702", + "direction": "Both", + "kind": "Incompatible_type", + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 26, "column": 20 }, + "end": { "path": "all_errors_old.atd", "line": 26, "column": 60 } }, + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 26, "column": 20 }, + "end": { "path": "all_errors_new.atd", "line": 26, "column": 39 } + }, + "description": "Incompatible kinds of types: map is now a list/array.", "affected_types": [ "changed_map1" ] }, { - "finding": { - "direction": "Both", - "kind": "Incompatible_type", - "location_old": { - "start": { "path": "all_errors_old.atd", "line": 27, "column": 20 }, - "end": { "path": "all_errors_old.atd", "line": 27, "column": 39 } - }, - "location_new": { - "start": { "path": "all_errors_new.atd", "line": 27, "column": 20 }, - "end": { "path": "all_errors_new.atd", "line": 27, "column": 60 } - }, - "description": "Incompatible kinds of types: list/array is now a map." + "hash": "2ddece43", + "direction": "Both", + "kind": "Incompatible_type", + "location_old": { + "start": { "path": "all_errors_old.atd", "line": 27, "column": 20 }, + "end": { "path": "all_errors_old.atd", "line": 27, "column": 39 } + }, + "location_new": { + "start": { "path": "all_errors_new.atd", "line": 27, "column": 20 }, + "end": { "path": "all_errors_new.atd", "line": 27, "column": 60 } }, + "description": "Incompatible kinds of types: list/array is now a map.", "affected_types": [ "changed_map2" ] } ] diff --git a/atddiff/test/no_locations_json/dune b/atddiff/test/no_locations_json/dune new file mode 100644 index 0000000..87367fc --- /dev/null +++ b/atddiff/test/no_locations_json/dune @@ -0,0 +1,32 @@ +; Generated by ./generate-dune-rules +; For adding tests, read the instructions in the Makefile. +(rule + (targets ordering.txt) + (deps ordering_old.atd ordering_new.atd) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success --no-locations -f json))) + +(rule + (alias runtest) + (deps ordering.txt) + (action (diff ordering.expected.txt ordering.txt))) + +(rule + (targets same_hash.txt) + (deps same_hash_old.atd same_hash_new.atd) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success --no-locations -f json))) + +(rule + (alias runtest) + (deps same_hash.txt) + (action (diff same_hash.expected.txt same_hash.txt))) + +(rule + (targets simple.txt) + (deps simple_old.atd simple_new.atd) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success --no-locations -f json))) + +(rule + (alias runtest) + (deps simple.txt) + (action (diff simple.expected.txt simple.txt))) + diff --git a/atddiff/test/no_locations_json/ordering.expected.txt b/atddiff/test/no_locations_json/ordering.expected.txt new file mode 100644 index 0000000..91e9d2a --- /dev/null +++ b/atddiff/test/no_locations_json/ordering.expected.txt @@ -0,0 +1,46 @@ +{ + "findings": [ + { + "hash": "0ba447bf", + "direction": "Both", + "kind": "Incompatible_type", + "description": "Incompatible kinds of types: list/array is now a string.", + "affected_types": [ "e" ] + }, + { + "hash": "1c2c4aae", + "direction": "Both", + "kind": "Incompatible_type", + "description": "Incompatible kinds of types: tuple is now a string.", + "affected_types": [ "c" ] + }, + { + "hash": "2182fd1f", + "direction": "Both", + "kind": "Incompatible_type", + "description": "Incompatible kinds of types: list/array is now a string.", + "affected_types": [ "b" ] + }, + { + "hash": "2e525f5c", + "direction": "Both", + "kind": "Incompatible_type", + "description": "Incompatible kinds of types: list/array is now a string.", + "affected_types": [ "f" ] + }, + { + "hash": "3b527108", + "direction": "Both", + "kind": "Incompatible_type", + "description": "Incompatible kinds of types: tuple is now a string.", + "affected_types": [ "d" ] + }, + { + "hash": "3f176ef7", + "direction": "Both", + "kind": "Incompatible_type", + "description": "Type names 'int' and 'string' are not the same and may not be compatible.", + "affected_types": [ "a" ] + } + ] +} diff --git a/atddiff/test/no_locations_json/ordering_new.atd b/atddiff/test/no_locations_json/ordering_new.atd new file mode 100644 index 0000000..e37b9df --- /dev/null +++ b/atddiff/test/no_locations_json/ordering_new.atd @@ -0,0 +1,6 @@ +type a = string +type b = string +type c = string +type d = string +type e = string +type f = string diff --git a/atddiff/test/no_locations_json/ordering_old.atd b/atddiff/test/no_locations_json/ordering_old.atd new file mode 100644 index 0000000..2b35677 --- /dev/null +++ b/atddiff/test/no_locations_json/ordering_old.atd @@ -0,0 +1,6 @@ +type a = int +type b = int list +type c = (b * b) +type d = (a * b) +type e = c list +type f = d list diff --git a/atddiff/test/no_locations_json/same_hash.expected.txt b/atddiff/test/no_locations_json/same_hash.expected.txt new file mode 100644 index 0000000..f71f730 --- /dev/null +++ b/atddiff/test/no_locations_json/same_hash.expected.txt @@ -0,0 +1,18 @@ +{ + "findings": [ + { + "hash": "177fee07", + "direction": "Both", + "kind": "Incompatible_type", + "description": "Type names 'int' and 'string' are not the same and may not be compatible.", + "affected_types": [ "t" ] + }, + { + "hash": "177fee07", + "direction": "Both", + "kind": "Incompatible_type", + "description": "Type names 'int' and 'string' are not the same and may not be compatible.", + "affected_types": [ "t" ] + } + ] +} diff --git a/atddiff/test/no_locations_json/same_hash_new.atd b/atddiff/test/no_locations_json/same_hash_new.atd new file mode 100644 index 0000000..86bd5b4 --- /dev/null +++ b/atddiff/test/no_locations_json/same_hash_new.atd @@ -0,0 +1 @@ +type t = (string * string) diff --git a/atddiff/test/no_locations_json/same_hash_old.atd b/atddiff/test/no_locations_json/same_hash_old.atd new file mode 100644 index 0000000..a26d4ce --- /dev/null +++ b/atddiff/test/no_locations_json/same_hash_old.atd @@ -0,0 +1,5 @@ +(* + This test produces two findings with the same hash ID +*) + +type t = (int * int) diff --git a/atddiff/test/no_locations_json/simple.expected.txt b/atddiff/test/no_locations_json/simple.expected.txt new file mode 100644 index 0000000..12db515 --- /dev/null +++ b/atddiff/test/no_locations_json/simple.expected.txt @@ -0,0 +1,11 @@ +{ + "findings": [ + { + "hash": "177fee07", + "direction": "Both", + "kind": "Incompatible_type", + "description": "Type names 'int' and 'string' are not the same and may not be compatible.", + "affected_types": [ "t" ] + } + ] +} diff --git a/atddiff/test/no_locations_json/simple_new.atd b/atddiff/test/no_locations_json/simple_new.atd new file mode 100644 index 0000000..c6a8e28 --- /dev/null +++ b/atddiff/test/no_locations_json/simple_new.atd @@ -0,0 +1 @@ +type t = string diff --git a/atddiff/test/no_locations_json/simple_old.atd b/atddiff/test/no_locations_json/simple_old.atd new file mode 100644 index 0000000..975adb5 --- /dev/null +++ b/atddiff/test/no_locations_json/simple_old.atd @@ -0,0 +1 @@ +type t = int diff --git a/atddiff/test/no_locations_text/dune b/atddiff/test/no_locations_text/dune new file mode 100644 index 0000000..27773c9 --- /dev/null +++ b/atddiff/test/no_locations_text/dune @@ -0,0 +1,32 @@ +; Generated by ./generate-dune-rules +; For adding tests, read the instructions in the Makefile. +(rule + (targets ordering.txt) + (deps ordering_old.atd ordering_new.atd) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success --no-locations -f text))) + +(rule + (alias runtest) + (deps ordering.txt) + (action (diff ordering.expected.txt ordering.txt))) + +(rule + (targets same_hash.txt) + (deps same_hash_old.atd same_hash_new.atd) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success --no-locations -f text))) + +(rule + (alias runtest) + (deps same_hash.txt) + (action (diff same_hash.expected.txt same_hash.txt))) + +(rule + (targets simple.txt) + (deps simple_old.atd simple_new.atd) + (action (run %{bin:atddiff} %{deps} -o %{targets} --exit-success --no-locations -f text))) + +(rule + (alias runtest) + (deps simple.txt) + (action (diff simple.expected.txt simple.txt))) + diff --git a/atddiff/test/no_locations_text/ordering.expected.txt b/atddiff/test/no_locations_text/ordering.expected.txt new file mode 100644 index 0000000..9cf28f6 --- /dev/null +++ b/atddiff/test/no_locations_text/ordering.expected.txt @@ -0,0 +1,30 @@ +[0ba447bf] Incompatibility in both directions: +Incompatible kinds of types: list/array is now a string. +The following types are affected: + e + +[1c2c4aae] Incompatibility in both directions: +Incompatible kinds of types: tuple is now a string. +The following types are affected: + c + +[2182fd1f] Incompatibility in both directions: +Incompatible kinds of types: list/array is now a string. +The following types are affected: + b + +[2e525f5c] Incompatibility in both directions: +Incompatible kinds of types: list/array is now a string. +The following types are affected: + f + +[3b527108] Incompatibility in both directions: +Incompatible kinds of types: tuple is now a string. +The following types are affected: + d + +[3f176ef7] Incompatibility in both directions: +Type names 'int' and 'string' are not the same and may not be compatible. +The following types are affected: + a + diff --git a/atddiff/test/no_locations_text/ordering_new.atd b/atddiff/test/no_locations_text/ordering_new.atd new file mode 100644 index 0000000..e37b9df --- /dev/null +++ b/atddiff/test/no_locations_text/ordering_new.atd @@ -0,0 +1,6 @@ +type a = string +type b = string +type c = string +type d = string +type e = string +type f = string diff --git a/atddiff/test/no_locations_text/ordering_old.atd b/atddiff/test/no_locations_text/ordering_old.atd new file mode 100644 index 0000000..2b35677 --- /dev/null +++ b/atddiff/test/no_locations_text/ordering_old.atd @@ -0,0 +1,6 @@ +type a = int +type b = int list +type c = (b * b) +type d = (a * b) +type e = c list +type f = d list diff --git a/atddiff/test/no_locations_text/same_hash.expected.txt b/atddiff/test/no_locations_text/same_hash.expected.txt new file mode 100644 index 0000000..a0fd66a --- /dev/null +++ b/atddiff/test/no_locations_text/same_hash.expected.txt @@ -0,0 +1,10 @@ +[177fee07] Incompatibility in both directions: +Type names 'int' and 'string' are not the same and may not be compatible. +The following types are affected: + t + +[177fee07] Incompatibility in both directions: +Type names 'int' and 'string' are not the same and may not be compatible. +The following types are affected: + t + diff --git a/atddiff/test/no_locations_text/same_hash_new.atd b/atddiff/test/no_locations_text/same_hash_new.atd new file mode 100644 index 0000000..86bd5b4 --- /dev/null +++ b/atddiff/test/no_locations_text/same_hash_new.atd @@ -0,0 +1 @@ +type t = (string * string) diff --git a/atddiff/test/no_locations_text/same_hash_old.atd b/atddiff/test/no_locations_text/same_hash_old.atd new file mode 100644 index 0000000..a26d4ce --- /dev/null +++ b/atddiff/test/no_locations_text/same_hash_old.atd @@ -0,0 +1,5 @@ +(* + This test produces two findings with the same hash ID +*) + +type t = (int * int) diff --git a/atddiff/test/no_locations_text/simple.expected.txt b/atddiff/test/no_locations_text/simple.expected.txt new file mode 100644 index 0000000..5dfaec8 --- /dev/null +++ b/atddiff/test/no_locations_text/simple.expected.txt @@ -0,0 +1,5 @@ +[177fee07] Incompatibility in both directions: +Type names 'int' and 'string' are not the same and may not be compatible. +The following types are affected: + t + diff --git a/atddiff/test/no_locations_text/simple_new.atd b/atddiff/test/no_locations_text/simple_new.atd new file mode 100644 index 0000000..c6a8e28 --- /dev/null +++ b/atddiff/test/no_locations_text/simple_new.atd @@ -0,0 +1 @@ +type t = string diff --git a/atddiff/test/no_locations_text/simple_old.atd b/atddiff/test/no_locations_text/simple_old.atd new file mode 100644 index 0000000..975adb5 --- /dev/null +++ b/atddiff/test/no_locations_text/simple_old.atd @@ -0,0 +1 @@ +type t = int diff --git a/atddiff/test/version/dune b/atddiff/test/version/dune new file mode 100644 index 0000000..b0de332 --- /dev/null +++ b/atddiff/test/version/dune @@ -0,0 +1,14 @@ +(rule + (targets version.txt) + (deps ) + (action + (with-stdout-to version.txt + (run %{bin:atddiff} --version) + ) + ) +) + +(rule + (alias runtest) + (deps version.txt) + (action (diff version.expected.txt version.txt))) diff --git a/atddiff/test/version/version.expected.txt b/atddiff/test/version/version.expected.txt new file mode 100644 index 0000000..68e69e4 --- /dev/null +++ b/atddiff/test/version/version.expected.txt @@ -0,0 +1 @@ +2.15.0 diff --git a/atdgen-codec-runtime.opam b/atdgen-codec-runtime.opam index 74f80ea..256c507 100644 --- a/atdgen-codec-runtime.opam +++ b/atdgen-codec-runtime.opam @@ -1,4 +1,4 @@ -version: "2.14.1" +version: "2.15.0" # This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: "Runtime for atdgen generated bucklescript converters" diff --git a/atdgen-runtime.opam b/atdgen-runtime.opam index 74bea00..e9ff352 100644 --- a/atdgen-runtime.opam +++ b/atdgen-runtime.opam @@ -1,4 +1,4 @@ -version: "2.14.1" +version: "2.15.0" # This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: "Runtime library for code generated by atdgen" diff --git a/atdgen-runtime/src/version.ml b/atdgen-runtime/src/version.ml index ab1c248..ba7c4aa 100644 --- a/atdgen-runtime/src/version.ml +++ b/atdgen-runtime/src/version.ml @@ -1,3 +1,3 @@ (* The version string is replaced by the actual version at release time by 'dune release'. *) -let version = "2.14.1" +let version = "2.15.0" diff --git a/atdgen.opam b/atdgen.opam index bbb6c45..a2f277a 100644 --- a/atdgen.opam +++ b/atdgen.opam @@ -1,4 +1,4 @@ -version: "2.14.1" +version: "2.15.0" # This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: diff --git a/atdgen/src/deprecated/version.ml b/atdgen/src/deprecated/version.ml index ab1c248..ba7c4aa 100644 --- a/atdgen/src/deprecated/version.ml +++ b/atdgen/src/deprecated/version.ml @@ -1,3 +1,3 @@ (* The version string is replaced by the actual version at release time by 'dune release'. *) -let version = "2.14.1" +let version = "2.15.0" diff --git a/atdgen/src/version.ml b/atdgen/src/version.ml index ab1c248..ba7c4aa 100644 --- a/atdgen/src/version.ml +++ b/atdgen/src/version.ml @@ -1,3 +1,3 @@ (* The version string is replaced by the actual version at release time by 'dune release'. *) -let version = "2.14.1" +let version = "2.15.0" @@ -1,4 +1,4 @@ -version: "2.14.1" +version: "2.15.0" # This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: "Java code generation for ATD" @@ -1,4 +1,4 @@ -version: "2.14.1" +version: "2.15.0" # This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: "Python/mypy code generation for ATD APIs" diff --git a/atdpy/src/lib/Version.ml b/atdpy/src/lib/Version.ml index ab1c248..ba7c4aa 100644 --- a/atdpy/src/lib/Version.ml +++ b/atdpy/src/lib/Version.ml @@ -1,3 +1,3 @@ (* The version string is replaced by the actual version at release time by 'dune release'. *) -let version = "2.14.1" +let version = "2.15.0" @@ -1,4 +1,4 @@ -version: "2.14.1" +version: "2.15.0" # This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: "ATD Code generator for Scala" @@ -1,4 +1,4 @@ -version: "2.14.1" +version: "2.15.0" # This file is generated by dune, edit dune-project instead opam-version: "2.0" synopsis: "TypeScript code generation for ATD APIs" diff --git a/atdts/src/lib/Version.ml b/atdts/src/lib/Version.ml index ab1c248..ba7c4aa 100644 --- a/atdts/src/lib/Version.ml +++ b/atdts/src/lib/Version.ml @@ -1,3 +1,3 @@ (* The version string is replaced by the actual version at release time by 'dune release'. *) -let version = "2.14.1" +let version = "2.15.0" diff --git a/dune-project b/dune-project index d6c1a69..5acec87 100644 --- a/dune-project +++ b/dune-project @@ -3,7 +3,7 @@ (implicit_transitive_deps false) (name atd) -(version 2.14.1) +(version 2.15.0) (license MIT) (maintainers |