Skip to content

Commit

Permalink
[Fix rubocop#12558] Fix an incorrect autocorrect for Style/MapToHash
Browse files Browse the repository at this point in the history
Fixes rubocop#12558.

This PR fixes an incorrect autocorrect for `Style/MapToHash`
when using `map.to_h` without receiver.
  • Loading branch information
koic committed Dec 20, 2023
1 parent 5af4bad commit 4cd79ed
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#12558](https://github.com/rubocop/rubocop/issues/12558): Fix an incorrect autocorrect for `Style/MapToHash` when using `map.to_h` without receiver. ([@koic][])
9 changes: 4 additions & 5 deletions lib/rubocop/cop/style/map_to_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ class MapToHash < Base
MSG = 'Pass a block to `to_h` instead of calling `%<method>s%<dot>sto_h`.'
RESTRICT_ON_SEND = %i[to_h].freeze

# @!method map_to_h?(node)
def_node_matcher :map_to_h?, <<~PATTERN
# @!method map_to_h(node)
def_node_matcher :map_to_h, <<~PATTERN
{
$(call ({block numblock} $(call _ {:map :collect}) ...) :to_h)
$(call $(call _ {:map :collect} (block_pass sym)) :to_h)
Expand All @@ -50,9 +50,9 @@ def self.autocorrect_incompatible_with
end

def on_send(node)
return unless (to_h_node, map_node = map_to_h?(node))
return unless (to_h_node, map_node = map_to_h(node))

message = format(MSG, method: map_node.loc.selector.source, dot: map_node.loc.dot.source)
message = format(MSG, method: map_node.loc.selector.source, dot: to_h_node.loc.dot.source)
add_offense(map_node.loc.selector, message: message) do |corrector|
# If the `to_h` call already has a block, do not autocorrect.
next if to_h_node.block_node
Expand All @@ -68,7 +68,6 @@ def autocorrect(corrector, to_h, map)
removal_range = range_between(to_h.loc.dot.begin_pos, to_h.loc.selector.end_pos)

corrector.remove(range_with_surrounding_space(removal_range, side: :left))
corrector.replace(map.loc.dot, '.') if to_h.dot?
corrector.replace(map.loc.selector, 'to_h')
end
end
Expand Down
17 changes: 15 additions & 2 deletions spec/rubocop/cop/style/map_to_hash_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@
end
end

context "for `#{method}.to_h` without receiver" do
it 'registers an offense and corrects' do
expect_offense(<<~RUBY, method: method)
#{method} { |x| [x, x * 2] }.to_h
^{method} Pass a block to `to_h` instead of calling `#{method}.to_h`.
RUBY

expect_correction(<<~RUBY)
to_h { |x| [x, x * 2] }
RUBY
end
end

context "for `#{method}&.to_h` with block arity 1" do
it 'registers an offense and corrects' do
expect_offense(<<~RUBY, method: method)
Expand All @@ -46,11 +59,11 @@
it 'registers an offense and corrects' do
expect_offense(<<~RUBY, method: method)
foo&.#{method} { |x| [x, x * 2] }.to_h
^{method} Pass a block to `to_h` instead of calling `#{method}&.to_h`.
^{method} Pass a block to `to_h` instead of calling `#{method}.to_h`.
RUBY

expect_correction(<<~RUBY)
foo.to_h { |x| [x, x * 2] }
foo&.to_h { |x| [x, x * 2] }
RUBY
end
end
Expand Down

0 comments on commit 4cd79ed

Please sign in to comment.