diff --git a/changelog/fix_incorrect_autocorrect_for_style_hash_transform_values.md b/changelog/fix_incorrect_autocorrect_for_style_hash_transform_values.md new file mode 100644 index 00000000000..217c35b0a0a --- /dev/null +++ b/changelog/fix_incorrect_autocorrect_for_style_hash_transform_values.md @@ -0,0 +1 @@ +* [#9940](https://github.com/rubocop/rubocop/issues/9940): Fix an incorrect auto-correct for `Style/HashTransformValues` when value is a hash literal for `_.to_h{...}`. ([@koic][]) diff --git a/lib/rubocop/cop/mixin/hash_transform_method.rb b/lib/rubocop/cop/mixin/hash_transform_method.rb index 099a0807044..68df99b76ba 100644 --- a/lib/rubocop/cop/mixin/hash_transform_method.rb +++ b/lib/rubocop/cop/mixin/hash_transform_method.rb @@ -175,7 +175,12 @@ def set_new_arg_name(transformed_argname, corrector) end def set_new_body_expression(transforming_body_expr, corrector) - corrector.replace(block_node.body, transforming_body_expr.loc.expression.source) + body_source = transforming_body_expr.loc.expression.source + if transforming_body_expr.hash_type? && !transforming_body_expr.braces? + body_source = "{ #{body_source} }" + end + + corrector.replace(block_node.body, body_source) end end end diff --git a/spec/rubocop/cop/style/hash_transform_values_spec.rb b/spec/rubocop/cop/style/hash_transform_values_spec.rb index 30bee15271f..0f3ec021226 100644 --- a/spec/rubocop/cop/style/hash_transform_values_spec.rb +++ b/spec/rubocop/cop/style/hash_transform_values_spec.rb @@ -211,6 +211,28 @@ RUBY end + it 'register and corrects an offense _.to_h{...} when value is a hash literal and is enclosed in braces' do + expect_offense(<<~RUBY) + {a: 1, b: 2}.to_h { |key, val| [key, { value: val }] } + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_values` over `to_h {...}`. + RUBY + + expect_correction(<<~RUBY) + {a: 1, b: 2}.transform_values { |val| { value: val } } + RUBY + end + + it 'register and corrects an offense _.to_h{...} when value is a hash literal and is not enclosed in braces' do + expect_offense(<<~RUBY) + {a: 1, b: 2}.to_h { |key, val| [key, value: val] } + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer `transform_values` over `to_h {...}`. + RUBY + + expect_correction(<<~RUBY) + {a: 1, b: 2}.transform_values { |val| { value: val } } + RUBY + end + it 'does not flag `_.to_h{...}` when both key & value are transformed' do expect_no_offenses(<<~RUBY) x.to_h { |k, v| [k.to_sym, foo(v)] }