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 the following incorrect auto-correct for `Style/SingleLineMethods`
when defining setter method.

```console
% cat example.rb
def foo=(other) @foo == foo end

% 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=(other) @foo == foo end
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

1 file inspected, 1 offense detected, 1 offense corrected
```

### Before

Auto-corrected to invalid syntax because setter method cannot be defined in
an endless method definition.

```ruby
% cat example.rb
def foo=(other) = @foo == foo

% ruby -c example.rb
example.rb:1: setter method cannot be defined in an endless method definition
def foo=(other) = @foo == foo
```

### After

```ruby
% cat example.rb
def foo=(other)
  @foo == foo
end
```
  • Loading branch information
koic committed Apr 26, 2021
1 parent 2ee24df commit 16c0321
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 3 deletions.
@@ -0,0 +1 @@
* [#9740](https://github.com/rubocop/rubocop/pull/9740): Fix an incorrect auto-correct for `Style/SingleLineMethods` when defining setter method. ([@koic][])
11 changes: 8 additions & 3 deletions lib/rubocop/cop/style/single_line_methods.rb
Expand Up @@ -68,6 +68,7 @@ def correct_to_endless?(body_node)
return false unless endless_method_config['Enabled']
return false if endless_method_config['EnforcedStyle'] == 'disallow'
return false unless body_node
return false if body_node.parent.assignment_method?

!(body_node.begin_type? || body_node.kwbegin_type?)
end
Expand Down Expand Up @@ -115,15 +116,19 @@ def move_comment(node, corrector)
end

def method_body_source(method_body)
if !method_body.send_type? || method_body.arguments.empty? || method_body.parenthesized?
method_body.source
else
if require_parentheses?(method_body)
arguments_source = method_body.arguments.map(&:source).join(', ')
body_source = "#{method_body.method_name}(#{arguments_source})"

method_body.receiver ? "#{method_body.receiver.source}.#{body_source}" : body_source
else
method_body.source
end
end

def require_parentheses?(method_body)
method_body.send_type? && !method_body.arguments.empty? && !method_body.comparison_method?
end
end
end
end
Expand Down
17 changes: 17 additions & 0 deletions spec/rubocop/cop/style/single_line_methods_spec.rb
Expand Up @@ -211,6 +211,23 @@ def some_method() = body
RUBY
end

RuboCop::AST::Node::COMPARISON_OPERATORS.each do |op|
it "corrects to an endless class method definition when using #{op}" do
expect_correction(<<~RUBY.strip, source: "def #{op}(other) self #{op} other end")
def #{op}(other) = self #{op} other
RUBY
end
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')
def foo=(foo)#{trailing_whitespace}
@foo = foo#{trailing_whitespace}
end
RUBY
end

it 'corrects to a normal method if the method body contains multiple statements' do
expect_correction(<<~RUBY.strip, source: 'def some_method; foo; bar end')
def some_method;#{trailing_whitespace}
Expand Down

0 comments on commit 16c0321

Please sign in to comment.