From cfdb0a1e67f1d29cee79e8aa09c900239fbb4a6a Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Tue, 6 Jul 2021 01:43:33 +0900 Subject: [PATCH] [Fix #9902] Fix an incorrect auto-correct for `Style/BlockDelimiters` Fixes #9902 This PR fixes an incorrect auto-correct for `Style/BlockDelimiters` when there is a comment after the closing brace. It prevents `Style/CommentedKeyword` from removing source code comment after `end` keyword. --- .rubocop_todo.yml | 2 +- ..._autocorrect_for_style_block_delimiters.md | 1 + lib/rubocop/cop/style/block_delimiters.rb | 15 ++++++++++ spec/rubocop/cli/autocorrect_spec.rb | 22 ++++++++++++++ .../cop/style/block_delimiters_spec.rb | 29 +++++++++++++++++++ 5 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 changelog/fix_incorrect_autocorrect_for_style_block_delimiters.md diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index ca611c6366b..86dca796768 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -13,7 +13,7 @@ InternalAffairs/NodeDestructuring: # Offense count: 49 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 186 + Max: 196 # Offense count: 228 # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods. diff --git a/changelog/fix_incorrect_autocorrect_for_style_block_delimiters.md b/changelog/fix_incorrect_autocorrect_for_style_block_delimiters.md new file mode 100644 index 00000000000..bc5310cf89d --- /dev/null +++ b/changelog/fix_incorrect_autocorrect_for_style_block_delimiters.md @@ -0,0 +1 @@ +* [#9902](https://github.com/rubocop/rubocop/issues/9902): Fix an incorrect auto-correct for `Style/BlockDelimiters` when there is a comment after the closing brace. ([@koic][]) diff --git a/lib/rubocop/cop/style/block_delimiters.rb b/lib/rubocop/cop/style/block_delimiters.rb index d8b80988a95..42251584dd8 100644 --- a/lib/rubocop/cop/style/block_delimiters.rb +++ b/lib/rubocop/cop/style/block_delimiters.rb @@ -135,6 +135,7 @@ module Style class BlockDelimiters < Base include ConfigurableEnforcedStyle include IgnoredMethods + include RangeHelp extend AutoCorrector ALWAYS_BRACES_MESSAGE = 'Prefer `{...}` over `do...end` for blocks.' @@ -231,6 +232,11 @@ def replace_braces_with_do_end(corrector, loc) corrector.insert_before(e, ' ') unless whitespace_before?(e) corrector.insert_after(b, ' ') unless whitespace_after?(b) corrector.replace(b, 'do') + + if (comment = processed_source.comment_at_line(e.line)) + move_comment_before_block(corrector, comment, loc.node, e) + end + corrector.replace(e, 'end') end @@ -252,6 +258,15 @@ def whitespace_after?(range, length = 1) /\s/.match?(range.source_buffer.source[range.begin_pos + length, 1]) end + def move_comment_before_block(corrector, comment, block_node, closing_brace) + range = range_between(closing_brace.end_pos, comment.loc.expression.end_pos) + + corrector.remove(range_with_surrounding_space(range: range, side: :right)) + corrector.insert_after(closing_brace, "\n") + + corrector.insert_before(block_node, "#{comment.text}\n") + end + def get_blocks(node, &block) case node.type when :block diff --git a/spec/rubocop/cli/autocorrect_spec.rb b/spec/rubocop/cli/autocorrect_spec.rb index fc35d83767c..0ffc39c3100 100644 --- a/spec/rubocop/cli/autocorrect_spec.rb +++ b/spec/rubocop/cli/autocorrect_spec.rb @@ -196,6 +196,28 @@ def batch RUBY end + it 'corrects `EnforcedStyle: line_count_based` of `Style/BlockDelimiters` with `Style/CommentedKeyword` and `Layout/BlockEndNewline`' do + create_file('.rubocop.yml', <<~YAML) + Style/BlockDelimiters: + EnforcedStyle: line_count_based + YAML + source = <<~RUBY + foo { + bar } # This comment should be kept. + RUBY + create_file('example.rb', source) + expect(cli.run([ + '--auto-correct', + '--only', 'Style/BlockDelimiters,Style/CommentedKeyword,Layout/BlockEndNewline' + ])).to eq(0) + expect(File.read('example.rb')).to eq(<<~RUBY) + # This comment should be kept. + foo do + bar + end + RUBY + end + it 'corrects `EnforcedStyle: require_parentheses` of `Style/MethodCallWithArgsParentheses` with `Style/NestedParenthesizedCalls`' do create_file('.rubocop.yml', <<~YAML) Style/MethodCallWithArgsParentheses: diff --git a/spec/rubocop/cop/style/block_delimiters_spec.rb b/spec/rubocop/cop/style/block_delimiters_spec.rb index 9f74fb8954f..bc51589c65e 100644 --- a/spec/rubocop/cop/style/block_delimiters_spec.rb +++ b/spec/rubocop/cop/style/block_delimiters_spec.rb @@ -354,6 +354,35 @@ RUBY end + it 'registers an offense when there is a comment after the closing brace and block body is not empty' do + expect_offense(<<~RUBY) + baz.map { |x| + ^ Avoid using `{...}` for multi-line blocks. + foo(x) } # comment + RUBY + + expect_correction(<<~RUBY) + # comment + baz.map do |x| + foo(x) end + RUBY + end + + it 'registers an offense when there is a comment after the closing brace and block body is empty' do + expect_offense(<<~RUBY) + baz.map { |x| + ^ Avoid using `{...}` for multi-line blocks. + } # comment + + RUBY + + expect_correction(<<~RUBY) + # comment + baz.map do |x| + end + RUBY + end + it 'accepts braces if do-end would change the meaning' do expect_no_offenses(<<~RUBY) scope :foo, lambda { |f|