Skip to content

Commit

Permalink
Add new Style/RedundantDoubleSplatBrackets cop
Browse files Browse the repository at this point in the history
This cop checks for redundant uses of double splat hash braces.

```ruby
# bad
do_something(**{foo: bar, baz: qux})

# good
do_something(foo: bar, baz: qux)
```

Both are keyword arguments after all.
  • Loading branch information
koic authored and bbatsov committed Dec 19, 2022
1 parent e41543d commit 0732939
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#11305](https://github.com/rubocop/rubocop/pull/11305): Add new `Style/RedundantDoubleSplatHashBraces` cop. ([@koic][])
5 changes: 5 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4744,6 +4744,11 @@ Style/RedundantConstantBase:
Enabled: pending
VersionAdded: '1.40'

Style/RedundantDoubleSplatHashBraces:
Description: 'Checks for redundant uses of double splat hash braces.'
Enabled: pending
VersionAdded: '<<next>>'

Style/RedundantEach:
Description: 'Checks for redundant `each`.'
Enabled: pending
Expand Down
1 change: 1 addition & 0 deletions lib/rubocop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@
require_relative 'rubocop/cop/style/operator_method_call'
require_relative 'rubocop/cop/style/redundant_assignment'
require_relative 'rubocop/cop/style/redundant_constant_base'
require_relative 'rubocop/cop/style/redundant_double_splat_hash_braces'
require_relative 'rubocop/cop/style/redundant_each'
require_relative 'rubocop/cop/style/redundant_fetch_block'
require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
Expand Down
39 changes: 39 additions & 0 deletions lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Style
# Checks for redundant uses of double splat hash braces.
#
# @example
#
# # bad
# do_something(**{foo: bar, baz: qux})
#
# # good
# do_something(foo: bar, baz: qux)
#
class RedundantDoubleSplatHashBraces < Base
extend AutoCorrector

MSG = 'Remove the redundant double splat and braces, use keyword arguments directly.'

# @!method double_splat_hash_braces?(node)
def_node_matcher :double_splat_hash_braces?, <<~PATTERN
(hash (kwsplat (hash ...)))
PATTERN

def on_hash(node)
return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)

grandparent = node.parent&.parent
return unless double_splat_hash_braces?(grandparent)

add_offense(grandparent) do |corrector|
corrector.replace(grandparent, node.pairs.map(&:source).join(', '))
end
end
end
end
end
end
56 changes: 56 additions & 0 deletions spec/rubocop/cop/style/redundant_double_splat_hash_braces_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Style::RedundantDoubleSplatHashBraces, :config do
it 'registers an offense when using double splat hash braces' do
expect_offense(<<~RUBY)
do_something(**{foo: bar, baz: qux})
^^^^^^^^^^^^^^^^^^^^^^ Remove the redundant double splat and braces, use keyword arguments directly.
RUBY

expect_correction(<<~RUBY)
do_something(foo: bar, baz: qux)
RUBY
end

it 'does not register an offense when using keyword arguments' do
expect_no_offenses(<<~RUBY)
do_something(foo: bar, baz: qux)
RUBY
end

it 'does not register an offense when using empty double splat hash braces arguments' do
expect_no_offenses(<<~RUBY)
do_something(**{})
RUBY
end

it 'does not register an offense when using hash rocket double splat hash braces arguments' do
expect_no_offenses(<<~RUBY)
do_something(**{foo => bar})
RUBY
end

it 'does not register an offense when using method call for double splat hash braces arguments' do
expect_no_offenses(<<~RUBY)
do_something(**{foo: bar}.merge(options))
RUBY
end

it 'does not register an offense when using hash braces arguments' do
expect_no_offenses(<<~RUBY)
do_something({foo: bar, baz: qux})
RUBY
end

it 'does not register an offense when using double splat variable' do
expect_no_offenses(<<~RUBY)
do_something(**h)
RUBY
end

it 'does not register an offense when using hash literal' do
expect_no_offenses(<<~RUBY)
{ a: a }
RUBY
end
end

0 comments on commit 0732939

Please sign in to comment.