zf

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

diff_summary.ex (5453B)


      1 defmodule Credo.CLI.Command.Diff.DiffSummary do
      2   @moduledoc false
      3 
      4   # This module is responsible for printing the summary at the end of the analysis.
      5 
      6   @category_wording [
      7     {:consistency, "consistency issue", "consistency issues"},
      8     {:warning, "warning", "warnings"},
      9     {:refactor, "refactoring opportunity", "refactoring opportunities"},
     10     {:readability, "code readability issue", "code readability issues"},
     11     {:design, "software design suggestion", "software design suggestions"}
     12   ]
     13   @cry_for_help "Please report incorrect results: https://github.com/rrrene/credo/issues"
     14 
     15   alias Credo.CLI.Output
     16   alias Credo.CLI.Output.UI
     17   alias Credo.Execution
     18 
     19   def print(
     20         _source_files,
     21         %Execution{format: "flycheck"},
     22         _time_load,
     23         _time_run
     24       ) do
     25     nil
     26   end
     27 
     28   def print(_source_files, %Execution{format: "oneline"}, _time_load, _time_run) do
     29     nil
     30   end
     31 
     32   def print(source_files, exec, time_load, time_run) do
     33     issues = Execution.get_issues(exec)
     34     source_file_count = exec |> Execution.get_source_files() |> Enum.count()
     35     checks_count = count_checks(exec)
     36 
     37     git_ref = Execution.get_assign(exec, "credo.diff.previous_git_ref")
     38 
     39     UI.puts()
     40     UI.puts([:faint, @cry_for_help])
     41     UI.puts()
     42 
     43     UI.puts(format_time_spent(checks_count, source_file_count, time_load, time_run))
     44     UI.puts()
     45 
     46     new_issues = Enum.filter(issues, &(&1.diff_marker == :new))
     47     fixed_issues = Enum.filter(issues, &(&1.diff_marker == :fixed))
     48     old_issues = Enum.filter(issues, &(&1.diff_marker == :old))
     49 
     50     UI.puts([
     51       "Changes between ",
     52       :faint,
     53       :cyan,
     54       git_ref,
     55       :reset,
     56       " and working dir:"
     57     ])
     58 
     59     UI.puts()
     60     UI.puts(summary_parts_new(source_files, new_issues))
     61     UI.puts(summary_parts_fixed(source_files, fixed_issues))
     62     UI.puts(summary_parts_old(source_files, old_issues))
     63     UI.puts()
     64 
     65     print_priority_hint(exec)
     66   end
     67 
     68   defp count_checks(exec) do
     69     {result, _only_matching, _ignore_matching} = Execution.checks(exec)
     70 
     71     Enum.count(result)
     72   end
     73 
     74   defp print_priority_hint(%Execution{min_priority: min_priority})
     75        when min_priority >= 0 do
     76     UI.puts([
     77       :faint,
     78       "Showing priority issues: ↑ ↗ →  (use `mix credo explain` to explain issues, `mix credo diff --help` for options)."
     79     ])
     80   end
     81 
     82   defp print_priority_hint(_) do
     83     UI.puts([
     84       :faint,
     85       "Use `mix credo explain` to explain issues, `mix credo diff --help` for options."
     86     ])
     87   end
     88 
     89   defp format_time_spent(check_count, source_file_count, time_load, time_run) do
     90     time_run = time_run |> div(10_000)
     91     time_load = time_load |> div(10_000)
     92 
     93     formatted_total = format_in_seconds(time_run + time_load)
     94 
     95     time_to_load = format_in_seconds(time_load)
     96     time_to_run = format_in_seconds(time_run)
     97 
     98     total_in_seconds =
     99       case formatted_total do
    100         "1.0" -> "1 second"
    101         value -> "#{value} seconds"
    102       end
    103 
    104     checks =
    105       if check_count == 1 do
    106         "1 check"
    107       else
    108         "#{check_count} checks"
    109       end
    110 
    111     source_files =
    112       if source_file_count == 1 do
    113         "1 file"
    114       else
    115         "#{source_file_count} files"
    116       end
    117 
    118     [
    119       :faint,
    120       "Analysis took #{total_in_seconds} ",
    121       "(#{time_to_load}s to load, #{time_to_run}s running #{checks} on #{source_files})"
    122     ]
    123   end
    124 
    125   defp format_in_seconds(t) do
    126     if t < 10 do
    127       "0.0#{t}"
    128     else
    129       t = div(t, 10)
    130       "#{div(t, 10)}.#{rem(t, 10)}"
    131     end
    132   end
    133 
    134   defp category_count(issues, category) do
    135     issues
    136     |> Enum.filter(&(&1.category == category))
    137     |> Enum.count()
    138   end
    139 
    140   defp summary_parts_new(_source_files, issues) do
    141     parts =
    142       @category_wording
    143       |> Enum.flat_map(&summary_part(&1, issues, "new "))
    144 
    145     parts =
    146       parts
    147       |> List.update_at(Enum.count(parts) - 1, fn last_part ->
    148         String.replace(last_part, ", ", "")
    149       end)
    150 
    151     parts =
    152       if Enum.empty?(parts) do
    153         "no issues"
    154       else
    155         parts
    156       end
    157 
    158     [
    159       :green,
    160       :bright,
    161       "+ ",
    162       :reset,
    163       :green,
    164       " added ",
    165       :reset,
    166       parts,
    167       ","
    168     ]
    169   end
    170 
    171   defp summary_parts_fixed(_source_files, issues) do
    172     parts =
    173       @category_wording
    174       |> Enum.flat_map(&summary_part(&1, issues))
    175 
    176     parts =
    177       parts
    178       |> List.update_at(Enum.count(parts) - 1, fn last_part ->
    179         String.replace(last_part, ", ", "")
    180       end)
    181 
    182     parts =
    183       if Enum.empty?(parts) do
    184         "no issues"
    185       else
    186         parts
    187       end
    188 
    189     [
    190       :faint,
    191       "✔ ",
    192       :reset,
    193       " fixed ",
    194       :faint,
    195       parts,
    196       ", and"
    197     ]
    198   end
    199 
    200   defp summary_parts_old(_source_files, issues) do
    201     parts =
    202       @category_wording
    203       |> Enum.flat_map(&summary_part(&1, issues))
    204       |> Enum.reject(&is_atom(&1))
    205 
    206     parts =
    207       parts
    208       |> List.update_at(Enum.count(parts) - 1, fn last_part ->
    209         String.replace(last_part, ", ", "")
    210       end)
    211 
    212     parts =
    213       if Enum.empty?(parts) do
    214         "no issues"
    215       else
    216         parts
    217       end
    218 
    219     [
    220       :faint,
    221       "~ ",
    222       " kept ",
    223       parts,
    224       "."
    225     ]
    226   end
    227 
    228   defp summary_part({category, singular, plural}, issues, qualifier \\ "") do
    229     color = Output.check_color(category)
    230 
    231     case category_count(issues, category) do
    232       0 -> []
    233       1 -> [color, "1 #{qualifier}#{singular}, "]
    234       x -> [color, "#{x} #{qualifier}#{plural}, "]
    235     end
    236   end
    237 end