Skip to content

Commit

Permalink
Make Style/MethodCallWithoutArgsParentheses allow parenthesized it
Browse files Browse the repository at this point in the history
This PR makes `Style/MethodCallWithoutArgsParentheses` allow the parenthesized `it` method in a block.

It respects following Ruby 3.3's warning:

```console
$ ruby -e '0.times { begin; it; end }'
-e:1: warning: `it` calls without arguments will refer to the first block param in Ruby 3.4; use it() or self.it
```

Related PR ... #12518
  • Loading branch information
koic authored and bbatsov committed Dec 11, 2023
1 parent b240a09 commit 0daa4aa
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#12522](https://github.com/rubocop/rubocop/pull/12522): Make `Style/MethodCallWithoutArgsParentheses` allow the parenthesized `it` method in a block. ([@koic][])
20 changes: 20 additions & 0 deletions lib/rubocop/cop/style/method_call_without_args_parentheses.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ module Style
# This cop can be customized allowed methods with `AllowedMethods`.
# By default, there are no methods to allowed.
#
# NOTE: This cop allows the use of `it()` without arguments in blocks,
# as in `0.times { it() }`, following `Lint/ItWithoutArgumentsInBlock` cop.
#
# @example
# # bad
# object.some_method()
Expand All @@ -30,15 +33,18 @@ class MethodCallWithoutArgsParentheses < Base

MSG = 'Do not use parentheses for method calls with no arguments.'

# rubocop:disable Metrics/CyclomaticComplexity
def on_send(node)
return unless !node.arguments? && node.parenthesized?
return if ineligible_node?(node)
return if default_argument?(node)
return if allowed_method_name?(node.method_name)
return if same_name_assignment?(node)
return if parenthesized_it_method_in_block?(node)

register_offense(node)
end
# rubocop:enable Metrics/CyclomaticComplexity

private

Expand Down Expand Up @@ -71,6 +77,20 @@ def same_name_assignment?(node)
end
end

# Respects `Lint/ItWithoutArgumentsInBlock` cop and the following Ruby 3.3's warning:
#
# $ ruby -e '0.times { begin; it; end }'
# -e:1: warning: `it` calls without arguments will refer to the first block param in
# Ruby 3.4; use it() or self.it
#
def parenthesized_it_method_in_block?(node)
return false unless node.method?(:it)
return false unless (block_node = node.each_ancestor(:block).first)
return false unless block_node.arguments.empty_and_without_delimiters?

!node.receiver && node.arguments.empty? && !node.block_literal?
end

def any_assignment?(node)
node.each_ancestor(*AST::Node::ASSIGNMENTS).any? do |asgn_node|
# `obj.method = value` parses as (send ... :method= ...), and will
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,51 @@
expect_no_offenses('not(something)')
end

it 'does not register an offense when using `it()` in the single line block' do
# `Lint/ItWithoutArgumentsInBlock` respects for this syntax.
expect_no_offenses(<<~RUBY)
0.times { it() }
RUBY
end

it 'does not register an offense when using `it()` in the multiline block' do
# `Lint/ItWithoutArgumentsInBlock` respects for this syntax.
expect_no_offenses(<<~RUBY)
0.times do
it()
it = 1
it
end
RUBY
end

it 'registers an offense when using `it` without arguments in `def` body' do
expect_offense(<<~RUBY)
def foo
it()
^^ Do not use parentheses for method calls with no arguments.
end
RUBY
end

it 'registers an offense when using `it` without arguments in the block with empty block parameter' do
expect_offense(<<~RUBY)
0.times { ||
it()
^^ Do not use parentheses for method calls with no arguments.
}
RUBY
end

it 'registers an offense when using `it` without arguments in the block with useless block parameter' do
expect_offense(<<~RUBY)
0.times { |_n|
it()
^^ Do not use parentheses for method calls with no arguments.
}
RUBY
end

context 'when AllowedMethods is enabled' do
let(:cop_config) { { 'AllowedMethods' => %w[s] } }

Expand Down

0 comments on commit 0daa4aa

Please sign in to comment.