class RuboCop::CLI

logic.
The CLI is a class responsible of handling all the command line interface

def act_on_options

def act_on_options
  ConfigLoader.debug = @options[:debug]
  ConfigLoader.auto_gen_config = @options[:auto_gen_config]
  ConfigLoader.ignore_parent_exclusion = @options[:ignore_parent_exclusion]
  @config_store.options_config = @options[:config] if @options[:config]
  @config_store.force_default_config! if @options[:force_default_config]
  handle_exiting_options
  if @options[:color]
    # color output explicitly forced on
    Rainbow.enabled = true
  elsif @options[:color] == false
    # color output explicitly forced off
    Rainbow.enabled = false
  end
end

def apply_default_formatter

def apply_default_formatter
  # This must be done after the options have already been processed,
  # because they can affect how ConfigStore behaves
  @options[:formatters] ||= begin
    cfg = @config_store.for(Dir.pwd).for_all_cops
    formatter = cfg['DefaultFormatter'] || 'progress'
    [[formatter, @options[:output_path]]]
  end
  return unless @options[:auto_gen_config]
  @options[:formatters] << [Formatter::DisabledConfigFormatter,
                            ConfigLoader::AUTO_GENERATED_FILE]
end

def config_lines(cop)

def config_lines(cop)
  cnf = @config_store.for(Dir.pwd).for_cop(cop)
  cnf.to_yaml.lines.to_a.butfirst.map { |line| '  ' + line }
end

def cops_of_department(cops, department)

def cops_of_department(cops, department)
  cops.with_department(department).sort!
end

def display_error_summary(errors)

def display_error_summary(errors)
  return if errors.empty?
  warn Rainbow("\n#{pluralize(errors.size, 'error')} occurred:").red
  errors.each { |error| warn error }
  warn <<-WARNING.strip_indent
    Errors are usually caused by RuboCop bugs.
    Please, report your problems to RuboCop's issue tracker.
    Mention the following information in the issue report:
    #{RuboCop::Version.version(true)}
  WARNING
end

def display_warning_summary(warnings)

def display_warning_summary(warnings)
  return if warnings.empty?
  warn Rainbow("\n#{pluralize(warnings.size, 'warning')}:").yellow
  warnings.each { |warning| warn warning }
end

def execute_runner(paths)

def execute_runner(paths)
  runner = Runner.new(@options, @config_store)
  trap_interrupt(runner)
  all_passed = runner.run(paths)
  display_warning_summary(runner.warnings)
  display_error_summary(runner.errors)
  maybe_print_corrected_source
  all_passed && !runner.aborting? && runner.errors.empty? ? 0 : 1
end

def execute_runners(paths)

def execute_runners(paths)
  if @options[:auto_gen_config]
    reset_config_and_auto_gen_file
    line_length_contents =
      if max_line_length(@config_store.for(Dir.pwd)) ==
         max_line_length(ConfigLoader.default_configuration)
        run_line_length_cop_auto_gen_config(paths)
      else
        puts Rainbow(SKIPPED_PHASE_1).yellow
        ''
      end
    run_all_cops_auto_gen_config(line_length_contents, paths)
  else
    execute_runner(paths)
  end
end

def handle_exiting_options

def handle_exiting_options
  return unless Options::EXITING_OPTIONS.any? { |o| @options.key? o }
  puts RuboCop::Version.version(false) if @options[:version]
  puts RuboCop::Version.version(true) if @options[:verbose_version]
  print_available_cops if @options[:show_cops]
  raise Finished
end

def initialize

def initialize
  @options = {}
  @config_store = ConfigStore.new
end

def max_line_length(config)

def max_line_length(config)
  config.for_cop('Metrics/LineLength')['Max']
end

def maybe_print_corrected_source

def maybe_print_corrected_source
  # If we are asked to autocorrect source code read from stdin, the only
  # reasonable place to write it is to stdout
  # Unfortunately, we also write other information to stdout
  # So a delimiter is needed for tools to easily identify where the
  # autocorrected source begins
  return unless @options[:stdin] && @options[:auto_correct]
  puts '=' * 20
  print @options[:stdin]
end

def print_available_cops

def print_available_cops
  # Load the configs so the require()s are done for custom cops
  @config_store.for(Dir.pwd)
  registry = Cop::Cop.registry
  show_all = @options[:show_cops].empty?
  if show_all
    puts "# Available cops (#{registry.length}) + config for #{Dir.pwd}: "
  end
  registry.departments.sort!.each do |department|
    print_cops_of_department(registry, department, show_all)
  end
end

def print_cop_details(cops)

def print_cop_details(cops)
  cops.each do |cop|
    puts '# Supports --auto-correct' if cop.new.support_autocorrect?
    puts "#{cop.cop_name}:"
    puts config_lines(cop)
    puts
  end
end

def print_cops_of_department(registry, department, show_all)

def print_cops_of_department(registry, department, show_all)
  selected_cops = if show_all
                    cops_of_department(registry, department)
                  else
                    selected_cops_of_department(registry, department)
                  end
  puts "# Department '#{department}' (#{selected_cops.length}):" if show_all
  print_cop_details(selected_cops)
end

def reset_config_and_auto_gen_file

def reset_config_and_auto_gen_file
  @config_store = ConfigStore.new
  File.open(ConfigLoader::AUTO_GENERATED_FILE, 'w') {}
  ConfigLoader.add_inheritance_from_auto_generated_file
end

def run(args = ARGV)

Returns:
  • (Integer) - UNIX exit code

Parameters:
  • args (Array) -- command line arguments

Other tags:
    Api: - public
def run(args = ARGV)
  @options, paths = Options.new.parse(args)
  validate_options_vs_config
  act_on_options
  apply_default_formatter
  execute_runners(paths)
rescue RuboCop::Error => e
  warn Rainbow("Error: #{e.message}").red
  return 2
rescue Finished
  return 0
rescue IncorrectCopNameError => e
  warn e.message
  return 2
rescue StandardError, SyntaxError, LoadError => e
  warn e.message
  warn e.backtrace
  return 2
end

def run_all_cops_auto_gen_config(line_length_contents, paths)

def run_all_cops_auto_gen_config(line_length_contents, paths)
  puts Rainbow('Phase 2 of 2: run all cops').yellow
  result = execute_runner(paths)
  # This run was made with the current maximum length allowed, so append
  # the saved setting for LineLength.
  File.open(ConfigLoader::AUTO_GENERATED_FILE, 'a') do |f|
    f.write(line_length_contents)
  end
  result
end

def run_line_length_cop_auto_gen_config(paths)

on Metrics/LineLength:Max get the correct value for that parameter.
Do an initial run with only Metrics/LineLength so that cops that depend
def run_line_length_cop_auto_gen_config(paths)
  puts Rainbow('Phase 1 of 2: run Metrics/LineLength cop').yellow
  @options[:only] = ['Metrics/LineLength']
  execute_runner(paths)
  @options.delete(:only)
  @config_store = ConfigStore.new
  # Save the todo configuration of the LineLength cop.
  IO.read(ConfigLoader::AUTO_GENERATED_FILE)
    .lines
    .drop_while { |line| line.start_with?('#') }
    .join
end

def selected_cops_of_department(cops, department)

def selected_cops_of_department(cops, department)
  cops_of_department(cops, department).select do |cop|
    @options[:show_cops].include?(cop.cop_name)
  end
end

def trap_interrupt(runner)

def trap_interrupt(runner)
  Signal.trap('INT') do
    exit!(1) if runner.aborting?
    runner.abort
    warn
    warn 'Exiting... Interrupt again to exit immediately.'
  end
end

def validate_options_vs_config

def validate_options_vs_config
  if @options[:parallel] &&
     !@config_store.for(Dir.pwd).for_all_cops['UseCache']
    raise ArgumentError, '-P/--parallel uses caching to speed up ' \
                         'execution, so combining with AllCops: ' \
                         'UseCache: false is not allowed.'
  end
end