Skip to content

Commit

Permalink
[Fix rubocop#9525] Add AllowMethodsWithArguments option to `Style/S…
Browse files Browse the repository at this point in the history
…ymbolProc`

## Summary

Fixes rubocop#9525.

This PR adds `AllowMethodsWithArguments` option to `Style/SymbolProc`.

### `AllowMethodsWithArguments: false` (default)

```ruby
# bad
something.do_something(foo) { |o| o.bar }

# good
something.do_something(foo, &:bar)
```

### `AllowMethodsWithArguments: true`

```ruby
# good
something.do_something(foo) { |o| o.bar }
```

If user prefer a style that allows block for method with arguments,
the user can set `true` to `AllowMethodsWithArguments`.

## Other Information

It may be possible to consider defaulting to `AllowMethodsWithArguments: true`,
but at the time of this patch `Style/SymbolProc` cop respect keeping the existing behavior.
  • Loading branch information
koic committed Feb 25, 2021
1 parent 8322f3a commit db955e3
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 9 deletions.
@@ -0,0 +1 @@
* [#9525](https://github.com/rubocop-hq/rubocop/issues/9525): Add `AllowMethodsWithArguments` option to `Style/SymbolProc`. ([@koic][])
1 change: 1 addition & 0 deletions config/default.yml
Expand Up @@ -4588,6 +4588,7 @@ Style/SymbolProc:
Safe: false
VersionAdded: '0.26'
VersionChanged: '1.5'
AllowMethodsWithArguments: false
# A list of method names to be ignored by the check.
# The names should be fairly unique, otherwise you'll end up ignoring lots of code.
IgnoredMethods:
Expand Down
19 changes: 19 additions & 0 deletions lib/rubocop/cop/style/symbol_proc.rb
Expand Up @@ -5,13 +5,27 @@ module Cop
module Style
# Use symbols as procs when possible.
#
# If you prefer a style that allows block for method with arguments,
# please set `true` to `AllowMethodsWithArguments`.
#
# @example
# # bad
# something.map { |s| s.upcase }
# something.map { _1.upcase }
#
# # good
# something.map(&:upcase)
#
# @example AllowMethodsWithArguments: false (default)
# # bad
# something.do_something(foo) { |o| o.bar }
#
# # good
# something.do_something(foo, &:bar)
#
# @example AllowMethodsWithArguments: true
# # good
# something.do_something(foo) { |o| o.bar }
class SymbolProc < Base
include RangeHelp
include IgnoredMethods
Expand Down Expand Up @@ -42,6 +56,7 @@ def on_block(node)
return if proc_node?(dispatch_node)
return if %i[lambda proc].include?(dispatch_node.method_name)
return if ignored_method?(dispatch_node.method_name)
return if allow_if_method_has_argument?(node)
return if node.block_type? && destructuring_block_argument?(arguments_node)

register_offense(node, method_name, dispatch_node.method_name)
Expand Down Expand Up @@ -103,6 +118,10 @@ def begin_pos_for_replacement(node)
node.loc.begin.begin_pos
end
end

def allow_if_method_has_argument?(node)
!!cop_config.fetch('AllowMethodsWithArguments', false) && !node.arguments.count.zero?
end
end
end
end
Expand Down
55 changes: 46 additions & 9 deletions spec/rubocop/cop/style/symbol_proc_spec.rb
Expand Up @@ -142,16 +142,53 @@
expect(&run).not_to raise_error
end

context 'when `super` has arguments' do
it 'registers an offense' do
expect_offense(<<~RUBY)
super(one, two) { |x| x.test }
^^^^^^^^^^^^^^ Pass `&:test` as an argument to `super` instead of a block.
RUBY
context 'when `AllowMethodsWithArguments: true`' do
let(:cop_config) { { 'AllowMethodsWithArguments' => true } }

context 'when method has arguments' do
it 'does not register an offense' do
expect_no_offenses(<<~RUBY)
do_something(one, two) { |x| x.test }
RUBY
end
end

expect_correction(<<~RUBY)
super(one, two, &:test)
RUBY
context 'when `super` has arguments' do
it 'does not register an offense' do
expect_no_offenses(<<~RUBY)
super(one, two) { |x| x.test }
RUBY
end
end
end

context 'when `AllowMethodsWithArguments: false`' do
let(:cop_config) { { 'AllowMethodsWithArguments' => false } }

context 'when method has arguments' do
it 'registers an offense' do
expect_offense(<<~RUBY)
do_something(one, two) { |x| x.test }
^^^^^^^^^^^^^^ Pass `&:test` as an argument to `do_something` instead of a block.
RUBY

expect_correction(<<~RUBY)
do_something(one, two, &:test)
RUBY
end
end

context 'when `super` has arguments' do
it 'registers an offense' do
expect_offense(<<~RUBY)
super(one, two) { |x| x.test }
^^^^^^^^^^^^^^ Pass `&:test` as an argument to `super` instead of a block.
RUBY

expect_correction(<<~RUBY)
super(one, two, &:test)
RUBY
end
end
end

Expand Down

0 comments on commit db955e3

Please sign in to comment.