diff --git a/src/state/gvMessages.ml b/src/state/gvMessages.ml index 8d1c4fa..d8f63c6 100644 --- a/src/state/gvMessages.ml +++ b/src/state/gvMessages.ml @@ -10,12 +10,20 @@ module Message = struct | Single p -> loc p | Group { pieces; _ } -> pieces |> List.filter_map loc |> List.enum |> Enum.get - let severity_to_bs_alert m = match m.severity with + let severity_to_hash m = m.severity |> Severity.hash + let severity_to_string m = match m.severity with + | Error -> "Error" + | Warning -> "Warning" + | Info -> "Info" + | Debug -> "Debug" + | Success -> "Success" + let severity_to_bootstrap_class (m:Severity.t) = match m with | Error -> "alert-danger" | Warning -> "alert-warning" | Info -> "alert-info" | Debug -> "alert-light" | Success -> "alert-success" + let message_to_bootstrap_class m = severity_to_bootstrap_class m.severity let to_string msg = let out = IO.output_string () in diff --git a/src/ui/panel/Panel.re b/src/ui/panel/Panel.re index b7ef9af..fb22bda 100644 --- a/src/ui/panel/Panel.re +++ b/src/ui/panel/Panel.re @@ -46,7 +46,7 @@ let make = (~state, ~dispatch) => {
{switch (current) { - | Some(Warnings) => + | Some(Warnings) => | Some(DeadCode) => | Some(Parameters) => | Some(Statistics) => diff --git a/src/ui/panel/WarningView.re b/src/ui/panel/WarningView.re index 8ae229c..bf98a5b 100644 --- a/src/ui/panel/WarningView.re +++ b/src/ui/panel/WarningView.re @@ -1,29 +1,126 @@ open Batteries; module Message = GvMessages.Message; +module Severity = Goblint_lib.Messages.Severity; [@react.component] -let make = (~warnings, ~dispatch) => { +let make = (~display: option(State.display), ~warnings, ~dispatch) => { + // List of all categories + let categories = + Stream.from(i => + if (i >= Severity.min && i < Severity.max) { + Severity.of_enum(i); + } else { + None; + } + ) + |> Stream.to_list; + + // Filter all warnings by category (and memoize to avoid recomputations) + let by_cat = + React.useMemo(() => + Array.init(List.length(categories), severity => + warnings + |> List.filter(m => { + Message.severity_to_hash(m) == Severity.min + severity + }) + ) + ); + let (categories_displayed, set_categories_displayed) = + React.useState(() => categories); + let (current_file_only, set_current_file_only) = React.useState(() => true); +
{if (List.length(warnings) == 0) { -

- {"No warnings found!" |> React.string} -

- } else { -
    - {warnings - |> List.map(w => (Message.to_string(w), Message.location(w), Message.severity_to_bs_alert(w))) - |> List.mapi((i, (text, loc, alert)) => { - let onClick = - loc - |> Option.map((loc, _) => - dispatch @@ `InspectLine(GvInspect.Line.of_location(loc)) - ); -
  • - {text |> React.string} -
  • ; - }) - |> React.list} -
- }} +

{"No warnings found!" |> React.string}

; + } else { + <> +
    +
  • + {categories + |> List.map(current_cat => + + ) + |> React.list} + // Seperate Button for filtering by the file currently selected. + +
  • +
+
    + {categories_displayed + |> List.map(Severity.hash) + |> List.map(Array.get(by_cat)) + |> List.flatten + |> List.filter(w => + if (!current_file_only) { + true; + } else { + Option.map_default( + fun + | GvDisplay.File(f) => { + let warning_path = + Message.location(w) + |> Option.map_default( + GvInspect.Line.of_location %> fst, + "", + ); + warning_path == f.path; + } + | _ => true, + true, + display, + ); + } + ) + |> List.map(w => + ( + Message.severity_to_string(w), + Message.to_string(w), + Message.location(w), + Message.message_to_bootstrap_class(w), + ) + ) + |> List.mapi((i, (title, text, loc, alert)) => { + let onClick = + loc + |> Option.map((loc, _) => + dispatch @@ + `InspectLine(GvInspect.Line.of_location(loc)) + ); +
  • +

    {title |> React.string}

    +

    {text |> React.string}

    +
  • ; + }) + |> React.list} +
+ ; + }}
; };