diff --git a/bin/import.ml b/bin/import.ml index ee2fecf14a3..de113400199 100644 --- a/bin/import.ml +++ b/bin/import.ml @@ -6,6 +6,7 @@ include struct open Dune_engine module Build_config = Build_config module Build_system = Build_system + module Build_system_error = Build_system_error module Load_rules = Load_rules module Hooks = Hooks module Action_builder = Action_builder @@ -157,7 +158,7 @@ module Scheduler = struct | Failure -> let failure_message = match - Build_system.Error.( + Build_system_error.( Id.Map.cardinal (Set.current (Fiber.Svar.read Build_system.errors))) with | 1 -> Pp.textf "Had 1 error" diff --git a/src/dune_engine/build_system.ml b/src/dune_engine/build_system.ml index 11532a06062..ffdc270f25f 100644 --- a/src/dune_engine/build_system.ml +++ b/src/dune_engine/build_system.ml @@ -1,6 +1,7 @@ open Import open Memo.O module Action_builder = Action_builder0 +module Error = Build_system_error module Progress = struct type t = @@ -26,132 +27,6 @@ module Progress = struct ;; end -module Error = struct - module Id = Id.Make () - - type t = - | Exn of - { id : Id.t - ; exn : Exn_with_backtrace.t - } - | Diagnostic of - { id : Id.t - ; diagnostic : Compound_user_error.t - ; dir : Path.t option - ; promotion : Diff_promotion.Annot.t option - } - - module Event = struct - type nonrec t = - | Add of t - | Remove of t - end - - let of_exn (exn : Exn_with_backtrace.t) = - let exn = - match exn.exn with - | Memo.Error.E e -> { exn with exn = Memo.Error.get e } - | _ -> exn - in - match exn.exn with - | User_error.E main -> - let dir = User_message.Annots.find main.annots Process.with_directory_annot in - let promotion = User_message.Annots.find main.annots Diff_promotion.Annot.annot in - (match User_message.Annots.find main.annots Compound_user_error.annot with - | None -> - [ Diagnostic - { dir - ; id = Id.gen () - ; diagnostic = Compound_user_error.make ~main ~related:[] - ; promotion - } - ] - | Some diagnostics -> - List.map diagnostics ~f:(fun diagnostic -> - Diagnostic { id = Id.gen (); diagnostic; dir; promotion })) - | _ -> [ Exn { id = Id.gen (); exn } ] - ;; - - let promotion = function - | Exn _ -> None - | Diagnostic d -> d.promotion - ;; - - let id = function - | Exn d -> d.id - | Diagnostic d -> d.id - ;; - - let dir = function - | Exn _ -> None - | Diagnostic d -> d.dir - ;; - - let description = function - | Exn e -> `Exn e.exn - | Diagnostic d -> `Diagnostic d.diagnostic - ;; - - module For_tests = struct - let make ~description ~dir ~promotion () = - let id = Id.gen () in - match description with - | `Exn exn -> Exn { id; exn } - | `Diagnostic diagnostic -> Diagnostic { id; diagnostic; dir; promotion } - ;; - end - - module Set : sig - type error := t - - type nonrec t = private - { current : t Id.Map.t - ; stamp : int - ; last_event : Event.t option - } - - val add : t -> error -> t - val one_event_diff : prev:t -> next:t -> Event.t option - val equal : t -> t -> bool - val current : t -> error Id.Map.t - val empty : t - end = struct - type nonrec t = - { current : t Id.Map.t - ; stamp : int - ; last_event : Event.t option - } - - let add t error = - let current = Id.Map.set t.current (id error) error in - { current; stamp = t.stamp + 1; last_event = Some (Add error) } - ;; - - let equal t { current; stamp; last_event } = - Int.equal t.stamp stamp - && - match t.last_event, last_event with - | None, None -> - assert (Id.Map.is_empty t.current && Id.Map.is_empty current); - true (* only possible when both sets are empty *) - | Some x, Some y -> - (match x, y with - | Add x, Add y -> Id.equal (id x) (id y) - | Add _, _ -> false - | Remove x, Remove y -> Id.equal (id x) (id y) - | Remove _, _ -> false) - | Some _, None | None, Some _ -> false - ;; - - let one_event_diff ~prev ~next = - if prev.stamp + 1 = next.stamp then next.last_event else None - ;; - - let current t = t.current - let empty = { current = Id.Map.empty; stamp = 0; last_event = None } - end -end - module State = struct module Svar = Fiber.Svar diff --git a/src/dune_engine/build_system.mli b/src/dune_engine/build_system.mli index eca27f9df71..1a3dc81a0b4 100644 --- a/src/dune_engine/build_system.mli +++ b/src/dune_engine/build_system.mli @@ -81,65 +81,5 @@ end val state : State.t Fiber.Svar.t -(** Errors found when building targets. *) -module Error : sig - module Id : sig - type t - - module Map : Map.S with type key = t - - val compare : t -> t -> Ordering.t - val to_int : t -> int - val to_dyn : t -> Dyn.t - end - - type t - - val id : t -> Id.t - - (** the directory where the rule the error is originating from *) - val dir : t -> Path.t option - - (** The description of the error. Errors from build rules contain useful - metadata that are extracted into [`Diagnostic] *) - val description - : t - -> [ `Exn of Exn_with_backtrace.t | `Diagnostic of Compound_user_error.t ] - - val promotion : t -> Diff_promotion.Annot.t option - - module Event : sig - type nonrec t = - | Add of t - | Remove of t - end - - module Set : sig - type error := t - type t - - (** [one_event_diff ~prev ~next] returns the event that constructs [next] - from [prev] if [next] is in the successive "generation" of [prev] *) - val one_event_diff : prev:t -> next:t -> Event.t option - - val equal : t -> t -> bool - val current : t -> error Id.Map.t - val empty : t - end - - module For_tests : sig - (** Internal helpers for testing purposes. Do not use. *) - - (** Construct an [Error.t] *) - val make - : description: - [ `Exn of Exn_with_backtrace.t | `Diagnostic of Compound_user_error.t ] - -> dir:Path.t option - -> promotion:Diff_promotion.Annot.t option - -> unit - -> t - end -end - (** The current set of active errors. *) -val errors : Error.Set.t Fiber.Svar.t +val errors : Build_system_error.Set.t Fiber.Svar.t diff --git a/src/dune_engine/build_system_error.ml b/src/dune_engine/build_system_error.ml new file mode 100644 index 00000000000..f34f83398b4 --- /dev/null +++ b/src/dune_engine/build_system_error.ml @@ -0,0 +1,112 @@ +open Import +module Id = Id.Make () + +type t = + | Exn of + { id : Id.t + ; exn : Exn_with_backtrace.t + } + | Diagnostic of + { id : Id.t + ; diagnostic : Compound_user_error.t + ; dir : Path.t option + ; promotion : Diff_promotion.Annot.t option + } + +module Event = struct + type nonrec t = + | Add of t + | Remove of t +end + +let of_exn (exn : Exn_with_backtrace.t) = + let exn = + match exn.exn with + | Memo.Error.E e -> { exn with exn = Memo.Error.get e } + | _ -> exn + in + match exn.exn with + | User_error.E main -> + let dir = User_message.Annots.find main.annots Process.with_directory_annot in + let promotion = User_message.Annots.find main.annots Diff_promotion.Annot.annot in + (match User_message.Annots.find main.annots Compound_user_error.annot with + | None -> + [ Diagnostic + { dir + ; id = Id.gen () + ; diagnostic = Compound_user_error.make ~main ~related:[] + ; promotion + } + ] + | Some diagnostics -> + List.map diagnostics ~f:(fun diagnostic -> + Diagnostic { id = Id.gen (); diagnostic; dir; promotion })) + | _ -> [ Exn { id = Id.gen (); exn } ] +;; + +let promotion = function + | Exn _ -> None + | Diagnostic d -> d.promotion +;; + +let id = function + | Exn d -> d.id + | Diagnostic d -> d.id +;; + +let dir = function + | Exn _ -> None + | Diagnostic d -> d.dir +;; + +let description = function + | Exn e -> `Exn e.exn + | Diagnostic d -> `Diagnostic d.diagnostic +;; + +module Set = struct + type error = t + + type t = + { current : error Id.Map.t + ; stamp : int + ; last_event : Event.t option + } + + let add t error = + let current = Id.Map.set t.current (id error) error in + { current; stamp = t.stamp + 1; last_event = Some (Add error) } + ;; + + let equal t { current; stamp; last_event } = + Int.equal t.stamp stamp + && + match t.last_event, last_event with + | None, None -> + assert (Id.Map.is_empty t.current && Id.Map.is_empty current); + true (* only possible when both sets are empty *) + | Some x, Some y -> + (match x, y with + | Add x, Add y -> Id.equal (id x) (id y) + | Add _, _ -> false + | Remove x, Remove y -> Id.equal (id x) (id y) + | Remove _, _ -> false) + | Some _, None | None, Some _ -> false + ;; + + let one_event_diff ~prev ~next = + if prev.stamp + 1 = next.stamp then next.last_event else None + ;; + + let current t = t.current + let empty = { current = Id.Map.empty; stamp = 0; last_event = None } +end + +module For_tests = struct + let make ~description ~dir ~promotion () = + let id = Id.gen () in + match description with + | `Exn exn -> Exn { id; exn } + | `Diagnostic diagnostic -> Diagnostic { id; diagnostic; dir; promotion } + ;; +end diff --git a/src/dune_engine/build_system_error.mli b/src/dune_engine/build_system_error.mli new file mode 100644 index 00000000000..9ffafb837c3 --- /dev/null +++ b/src/dune_engine/build_system_error.mli @@ -0,0 +1,64 @@ +(** Errors found when building targets. *) + +open Import + +module Id : sig + type t + + module Map : Map.S with type key = t + + val compare : t -> t -> Ordering.t + val to_int : t -> int + val to_dyn : t -> Dyn.t +end + +type t + +(** Construct a list of errors from an exception. *) +val of_exn : Exn_with_backtrace.t -> t list + +val id : t -> Id.t + +(** the directory where the rule the error is originating from *) +val dir : t -> Path.t option + +(** The description of the error. Errors from build rules contain useful + metadata that are extracted into [`Diagnostic] *) +val description + : t + -> [ `Exn of Exn_with_backtrace.t | `Diagnostic of Compound_user_error.t ] + +val promotion : t -> Diff_promotion.Annot.t option + +module Event : sig + type nonrec t = + | Add of t + | Remove of t +end + +module Set : sig + type error := t + type t + + val add : t -> error -> t + + (** [one_event_diff ~prev ~next] returns the event that constructs [next] + from [prev] if [next] is in the successive "generation" of [prev] *) + val one_event_diff : prev:t -> next:t -> Event.t option + + val equal : t -> t -> bool + val current : t -> error Id.Map.t + val empty : t +end + +module For_tests : sig + (** Internal helpers for testing purposes. Do not use. *) + + (** Construct an [Error.t] *) + val make + : description:[ `Exn of Exn_with_backtrace.t | `Diagnostic of Compound_user_error.t ] + -> dir:Path.t option + -> promotion:Diff_promotion.Annot.t option + -> unit + -> t +end diff --git a/src/dune_engine/dune_engine.ml b/src/dune_engine/dune_engine.ml index 5203fa0a273..e40b7de3b65 100644 --- a/src/dune_engine/dune_engine.ml +++ b/src/dune_engine/dune_engine.ml @@ -18,6 +18,7 @@ module Target_promotion = Target_promotion module Build_context = Build_context module Build_config = Build_config module Build_system = Build_system +module Build_system_error = Build_system_error module Load_rules = Load_rules module Clflags = Clflags module Response_file = Response_file diff --git a/src/dune_rpc_impl/diagnostics.ml b/src/dune_rpc_impl/diagnostics.ml index 443259780ae..d828c2686e3 100644 --- a/src/dune_rpc_impl/diagnostics.ml +++ b/src/dune_rpc_impl/diagnostics.ml @@ -14,10 +14,10 @@ let absolutize_paths ~dir (loc : Loc.t) = |> Loc.to_lexbuf_loc ;; -let diagnostic_of_error : Build_system.Error.t -> Dune_rpc_private.Diagnostic.t = +let diagnostic_of_error : Build_system_error.t -> Dune_rpc_private.Diagnostic.t = fun m -> let dir = - let dir = Build_system.Error.dir m in + let dir = Build_system_error.dir m in Option.map dir ~f:Path.drop_optional_build_context_maybe_sandboxed in let make_loc loc = @@ -25,7 +25,7 @@ let diagnostic_of_error : Build_system.Error.t -> Dune_rpc_private.Diagnostic.t absolutize_paths ~dir loc in let message, related = - match Build_system.Error.description m with + match Build_system_error.description m with | `Exn e -> (* CR-someday jeremiedimino: Use [Report_error.get_user_message] here. *) User_message.make [ Pp.text (Printexc.to_string e.exn) ], [] @@ -34,10 +34,10 @@ let diagnostic_of_error : Build_system.Error.t -> Dune_rpc_private.Diagnostic.t let loc = Option.map message.loc ~f:make_loc in let make_message pars = Pp.map_tags (Pp.concat pars) ~f:(fun _ -> ()) in let id = - Build_system.Error.id m |> Build_system.Error.Id.to_int |> Diagnostic.Id.create + Build_system_error.id m |> Build_system_error.Id.to_int |> Diagnostic.Id.create in let promotion = - match Build_system.Error.promotion m with + match Build_system_error.promotion m with | None -> [] | Some { in_source; in_build } -> [ { Diagnostic.Promotion.in_source = @@ -63,7 +63,7 @@ let diagnostic_of_error : Build_system.Error.t -> Dune_rpc_private.Diagnostic.t } ;; -let diagnostic_event_of_error_event (e : Build_system.Error.Event.t) : Diagnostic.Event.t = +let diagnostic_event_of_error_event (e : Build_system_error.Event.t) : Diagnostic.Event.t = match e with | Remove e -> Remove (diagnostic_of_error e) | Add e -> Add (diagnostic_of_error e) diff --git a/src/dune_rpc_impl/diagnostics.mli b/src/dune_rpc_impl/diagnostics.mli index 38ba44b84ea..22782fdcb16 100644 --- a/src/dune_rpc_impl/diagnostics.mli +++ b/src/dune_rpc_impl/diagnostics.mli @@ -3,7 +3,7 @@ open Import val diagnostic_event_of_error_event - : Build_system.Error.Event.t + : Build_system_error.Event.t -> Dune_rpc.Diagnostic.Event.t -val diagnostic_of_error : Build_system.Error.t -> Dune_rpc_private.Diagnostic.t +val diagnostic_of_error : Build_system_error.t -> Dune_rpc_private.Diagnostic.t diff --git a/src/dune_rpc_impl/import.ml b/src/dune_rpc_impl/import.ml index 21390b978d6..61961a8153e 100644 --- a/src/dune_rpc_impl/import.ml +++ b/src/dune_rpc_impl/import.ml @@ -5,6 +5,7 @@ module Dune_rpc = Dune_rpc_private include struct open Dune_engine module Build_system = Build_system + module Build_system_error = Build_system_error module Scheduler = Scheduler module Running_jobs = Running_jobs end diff --git a/src/dune_rpc_impl/server.ml b/src/dune_rpc_impl/server.ml index 003965cf306..ac3148bb957 100644 --- a/src/dune_rpc_impl/server.ml +++ b/src/dune_rpc_impl/server.ml @@ -229,7 +229,7 @@ let handler (t : _ t Fdecl.t) action_runner_server handle : 'a Dune_rpc_server.H Handler.create ~on_terminate ~on_init ~version:Dune_rpc_private.Version.latest () in let () = - let module Error = Build_system.Error in + let module Error = Build_system_error in let diff ~last ~(now : Error.Set.t) = match last with | None -> @@ -386,8 +386,8 @@ let handler (t : _ t Fdecl.t) action_runner_server handle : 'a Dune_rpc_server.H let () = let f _ () = let errors = Fiber.Svar.read Build_system.errors in - Build_system.Error.Set.current errors - |> Build_system.Error.Id.Map.values + Build_system_error.Set.current errors + |> Build_system_error.Id.Map.values |> List.map ~f:Diagnostics.diagnostic_of_error |> Fiber.return in diff --git a/test/expect-tests/dune_rpc_impl/dune_rpc_impl_tests.ml b/test/expect-tests/dune_rpc_impl/dune_rpc_impl_tests.ml index 1d172662600..bd4c24105fe 100644 --- a/test/expect-tests/dune_rpc_impl/dune_rpc_impl_tests.ml +++ b/test/expect-tests/dune_rpc_impl/dune_rpc_impl_tests.ml @@ -14,7 +14,7 @@ let test ~dir ~f main = Dune_console.printf "---- Original ----"; f main; Dune_console.printf "------- RPC ------"; - Dune_engine.Build_system.Error.For_tests.make ~description ~dir ~promotion:None () + Dune_engine.Build_system_error.For_tests.make ~description ~dir ~promotion:None () |> Dune_rpc_impl.Diagnostics.For_tests.diagnostic_of_error |> Dune_rpc_private.Diagnostic.to_user_message |> f