lib/rubocop/formatter/disabled_config_formatter.rb
# encoding: utf-8 module RuboCop module Formatter # This formatter displays a YAML configuration file where all cops that # detected any offenses are configured to not detect the offense. class DisabledConfigFormatter < BaseFormatter HEADING = ['# This configuration was generated by', '# `%s`', "# on #{Time.now} using RuboCop version #{Version.version}.", '# The point is for the user to remove these configuration records', '# one by one as the offenses are removed from the code base.', '# Note that changes in the inspected code, or installation of new', '# versions of RuboCop, may require this file to be generated again.'] .join("\n") @config_to_allow_offenses = {} COPS = Cop::Cop.all.group_by(&:cop_name) class << self attr_accessor :config_to_allow_offenses end def file_started(_file, file_info) @exclude_limit_option = file_info.fetch(:cli_options, {})[:exclude_limit] @exclude_limit = ( @exclude_limit_option || RuboCop::Options::DEFAULT_MAXIMUM_EXCLUSION_ITEMS).to_i end def file_finished(file, offenses) @cops_with_offenses ||= Hash.new(0) @files_with_offenses ||= {} offenses.each do |o| @cops_with_offenses[o.cop_name] += 1 @files_with_offenses[o.cop_name] ||= [] @files_with_offenses[o.cop_name] << file end end def finished(_inspected_files) command = 'rubocop --auto-gen-config' if @exclude_limit_option command += format(' --exclude-limit %d', @exclude_limit_option.to_i) end output.puts HEADING % command # Syntax isn't a real cop and it can't be disabled. @cops_with_offenses.delete('Syntax') @cops_with_offenses.sort.each do |cop_name, offense_count| output.puts cfg = self.class.config_to_allow_offenses[cop_name] cfg ||= {} output_cop_comments(output, cfg, cop_name, offense_count) output_cop_config(output, cfg, cop_name) end puts "Created #{output.path}." puts "Run `rubocop --config #{output.path}`, or" puts "add inherit_from: #{output.path} in a .rubocop.yml file." end def output_cop_comments(output, cfg, cop_name, offense_count) output.puts "# Offense count: #{offense_count}" if COPS[cop_name] && COPS[cop_name].first.new.support_autocorrect? output.puts '# Cop supports --auto-correct.' end default_cfg = RuboCop::ConfigLoader.default_configuration[cop_name] return unless default_cfg params = default_cfg.keys - %w(Description StyleGuide Reference Enabled) - cfg.keys return if params.empty? output.puts "# Configuration parameters: #{params.join(', ')}." end def output_cop_config(output, cfg, cop_name) output.puts "#{cop_name}:" cfg.each do |key, value| value = value[0] if value.is_a?(Array) output.puts " #{key}: #{value}" end output_offending_files(output, cfg, cop_name) end def output_offending_files(output, cfg, cop_name) return unless cfg.empty? offending_files = @files_with_offenses[cop_name].uniq.sort if offending_files.count > @exclude_limit output.puts ' Enabled: false' else output_exclude_list(output, offending_files, cop_name) end end def output_exclude_list(output, offending_files, cop_name) require 'pathname' parent = Pathname.new(Dir.pwd) # Exclude properties in .rubocop_todo.yml override default ones, so in # order to retain the default excludes we must copy them. default_cfg = RuboCop::ConfigLoader.default_configuration[cop_name] default_excludes = default_cfg ? default_cfg['Exclude'] || [] : [] output.puts ' Exclude:' (default_excludes + offending_files).each do |file| file_path = Pathname.new(file) begin relative = file_path.relative_path_from(parent) output.puts " - '#{relative}'" rescue ArgumentError output.puts " - '#{file}'" end end rescue LoadError # Fallback to Enabled: false for Ruby < 1.9.3 output.puts ' Enabled: false' end end end end