Skip to content

Commit

Permalink
Fix an incorrect auto-correct for Style/SingleLineMethods
Browse files Browse the repository at this point in the history
This PR fixes an incorrect auto-correct for `Style/SingleLineMethods`
when using `return`, `break`, or `next` for one line method body in Ruby 3.0.

These are not supported in the endless method definition.

```console
% ruby -v
ruby 3.0.1p64 (2021-04-05 revision 0fb782ee38) [x86_64-darwin19]

% cat example.rb
def foo(argument) break bar(argument); end
def foo(argument) next bar(argument); end
def foo(argument) return bar(argument); end

% ruby -c example.rb
Syntax OK

% bundle exec rubocop --only Style/SingleLineMethods -a
(snip)

Inspecting 1 file
C

Offenses:

example.rb:1:1: C: [Corrected] Style/SingleLineMethods: Avoid
single-line method definitions.
def foo(argument) break bar(argument); end
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
example.rb:2:1: C: [Corrected] Style/SingleLineMethods: Avoid
single-line method definitions.
def foo(argument) next bar(argument); end
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
example.rb:3:1: C: [Corrected] Style/SingleLineMethods: Avoid
single-line method definitions.
def foo(argument) return bar(argument); end
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

1 file inspected, 3 offenses detected, 3 offenses corrected

% cat example.rb
def foo(argument) = break bar(argument)
def foo(argument) = next bar(argument)
def foo(argument) = return bar(argument)

% ruby -ce 'def foo(argument) = break bar(argument)'
-e:1: syntax error, unexpected local variable or method, expecting
end-of-input
def foo(argument) = break bar(argument)

% ruby -ce 'def foo(argument) = next bar(argument)'
-e:1: syntax error, unexpected local variable or method, expecting
end-of-input
def foo(argument) = next bar(argument)

% ruby -ce 'def foo(argument) = return bar(argument)'
-e:1: syntax error, unexpected local variable or method, expecting
end-of-input
def foo(argument) = return bar(argument)
```
  • Loading branch information
koic authored and bbatsov committed Jul 6, 2021
1 parent cfdb0a1 commit ccdf562
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 6 deletions.
@@ -0,0 +1 @@
* [#9909](https://github.com/rubocop/rubocop/pull/9909): This PR fixes an incorrect auto-correct for `Style/SingleLineMethods` when using `return`, `break`, or `next` for one line method body in Ruby 3.0. ([@koic][])
17 changes: 11 additions & 6 deletions lib/rubocop/cop/style/single_line_methods.rb
Expand Up @@ -36,6 +36,7 @@ class SingleLineMethods < Base
extend AutoCorrector

MSG = 'Avoid single-line method definitions.'
NOT_SUPPORTED_ENDLESS_METHOD_BODY_TYPES = %i[return break next].freeze

def on_def(node)
return unless node.single_line?
Expand All @@ -62,13 +63,10 @@ def allow_empty?

def correct_to_endless?(body_node)
return false if target_ruby_version < 3.0

endless_method_config = config.for_cop('Style/EndlessMethod')

return false unless endless_method_config['Enabled']
return false if endless_method_config['EnforcedStyle'] == 'disallow'
return false if disallow_endless_method_style?
return false unless body_node
return false if body_node.parent.assignment_method?
return false if body_node.parent.assignment_method? ||
NOT_SUPPORTED_ENDLESS_METHOD_BODY_TYPES.include?(body_node.type)

!(body_node.begin_type? || body_node.kwbegin_type?)
end
Expand Down Expand Up @@ -129,6 +127,13 @@ def method_body_source(method_body)
def require_parentheses?(method_body)
method_body.send_type? && !method_body.arguments.empty? && !method_body.comparison_method?
end

def disallow_endless_method_style?
endless_method_config = config.for_cop('Style/EndlessMethod')
return false unless endless_method_config['Enabled']

endless_method_config['EnforcedStyle'] == 'disallow'
end
end
end
end
Expand Down
24 changes: 24 additions & 0 deletions spec/rubocop/cop/style/single_line_methods_spec.rb
Expand Up @@ -219,6 +219,30 @@ def #{op}(other) = self #{op} other
end
end

it 'does not to an endless class method definition when using `return`' do
expect_correction(<<~RUBY.strip, source: 'def foo(argument) return bar(argument); end')
def foo(argument)#{trailing_whitespace}
return bar(argument);#{trailing_whitespace}
end
RUBY
end

it 'does not to an endless class method definition when using `break`' do
expect_correction(<<~RUBY.strip, source: 'def foo(argument) break bar(argument); end')
def foo(argument)#{trailing_whitespace}
break bar(argument);#{trailing_whitespace}
end
RUBY
end

it 'does not to an endless class method definition when using `next`' do
expect_correction(<<~RUBY.strip, source: 'def foo(argument) next bar(argument); end')
def foo(argument)#{trailing_whitespace}
next bar(argument);#{trailing_whitespace}
end
RUBY
end

# NOTE: Setter method cannot be defined in the endless method definition.
it 'corrects to multiline method definition when defining setter method' do
expect_correction(<<~RUBY.chop, source: 'def foo=(foo) @foo = foo end')
Expand Down

0 comments on commit ccdf562

Please sign in to comment.