diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b3d19712ea..ea6337fdfda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * [#8750](https://github.com/rubocop-hq/rubocop/pull/8750): Fix an incorrect auto-correct for `Style/MultilineWhenThen` when line break for multiple condidate values of `when` statement. ([@koic][]) * [#8754](https://github.com/rubocop-hq/rubocop/pull/8754): Fix an error for `Style/RandomWithOffset` when using a range with non-integer bounds. ([@eugeneius][]) * [#8756](https://github.com/rubocop-hq/rubocop/issues/8756): Fix an infinite loop error for `Layout/EmptyLinesAroundAccessModifier` with `Layout/EmptyLinesAroundBlockBody` when using access modifier with block argument. ([@koic][]) +* [#8372](https://github.com/rubocop-hq/rubocop/issues/8372): Fix `Lint/RedundantCopDisableDirective` autocorrection. ([@dvandersluis][]) ### Changes diff --git a/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb b/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb index eaa845713a6..956896ee3b2 100644 --- a/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +++ b/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb @@ -56,19 +56,29 @@ def on_new_investigation private + def previous_line_blank?(range) + processed_source.buffer.source_line(range.line - 1).blank? + end + def comment_range_with_surrounding_space(range) - # Eat the entire comment, the preceding space, and the preceding - # newline if there is one. - original_begin = range.begin_pos - range = range_with_surrounding_space(range: range, - side: :left, - newlines: true) - range_with_surrounding_space(range: range, - side: :right, - # Special for a comment that - # begins the file: remove - # the newline at the end. - newlines: original_begin.zero?) + if previous_line_blank?(range) + # When the previous line is blank, it should be retained + range_with_surrounding_space(range: range, side: :right) + else + # Eat the entire comment, the preceding space, and the preceding + # newline if there is one. + original_begin = range.begin_pos + range = range_with_surrounding_space(range: range, + side: :left, + newlines: true) + + range_with_surrounding_space(range: range, + side: :right, + # Special for a comment that + # begins the file: remove + # the newline at the end. + newlines: original_begin.zero?) + end end def directive_range_in_list(range, ranges) diff --git a/spec/rubocop/cop/lint/redundant_cop_disable_directive_spec.rb b/spec/rubocop/cop/lint/redundant_cop_disable_directive_spec.rb index 5cd45ddb745..7db7f286f1d 100644 --- a/spec/rubocop/cop/lint/redundant_cop_disable_directive_spec.rb +++ b/spec/rubocop/cop/lint/redundant_cop_disable_directive_spec.rb @@ -314,5 +314,157 @@ class One end end end + + context 'autocorrecting whitespace' do + context 'when the comment is the first line of the file' do + context 'followed by code' do + it 'removes the comment' do + expect_offense(<<~RUBY) + # rubocop:disable Metrics/MethodLength + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unnecessary disabling of `Metrics/MethodLength`. + def my_method + end + # rubocop:enable Metrics/MethodLength + RUBY + + expect_correction(<<~RUBY) + def my_method + end + # rubocop:enable Metrics/MethodLength + RUBY + end + end + + context 'followed by a newline' do + it 'removes the comment and newline' do + expect_offense(<<~RUBY) + # rubocop:disable Metrics/MethodLength + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unnecessary disabling of `Metrics/MethodLength`. + + def my_method + end + # rubocop:enable Metrics/MethodLength + RUBY + + expect_correction(<<~RUBY) + def my_method + end + # rubocop:enable Metrics/MethodLength + RUBY + end + end + + context 'followed by another comment' do + it 'removes the comment and newline' do + expect_offense(<<~RUBY) + # rubocop:disable Metrics/MethodLength + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unnecessary disabling of `Metrics/MethodLength`. + # @api private + def my_method + end + # rubocop:enable Metrics/MethodLength + RUBY + + expect_correction(<<~RUBY) + # @api private + def my_method + end + # rubocop:enable Metrics/MethodLength + RUBY + end + end + end + + context 'when there is only whitespace before the comment' do + it 'leaves the whitespace' do + expect_offense(<<~RUBY) + + # rubocop:disable Metrics/MethodLength + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unnecessary disabling of `Metrics/MethodLength`. + def my_method + end + # rubocop:enable Metrics/MethodLength + RUBY + + expect_correction(<<~RUBY) + + def my_method + end + # rubocop:enable Metrics/MethodLength + RUBY + end + end + + context 'when the comment is not the first line of the file' do + it 'preserves whitespace before the comment' do + expect_offense(<<~RUBY) + attr_reader :foo + + # rubocop:disable Metrics/MethodLength + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unnecessary disabling of `Metrics/MethodLength`. + def my_method + end + # rubocop:enable Metrics/MethodLength + RUBY + + expect_correction(<<~RUBY) + attr_reader :foo + + def my_method + end + # rubocop:enable Metrics/MethodLength + RUBY + end + end + + context 'nested inside a namespace' do + it 'preserves indentation' do + expect_offense(<<~RUBY) + module Foo + module Bar + # rubocop:disable Metrics/ClassLength + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unnecessary disabling of `Metrics/ClassLength`. + class Baz + end + # rubocop:enable Metrics/ClassLength + end + end + RUBY + + expect_correction(<<~RUBY) + module Foo + module Bar + class Baz + end + # rubocop:enable Metrics/ClassLength + end + end + RUBY + end + end + + context 'inline comment' do + it 'removes the comment and preceding whitespace' do + expect_offense(<<~RUBY) + module Foo + module Bar + class Baz # rubocop:disable Metrics/ClassLength + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Unnecessary disabling of `Metrics/ClassLength`. + end + end + end + RUBY + + expect_correction(<<~RUBY) + module Foo + module Bar + class Baz + end + end + end + RUBY + end + end + end end end