zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

formatter.ex (4106B)


      1 defmodule Dialyxir.Formatter do
      2   @moduledoc """
      3   Elixir-friendly dialyzer formatter.
      4 
      5   Wrapper around normal Dialyzer warning messages that provides
      6   example output for error messages.
      7   """
      8   import Dialyxir.Output, only: [info: 1]
      9 
     10   alias Dialyxir.FilterMap
     11 
     12   @type warning() :: {tag :: term(), {file :: Path.t(), line :: pos_integer()}, {atom(), list()}}
     13 
     14   @type t() :: module()
     15 
     16   @callback format(warning()) :: String.t()
     17 
     18   def formatted_time(duration_us) do
     19     minutes = div(duration_us, 60_000_000)
     20     seconds = (rem(duration_us, 60_000_000) / 1_000_000) |> Float.round(2)
     21     "done in #{minutes}m#{seconds}s"
     22   end
     23 
     24   @spec format_and_filter([tuple], module, Keyword.t(), t()) :: tuple
     25   def format_and_filter(warnings, filterer, filter_map_args, formatter) do
     26     filter_map = filterer.filter_map(filter_map_args)
     27 
     28     {filtered_warnings, filter_map} = filter_warnings(warnings, filterer, filter_map)
     29 
     30     formatted_warnings =
     31       filtered_warnings
     32       |> filter_legacy_warnings(filterer)
     33       |> Enum.map(&formatter.format/1)
     34       |> Enum.uniq()
     35 
     36     show_count_skipped(warnings, formatted_warnings, filter_map)
     37     formatted_unnecessary_skips = format_unnecessary_skips(filter_map)
     38 
     39     result(formatted_warnings, filter_map, formatted_unnecessary_skips)
     40   end
     41 
     42   defp result(formatted_warnings, filter_map, formatted_unnecessary_skips) do
     43     cond do
     44       FilterMap.unused_filters?(filter_map) && filter_map.unused_filters_as_errors? ->
     45         {:error, formatted_warnings, {:unused_filters_present, formatted_unnecessary_skips}}
     46 
     47       FilterMap.unused_filters?(filter_map) ->
     48         {:warn, formatted_warnings, {:unused_filters_present, formatted_unnecessary_skips}}
     49 
     50       true ->
     51         {:ok, formatted_warnings, :no_unused_filters}
     52     end
     53   end
     54 
     55   defp show_count_skipped(warnings, filtered_warnings, filter_map) do
     56     warnings_count = Enum.count(warnings)
     57     filtered_warnings_count = Enum.count(filtered_warnings)
     58     skipped_count = warnings_count - filtered_warnings_count
     59     unnecessary_skips_count = count_unnecessary_skips(filter_map)
     60 
     61     info(
     62       "Total errors: #{warnings_count}, Skipped: #{skipped_count}, " <>
     63         "Unnecessary Skips: #{unnecessary_skips_count}"
     64     )
     65 
     66     :ok
     67   end
     68 
     69   defp format_unnecessary_skips(filter_map = %FilterMap{list_unused_filters?: true}) do
     70     unused_filters = FilterMap.unused_filters(filter_map)
     71 
     72     if Enum.empty?(unused_filters) do
     73       ""
     74     else
     75       unused_filters = Enum.map_join(unused_filters, "\n", &inspect/1)
     76       "Unused filters:\n#{unused_filters}"
     77     end
     78   end
     79 
     80   defp format_unnecessary_skips(_) do
     81     ""
     82   end
     83 
     84   defp count_unnecessary_skips(filter_map) do
     85     filter_map.counters
     86     |> Enum.filter(&FilterMap.unused?/1)
     87     |> Enum.count()
     88   end
     89 
     90   defp filter_warnings(warnings, filterer, filter_map) do
     91     {warnings, filter_map} =
     92       Enum.map_reduce(warnings, filter_map, &filter_warning(filterer, &1, &2))
     93 
     94     warnings = Enum.reject(warnings, &is_nil/1)
     95     {warnings, filter_map}
     96   end
     97 
     98   defp filter_warning(filterer, warning = {_, {file, line}, {warning_type, _}}, filter_map) do
     99     if Map.has_key?(Dialyxir.Warnings.warnings(), warning_type) do
    100       {skip?, matching_filters} =
    101         try do
    102           filterer.filter_warning?(
    103             {to_string(file), warning_type, line, Dialyxir.Formatter.Short.format(warning)},
    104             filter_map
    105           )
    106         rescue
    107           _ ->
    108             {false, []}
    109         catch
    110           _ ->
    111             {false, []}
    112         end
    113 
    114       filter_map =
    115         Enum.reduce(matching_filters, filter_map, fn filter, filter_map ->
    116           FilterMap.inc(filter_map, filter)
    117         end)
    118 
    119       if skip? do
    120         {nil, filter_map}
    121       else
    122         {warning, filter_map}
    123       end
    124     else
    125       {warning, filter_map}
    126     end
    127   end
    128 
    129   defp filter_legacy_warnings(warnings, filterer) do
    130     Enum.reject(warnings, fn warning ->
    131       formatted_warnings =
    132         warning
    133         |> Dialyxir.Formatter.Dialyzer.format()
    134         |> List.wrap()
    135 
    136       Enum.empty?(filterer.filter_legacy_warnings(formatted_warnings))
    137     end)
    138   end
    139 end