Skip to content

Commit

Permalink
Add --regenerate-todo option to rebuild the todo file using the pre…
Browse files Browse the repository at this point in the history
…vious options, or acts as `--auto-gen-config` if there is no valid todo file.

Other options that affect `--auto-gen-config` are accepted, and can be passed in to override values in the previous todo.
eg. `--regenerate-todo --offense-counts` will supercede `--no-offense-counts`.
  • Loading branch information
dvandersluis committed Sep 24, 2020
1 parent 7375130 commit 32ec02c
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 1 deletion.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,10 +2,15 @@

## master (unreleased)

### New features

* [#8778](https://github.com/rubocop-hq/rubocop/pull/8778): Add command line option `--regenerate-todo`. ([@dvandersluis][])

### Bug fixes

* [#8774](https://github.com/rubocop-hq/rubocop/issues/8774): Fix a false positive for `Layout/ArrayAlignment` with parallel assignment. ([@dvandersluis][])


## 0.91.1 (2020-09-23)

### Bug fixes
Expand Down
3 changes: 2 additions & 1 deletion docs/modules/ROOT/pages/configuration.adoc
Expand Up @@ -586,7 +586,8 @@ behavior of a cop instead of disabling it completely.

Then you can start removing the entries in the generated
`.rubocop_todo.yml` file one by one as you work through all the offenses
in the code.
in the code. You can also regenerate your `.rubocop_todo.yml` using
the same options by running `rubocop --regenerate-todo`.

Another way of silencing offense reports, aside from configuration, is
through source code comments. These can be added manually or
Expand Down
3 changes: 3 additions & 0 deletions docs/modules/ROOT/pages/usage/basic_usage.adoc
Expand Up @@ -220,6 +220,9 @@ $ rubocop -h
| `-r/--require`
| Require Ruby file (see xref:extensions.adoc#loading-extensions[Loading Extensions]).

| `--regenerate-todo`
| Regenerate the TODO list using the same options as the last time it was generated with `--auto-gen-config` (generation options can be overridden).

| `--safe`
| Run only safe cops.

Expand Down
1 change: 1 addition & 0 deletions lib/rubocop.rb
Expand Up @@ -628,6 +628,7 @@
require_relative 'rubocop/cli/command/init_dotfile'
require_relative 'rubocop/cli/command/show_cops'
require_relative 'rubocop/cli/command/version'
require_relative 'rubocop/config_regeneration'
require_relative 'rubocop/options'
require_relative 'rubocop/remote_config'
require_relative 'rubocop/target_ruby'
Expand Down
33 changes: 33 additions & 0 deletions lib/rubocop/config_regeneration.rb
@@ -0,0 +1,33 @@
# frozen_string_literal: true

module RuboCop
# This class handles collecting the options for regenerating a TODO file.
# @api private
class ConfigRegeneration
AUTO_GENERATED_FILE = RuboCop::CLI::Command::AutoGenerateConfig::AUTO_GENERATED_FILE
COMMAND_REGEX = /(?<=`rubocop )(.*?)(?=`)/.freeze
DEFAULT_OPTIONS = { auto_gen_config: true }.freeze

# Get options from the comment in the TODO file, and parse them as options
def options
# If there's no existing TODO file, generate one
return DEFAULT_OPTIONS unless todo_exists?

match = generation_command.match(COMMAND_REGEX)
return DEFAULT_OPTIONS unless match

options = match[1].split(' ')
Options.new.parse(options).first
end

private

def todo_exists?
File.exist?(AUTO_GENERATED_FILE) && !File.empty?(AUTO_GENERATED_FILE)
end

def generation_command
File.foreach(AUTO_GENERATED_FILE).take(2).last
end
end
end
7 changes: 7 additions & 0 deletions lib/rubocop/options.rb
Expand Up @@ -114,6 +114,10 @@ def add_configuration_options(opts)
def add_auto_gen_options(opts)
option(opts, '--auto-gen-config')

option(opts, '--regenerate-todo') do
@options.replace(ConfigRegeneration.new.options.merge(@options))
end

option(opts, '--exclude-limit COUNT') do
@validator.validate_exclude_limit_option
end
Expand Down Expand Up @@ -418,6 +422,9 @@ module OptionsHelp
config: 'Specify configuration file.',
auto_gen_config: ['Generate a configuration file acting as a',
'TODO list.'],
regenerate_todo: ['Regenerate the TODO configuration file using',
'the last configuration. If there is no existing',
'TODO file, acts like --auto-gen-config.'],
offense_counts: ['Include offense counts in configuration',
'file generated by --auto-gen-config.',
'Default is true.'],
Expand Down
51 changes: 51 additions & 0 deletions spec/rubocop/config_regeneration_spec.rb
@@ -0,0 +1,51 @@
# frozen_string_literal: true

RSpec.describe RuboCop::ConfigRegeneration, :isolated_environment do
include FileHelper

subject(:config_regeneration) { described_class.new }

describe '#options' do
subject { config_regeneration.options }

context 'when no todo file exists' do
it { is_expected.to eq(auto_gen_config: true) }
end

context 'when there is a blank todo file' do
before { create_file('.rubocop_todo.yml', nil) }

it { is_expected.to eq(auto_gen_config: true) }
end

context 'when the todo file is malformed' do
before { create_file('.rubocop_todo.yml', 'todo') }

it { is_expected.to eq(auto_gen_config: true) }
end

context 'it parses options from the generation comment' do
let(:header) do
<<~HEADER
# This configuration was generated by
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 100 --no-offense-counts --no-auto-gen-timestamp`
# on 2020-06-12 17:42:47 UTC using RuboCop version 0.85.1.
HEADER
end

let(:expected_options) do
{
auto_gen_config: true,
auto_gen_only_exclude: true,
exclude_limit: '100',
offense_counts: false,
auto_gen_timestamp: false
}
end

before { create_file('.rubocop_todo.yml', header) }

it { is_expected.to eq(expected_options) }
end
end
end
72 changes: 72 additions & 0 deletions spec/rubocop/options_spec.rb
Expand Up @@ -52,6 +52,9 @@ def abs(path)
files are present in the directory tree.
--auto-gen-config Generate a configuration file acting as a
TODO list.
--regenerate-todo Regenerate the TODO configuration file using
the last configuration. If there is no existing
TODO file, acts like --auto-gen-config.
--exclude-limit COUNT Used together with --auto-gen-config to
set the limit for how many Exclude
properties to generate. Default is 15.
Expand Down Expand Up @@ -370,6 +373,75 @@ def abs(path)
end
end

describe '--regenerate-todo' do
subject(:parsed_options) { options.parse(command_line_options).first }

let(:config_regeneration) do
instance_double(RuboCop::ConfigRegeneration, options: todo_options)
end
let(:todo_options) { { auto_gen_config: true, exclude_limit: '100', offense_counts: false } }

before do
allow(RuboCop::ConfigRegeneration).to receive(:new).and_return(config_regeneration)
end

context 'when no other options are given' do
let(:command_line_options) { %w[--regenerate-todo] }
let(:expected_options) do
{
auto_gen_config: true,
exclude_limit: '100',
offense_counts: false,
regenerate_todo: true
}
end

it { is_expected.to eq(expected_options) }
end

context 'when todo options are overridden before --regenerate-todo' do
let(:command_line_options) { %w[--exclude-limit 50 --regenerate-todo] }
let(:expected_options) do
{
auto_gen_config: true,
exclude_limit: '50',
offense_counts: false,
regenerate_todo: true
}
end

it { is_expected.to eq(expected_options) }
end

context 'when todo options are overridden after --regenerate-todo' do
let(:command_line_options) { %w[--regenerate-todo --exclude-limit 50] }
let(:expected_options) do
{
auto_gen_config: true,
exclude_limit: '50',
offense_counts: false,
regenerate_todo: true
}
end

it { is_expected.to eq(expected_options) }
end

context 'when disabled options are overridden to be enabled' do
let(:command_line_options) { %w[--regenerate-todo --offense-counts] }
let(:expected_options) do
{
auto_gen_config: true,
exclude_limit: '100',
offense_counts: true,
regenerate_todo: true
}
end

it { is_expected.to eq(expected_options) }
end
end

describe '-s/--stdin' do
before do
$stdin = StringIO.new
Expand Down

0 comments on commit 32ec02c

Please sign in to comment.