gitlab-org--gitlab-foss/rubocop/formatter/graceful_formatter.rb

109 lines
3.2 KiB
Ruby

# frozen_string_literal: true
require 'rubocop'
module RuboCop
module Formatter
class GracefulFormatter < ::RuboCop::Formatter::ProgressFormatter
CONFIG_DETAILS_KEY = 'Details'
CONFIG_DETAILS_VALUE = 'grace period'
class << self
attr_accessor :active_offenses
end
def started(...)
super
self.class.active_offenses = 0
@silenced_offenses_for_files = {}
@config = RuboCop::ConfigStore.new.for_pwd
end
def file_finished(file, offenses)
silenced_offenses, active_offenses = offenses.partition { silenced?(_1) }
@silenced_offenses_for_files[file] = silenced_offenses if silenced_offenses.any?
super(file, active_offenses)
end
def finished(inspected_files)
# See the note below why are using this ivar in the first place.
unless defined?(@total_offense_count)
raise <<~MESSAGE
RuboCop has changed its internals and the instance variable
`@total_offense_count` is no longer defined but we were relying on it.
Please change the implementation.
See https://github.com/rubocop/rubocop/blob/65a757b0f/lib/rubocop/formatter/simple_text_formatter.rb#L24
MESSAGE
end
super
# Internally, RuboCop has no notion of "silenced offenses". We cannot
# override this meaning in a formatter that's why we track what we
# consider to be an active offense.
# This is needed for `adjusted_exit_status` method below.
self.class.active_offenses = @total_offense_count
report_silenced_offenses(inspected_files)
end
# We consider this run a success without any active offenses.
def self.adjusted_exit_status(status)
return status unless status == RuboCop::CLI::STATUS_OFFENSES
return RuboCop::CLI::STATUS_SUCCESS if active_offenses == 0
status
end
def self.grace_period?(cop_name, config)
details = config[CONFIG_DETAILS_KEY]
return false unless details
return true if details == CONFIG_DETAILS_VALUE
warn "#{cop_name}: Unhandled value #{details.inspect} for `Details` key."
false
end
def self.grace_period_key_value
"#{CONFIG_DETAILS_KEY}: #{CONFIG_DETAILS_VALUE}"
end
private
def silenced?(offense)
cop_config = @config.for_cop(offense.cop_name)
self.class.grace_period?(offense.cop_name, cop_config)
end
def report_silenced_offenses(inspected_files)
return if @silenced_offenses_for_files.empty?
output.puts
output.puts 'Silenced offenses:'
output.puts
@silenced_offenses_for_files.each do |file, offenses|
report_file(file, offenses)
end
silenced_offense_count = @silenced_offenses_for_files.values.sum(&:size)
silenced_text = colorize("#{silenced_offense_count} offenses", :yellow)
output.puts
output.puts "#{inspected_files.size} files inspected, #{silenced_text} silenced"
end
def report_file_as_mark(_offenses)
# Skip progress bar. No dots. No C/Ws.
end
end
end
end