diff --git a/changelog/fix_rubocop_todo_link_injection_when.md b/changelog/fix_rubocop_todo_link_injection_when.md new file mode 100644 index 000000000000..5bc127914498 --- /dev/null +++ b/changelog/fix_rubocop_todo_link_injection_when.md @@ -0,0 +1 @@ +* [#9406](https://github.com/rubocop-hq/rubocop/pull/9406): Fix rubocop_todo link injection when YAML doc start sigil exists. ([@dduugg][]) diff --git a/lib/rubocop/cli/command/auto_genenerate_config.rb b/lib/rubocop/cli/command/auto_genenerate_config.rb index aa60e02043d6..f0586fec98dc 100644 --- a/lib/rubocop/cli/command/auto_genenerate_config.rb +++ b/lib/rubocop/cli/command/auto_genenerate_config.rb @@ -9,6 +9,7 @@ class AutoGenerateConfig < Base self.command_name = :auto_gen_config AUTO_GENERATED_FILE = '.rubocop_todo.yml' + YAML_OPTIONAL_DOC_START = /\A---(\s+#|\s*\z)/.freeze PHASE_1 = 'Phase 1 of 2: run Layout/LineLength cop' PHASE_2 = 'Phase 2 of 2: run all cops' @@ -130,10 +131,10 @@ def existing_configuration(config_file) end def write_config_file(file_name, file_string, rubocop_yml_contents) - File.open(file_name, 'w') do |f| - f.write "inherit_from:#{file_string}\n" - f.write "\n#{rubocop_yml_contents}" if /\S/.match?(rubocop_yml_contents) - end + lines = /\S/.match?(rubocop_yml_contents) ? rubocop_yml_contents.split("\n", -1) : [] + doc_start_index = lines.index { |line| YAML_OPTIONAL_DOC_START.match?(line) } || -1 + lines.insert(doc_start_index + 1, "inherit_from:#{file_string}\n") + File.open(file_name, 'w') { |f| f.write lines.join("\n") } end end end diff --git a/spec/rubocop/cli/cli_auto_gen_config_spec.rb b/spec/rubocop/cli/cli_auto_gen_config_spec.rb index 99c8903c5f8c..69fb3e91fd00 100644 --- a/spec/rubocop/cli/cli_auto_gen_config_spec.rb +++ b/spec/rubocop/cli/cli_auto_gen_config_spec.rb @@ -482,6 +482,43 @@ def fooBar; end end end + context 'when existing config file has a YAML document start header' do + it 'inserts `inherit_from` key after hearder' do + create_file('example1.rb', <<~RUBY) + def foo; end + RUBY + create_file('.rubocop.yml', <<~YAML) + # rubocop config file + --- # YAML document start + # The following cop does not support auto-correction. + Naming/MethodName: + Enabled: true + YAML + expect(cli.run(%w[--auto-gen-config])).to eq(0) + expect($stderr.string).to eq('') + expect(Dir['.*']).to include('.rubocop_todo.yml') + todo_contents = IO.read('.rubocop_todo.yml').lines[8..-1].join + expect(todo_contents).to eq(<<~YAML) + # Offense count: 1 + # Cop supports --auto-correct. + # Configuration parameters: EnforcedStyle. + # SupportedStyles: always, always_true, never + Style/FrozenStringLiteralComment: + Exclude: + - 'example1.rb' + YAML + expect(IO.read('.rubocop.yml')).to eq(<<~YAML) + # rubocop config file + --- # YAML document start + inherit_from: .rubocop_todo.yml + + # The following cop does not support auto-correction. + Naming/MethodName: + Enabled: true + YAML + end + end + context 'when working in a subdirectory' do it 'can generate a todo list' do create_file('dir/example1.rb', ['$x = 0 ',