# frozen_string_literal: true require "erb" require "rubycritic/commands/status_reporter" require "terminal-table" module Skunk module Command # Knows how to report status for stinky files class StatusReporter < RubyCritic::Command::StatusReporter attr_accessor :analysed_modules HEADINGS = %w[file skunk_score churn_times_cost churn cost coverage].freeze HEADINGS_WITHOUT_FILE = HEADINGS - %w[file] HEADINGS_WITHOUT_FILE_WIDTH = HEADINGS_WITHOUT_FILE.size * 17 # padding TEMPLATE = ERB.new(<<-TEMPL <%= _ttable %>\n SkunkScore Total: <%= total_skunk_score %> Modules Analysed: <%= analysed_modules_count %> SkunkScore Average: <%= skunk_score_average %> <% if worst %>Worst SkunkScore: <%= worst.skunk_score %> (<%= worst.pathname %>)<% end %> Generated with Skunk v<%= Skunk::VERSION %> TEMPL ) # Returns a status message with a table of all analysed_modules and # a skunk score average def update_status_message opts = table_options.merge(headings: HEADINGS, rows: table) _ttable = Terminal::Table.new(opts) @status_message = TEMPLATE.result(binding) end private def analysed_modules_count @analysed_modules_count ||= non_test_modules.count end def non_test_modules @non_test_modules ||= analysed_modules.reject do |a_module| module_path = a_module.pathname.dirname.to_s module_path.start_with?("test", "spec") || module_path.end_with?("test", "spec") end end def worst @worst ||= sorted_modules.first end def sorted_modules @sorted_modules ||= non_test_modules.sort_by(&:skunk_score).reverse! end def total_skunk_score @total_skunk_score ||= non_test_modules.sum(&:skunk_score) end def total_churn_times_cost non_test_modules.sum(&:churn_times_cost) end def skunk_score_average return 0 if analysed_modules_count.zero? (total_skunk_score.to_d / analysed_modules_count).to_f.round(2) end def table_options max = sorted_modules.max_by { |a_mod| a_mod.pathname.to_s.length } width = max.pathname.to_s.length + HEADINGS_WITHOUT_FILE_WIDTH { style: { width: width # rubocop:disable Style/HashSyntax } } end def table sorted_modules.map do |a_mod| [ a_mod.pathname, a_mod.skunk_score, a_mod.churn_times_cost, a_mod.churn, a_mod.cost.round(2), a_mod.coverage.round(2) ] end end end end end